Redis Implements distributed locks

Source: Internet
Author: User
Tags delete key zookeeper

Redis Implements distributed locks

In the cluster and other multi-server often to use to synchronize the business, then the ordinary transaction is to meet the needs of the business, the need for distributed locks. Distributed locks are implemented in a variety of ways, such as redis implementation of distributed locks, zookeeper implementation of distributed locks, the first realization of the Redis distributed lock.

Implementation principle

1, through SETNX (lock_timeout) implementation, if the lock is set to return 1, there is already a value has not been set to successfully return 0.

2, deadlock problem: Through time to determine whether expired, if it has expired, get to the expiration Time get (Lockkey), and then Getset (LOCK_TIMEOUT) to determine whether and get the same, the same proof has been locked successfully, Because it may cause multiple threads to execute the Getset (lock_timeout) method at the same time. This is likely to result in multiple threads having only getset after, for determining the lock successful thread, plus expire (Lockkey, lock_timeout, timeunit.milliseconds) expiration time, to prevent multiple threads simultaneously overlay time, Causes the lock aging time to double.

3, for the cluster server time inconsistency problem, you can get the current time from the call to Redis.

Code implementation Distributed Lock interface

Distributionlock.java

/** * 创建时间:2016年12月8日 下午6:51:51 *  * 分布式锁 *  * @author andy * @version 2.2 */publicinterface DistributionLock {    //加锁成功 返回加锁时间    publiclock(String lockKey, String threadname);    //解锁 需要更加加锁时间判断是否有权限    publicvoidunlocklong lockvalue, String threadname);}
Distributed-lock Redis implementation

Redisdistributionlock.java

Importjava.io.Serializable;ImportJava.util.concurrent.TimeUnit;ImportOrg.apache.log4j.Logger;ImportOrg.springframework.dao.DataAccessException;ImportOrg.springframework.data.redis.connection.RedisConnection;ImportOrg.springframework.data.redis.core.RedisCallback;ImportOrg.springframework.data.redis.core.RedisTemplate;ImportOrg.springframework.data.redis.serializer.JdkSerializationRedisSerializer;ImportOrg.andy.utils.SpringContextHolder;/** * Created: December 8, 2016 PM 5:44:16 * * Redis Distributed Lock * * @author Andy * @version 2.2 * * Public  class redisdistributionlock implements distributionlock{    Private Static Final LongLock_timeout = -* +;//Gartha time unit milliseconds means that the operation completes during the lock period if it is not completed there will be concurrency    Private Static FinalLogger LOG = Logger.getlogger (Redisdistributionlock.class);//redis Lock Log    @SuppressWarnings("Unchecked")Private StaticRedistemplate<serializable, serializable> redistemplate = (redistemplate<serializable, Serializable>) Springcontextholder. Getbean ("Redistemplate");/** * Take the lock and lock the lock and wait until the lock is acquired .    @Override     Public synchronizedLongLock(String Lockkey, String threadname) {Log.info (ThreadName +"Start lock-out"); while(true) {//Loop get lockLong lock_timeout = System.currenttimemillis () + Lock_timeout +1;//Lock Time            if(Redistemplate.execute (NewRediscallback<boolean> () {@Override                 PublicBooleanDoinredis(Redisconnection connection)throwsDataAccessException {Jdkserializationredisserializer Jdkserializer =NewJdkserializationredisserializer ();byte[] value = Jdkserializer.serialize (lock_timeout);returnConnection.setnx (Lockkey.getbytes (), value); }            })) {//If the lock succeedsLog.info (ThreadName +"Lock successfully ++++++++111111111"); Redistemplate.expire (Lockkey, Lock_timeout, timeunit.milliseconds);//Set timeout time, free memory                returnLock_timeout; }Else{Long currt_lock_timeout_str = (long) redistemplate.opsforvalue (). get (Lockkey);//Redis time                if(Currt_lock_timeout_str! =NULL&& Currt_lock_timeout_str < System.currenttimemillis ()) {//Lock has expired                    //To determine whether it is empty, not empty, the description has been invalidated, if the value is set by another thread, then the second condition is judged to be unable to executeLong old_lock_timeout_str = (long) redistemplate.opsforvalue (). Getandset (Lockkey, lock_timeout);//Get the last lock expiry time and set the current lock expiry time                    if(Old_lock_timeout_str! =NULL&& old_lock_timeout_str.equals (currt_lock_timeout_str)) {//If at this time, more than one thread is here, but only one thread has the same setting value as the current value, he has the right to acquire the lockLog.info (ThreadName +"Lock successfully +++++++2222222222"); Redistemplate.expire (Lockkey, Lock_timeout, timeunit.milliseconds);//Set timeout time, free memory                        returnLock_timeout;//Return lock time}                }            }Try{Log.info (ThreadName +"Wait for lock, sleep 100 milliseconds"); TimeUnit.MILLISECONDS.sleep ( -);//Sleep 100 ms}Catch(Interruptedexception e)            {E.printstacktrace (); }         }    }@Override     Public synchronized void Unlock(String Lockkey,LongLockvalue, String threadname) {log.info (ThreadName +"Perform unlock ==========");//Normal Direct Delete If the exception is closed and the lock will determine the expiration timeLong currt_lock_timeout_str = (long) redistemplate.opsforvalue (). get (Lockkey);//Redis time        if(Currt_lock_timeout_str! =NULL&& Currt_lock_timeout_str = = Lockvalue) {//If it is a lock, delete the lock if it is not, wait for auto-expiration to re-compete and lockRedistemplate.delete (Lockkey);//Delete keyLog.info (ThreadName +"Unlock successful-----------------"); }    }}

Note: The parameter ThreadName in the above interface is just for testing multi-threaded data printing, the build environment can remove the interface Distributionlock and implement string in class Redisdistributionlock The ThreadName parameter.

Multi-server takes the Redis time instead of all the current time System.currenttimemillis () used above.

publiclongcurrtTimeFromRedis//获取redis当前时间        return redisTemplate.execute(new RedisCallback<Long>() {            @Override            publicdoInRedisthrows DataAccessException {                return connection.time();            }        });    }
Simulation test test Code

Simulate 20 threads executing the business at the same time, acquiring resources.

@Test Public void Testredisdistributionlock(){ for(inti =0; I < -; i++) {NewThread (NewRunnable () {@Override Public void Run() {Task (Thread.CurrentThread (). GetName ());        }}). Start (); }Try{TimeUnit.MINUTES.sleep (1); }Catch(Interruptedexception e)        {E.printstacktrace (); }    }Private void Task(String name) {DistributionlockLock=NewRedisdistributionlock (); Long Locktime;//Locking time        if((Locktime =Lock.Lock(Rediskeyutil.distributed_lock_no +1, name))! =NULL) {//Start performing tasksSystem. out. println (name +"in Task execution");//Task execution complete close lock            Lock. Unlock (Rediskeyutil.distributed_lock_no +1, locktime, name); }    }
Test results

After locking, only one thread is guaranteed to get the current resource, releasing the lock and releasing the resource.

Have time to write about zookeeper implementing distributed locks

Redis Implements distributed locks

Related Article

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.