Concurrent writes of Redis

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

The first thing to clarify is the fact that the redis server is a single-threaded client request, which means that the client request is serialized on the server side, so there is no concurrency problem on the server side. But the business side has the redis same situation in concurrent operations key . So how to let the A client know that the B client is manipulating what it wants to do is key a problem that must be discussed.

So let's start by summarizing the following scenario:

1. SETNX key value      //key存在就不做任何操作,返回0;不存在操作成功返回1

This approach key guarantees the serialization of concurrent operations by adding locks to the required operations. Here we take Golang The example of code to illustrate the operation. Look at multiple co-processes to write key the same situation first. The code is as follows:

Package Mainimport ("FMT" "Github.com/garyburd/redigo/redis" "Runtime" "Sync" "Time") var w sync. Waitgroupfunc newrdspool (server, auth string) *redis. Pool {return &redis. pool{maxidle:100, maxactive:30, idletimeout:60 * time. Second, Dial:func () (Redis. Conn, error) {c, err: = Redis.                Dial ("TCP", server) if err! = Nil {return nil, err} if auth = = "" { Return C, Err} If _, Err: = C.do ("AUTH", AUTH);        Err! = Nil {c.close () return nil, err} return C, err}, Testonborrow:func (c Redis. Conn, T time. Time) Error {_, Err: = C.do ("PING") return err},}}func G1 (R redis. Conn) {for i: = 0; i < 2; i++ {If _, err: = Redis. String (R.do ("Set", "Hello", "1")); Err! = Nil {fmt. PRINTLN (ERR)} time. Sleep (TimE.millisecond)} w.done ()}func G2 (R Redis). Conn) {for i: = 0; i < 2; i++ {If _, err: = Redis. String (R.do ("Set", "Hello", "2")); Err! = Nil {fmt. PRINTLN (ERR)} time. Sleep (Ten * Time.millisecond)} w.done ()}func main () {W.add (2) runtime. Gomaxprocs (runtime. NUMCPU ()) var RC1 redis. Conn = Newrdspool (' 127.0.0.1:6379 ', '). Get () var rc2 redis. Conn = Newrdspool (' 127.0.0.1:6379 ', '). Get () defer RC1. Close () defer RC2. Close () Go G1 (RC1) go G2 (RC2) w.wait ()}

After the

Executes the above code, the value of Hello hovers between 1 and 2. The hope is that if the co-process 1 is in operation, the process 2 will discard the operation, that is, let the operation serialization. This requires a lock to ensure that two simultaneous processes cannot be in the critical section at the same time. setnx = Set if not exists does not exist return 1, there is a return of 0. This mechanism allows you to determine whether the current lock is already set. lock must give an expiration time because it is likely that goroutine1 appears panic at do work , which results in Goroutine2 has been trying to acquire a lock.

Package Mainimport ("FMT" "Github.com/garyburd/redigo/redis" "Runtime" "Sync" "Time") var w sync. Waitgroupfunc newrdspool (server, auth string) *redis. Pool {return &redis. pool{maxidle:100, maxactive:30, idletimeout:60 * time. Second, Dial:func () (Redis. Conn, error) {c, err: = Redis.                Dial ("TCP", server) if err! = Nil {return nil, err} if auth = = "" { Return C, Err} If _, Err: = C.do ("AUTH", AUTH);        Err! = Nil {c.close () return nil, err} return C, err}, Testonborrow:func (c Redis. Conn, T time. Time) Error {_, Err: = C.do ("PING") return err},}}func G1 (R redis.        Conn) {var lock int64 var lock_timeout int64 = 2 var lock_time int64 var now int64 for Lock! = 1 { now = time. Now (). Unix () Lock_time = Now + lock_Timeout lock, err1: = Redis. Int64 (R.do ("Setnx", "foo", Lock_time)) lockValue1, err2: = Redis. Int64 (R.do ("Get", "foo")) if lock = = 1 && err1 = = Nil {break} else {if now > lockValue1 && err2 = = Nil {lockValue2, err3: = Redis.                    Int64 (R.do ("Getset", "foo", Lock_time)) If Err3 = nil && now > lockValue2 { Break} else {fmt. Println (' G1 not get lock ') time. Sleep (Time.millisecond)}} else {fmt. Println (' G1 not get lock ') time. Sleep (Time.millisecond)}}} for I: = 0; I < 5; i++ {If _, err: = Redis. String (R.do ("Set", "Hello", "1")); Err! = Nil {fmt. PRINTLN (Err)} FMT. Println (' G1 now work ... ') time. Sleep (1 * time. Second)} if time. Now (). Unix () < Lock_time {if_, Err4: = Redis. Int64 (R.do ("Del", "foo")); Err4! = Nil {fmt. Println (ERR4)}} w.done ()}func G2 (R redis.        Conn) {var lock int64 var lock_timeout int64 = 2 var lock_time int64 var now int64 for Lock! = 1 { now = time. Now (). Unix () Lock_time = now + lock_timeout lock, err1: = Redis. Int64 (R.do ("Setnx", "foo", Lock_time)) lockValue1, err2: = Redis. Int64 (R.do ("Get", "foo")) if lock = = 1 && err1 = = Nil {break} else {if now > lockValue1 && err2 = = Nil {lockValue2, err3: = Redis.                    Int64 (R.do ("Getset", "foo", Lock_time)) If Err3 = nil && now > lockValue2 { Break} else {fmt. Println (' G2 not get lock ') time. Sleep (Time.millisecond)}} else {fmt. Println (' G2 not get lock ') time. Sleep (Time.millisEcond)}}} for I: = 0; I < 5; i++ {If _, err: = Redis. String (R.do ("Set", "Hello", "2")); Err! = Nil {fmt. PRINTLN (Err)} FMT. Println (' G2 now work ... ') time. Sleep (1 * time. Second)} if time. Now (). Unix () < Lock_time {if _, Err4: = Redis. Int64 (R.do ("Del", "foo")); Err4! = Nil {fmt. Println (ERR4)}} w.done ()}func main () {W.add (2) runtime. Gomaxprocs (runtime. NUMCPU ()) var RC1 redis. Conn = Newrdspool (' 127.0.0.1:6379 ', '). Get () var rc2 redis. Conn = Newrdspool (' 127.0.0.1:6379 ', '). Get () defer RC1. Close () defer RC2. Close () Go G1 (RC1) go G2 (RC2) w.wait ()}

The above code gives the goroutine same effect as two through the lock to achieve serialization operation key .

2.  MULTI、DISCARD、 EXEC、WATCH    
3. 将对key的操作的值都放到一个list里面

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.