Redis Implement distributed lock

Source: Internet
Author: User
Tags delete key redis zookeeper
Redis Implement distributed lock

In the cluster and other multiple servers often used 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 implementation of the Redis distributed locks. Implementation Principle

1, through SETNX (lock_timeout), if the lock is set to return 1, there is already a value does not set a successful return of 0.

2, deadlock problem: Through the time to determine whether the expiration, if it has expired, get to the expiration Time got (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 concurrently. This is likely to cause multiple threads to simply getset, to determine the lock success of the thread, plus expire (Lockkey, lock_timeout, timeunit.milliseconds) expiration time, prevent multiple threads simultaneously superimposed time, Lead to a doubling of the lock aging time.

3, for the cluster server time inconsistency problem, you can call Redis time () to get the current times. Code Implementation Distributed Lock Interface

Distributionlock.java

/**
 * Creation Date: December 8, 2016 PM 6:51:51 * * * 
 Distributed lock
 * * 
 @author Andy
 * @version
 2.2

/Public Interface Distributionlock {

    //Lock successfully returned lock time public
    long Lock (String lockkey, String threadname);

    Unlocking requires more locking time to determine whether there are permissions to public
    void unlock (String lockkey, Long Lockvalue, string threadname);
implementation of distributed lock Redis

Redisdistributionlock.java

Import java.io.Serializable;

Import Java.util.concurrent.TimeUnit;
Import Org.apache.log4j.Logger;
Import org.springframework.dao.DataAccessException;
Import org.springframework.data.redis.connection.RedisConnection;
Import Org.springframework.data.redis.core.RedisCallback;
Import Org.springframework.data.redis.core.RedisTemplate;

Import Org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;


Import Org.andy.utils.SpringContextHolder; /** * Creation Time: December 8, 2016 PM 5:44:16 * * Redis Distributed Lock * * @author Andy * @version 2.2/public class REDISDISTRIBUTIONL Ock implements distributionlock{private static final long lock_timeout = 60 * 1000;//Gartha time per unit millisecond means that the operation is performed within the lock period if it is not Completion will have concurrent phenomena private static final Logger LOG = Logger.getlogger (Redisdistributionlock.class); Redis Lock Log @SuppressWarnings ("unchecked") private static redistemplate<serializable, serializable> Redistem Plate = (redistemplate<serializable, serializable>) springcontextholder
            . Getbean ("Redistemplate"); /** * to lock and lock and wait until the lock is acquired/@Override public Long Lock (string lockkey, String threadname) {LOG
        . info (threadname + "Start the lock");  while (true) {//Loop fetch lock Long lock_timeout = System.currenttimemillis () + lock_timeout + 1;//Lock time if (Redistemplate.execute new rediscallback<boolean> () {@Override public Boolean DoI Nredis (redisconnection connection) throws DataAccessException {Jdkserializationredisserializer Jdkser
                    Ializer = new Jdkserializationredisserializer ();
                    byte[] Value = jdkserializer.serialize (lock_timeout);
                Return Connection.setnx (Lockkey.getbytes (), value);
                }) {//If the lock succeeds Log.info (ThreadName + lock successful ++++++++111111111); Redistemplate.expire (Lockkey, Lock_timeout, timeunit.milliseconds); Set timeout time, free memory return lock_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 is invalid If you decide whether it is null or empty, the description has been invalidated, and if the value is set by another thread, the second condition is that it cannot execute Long old_lock_timeout_str = (L
                    ONG) Redistemplate.opsforvalue (). Getandset (Lockkey, lock_timeout); Gets the last lock expiration time and sets the current lock expiration if (old_lock_timeout_str!= null && old_lock_timeout_str.equals (curr T_LOCK_TIMEOUT_STR)) {//As of this time, multiple threads happen to be here, but only one thread has the same set value as the current value, and he has the right to acquire the lock L
                        Og.info (ThreadName + "lock success +++++++2222222222"); Redistemplate.expire (Lockkey, Lock_timeout, timeunit.milliseconds);

            Set timeout time, free memory return lock_timeout;//back Lock Time}}
  try {              Log.info (threadname + "Wait for lock, sleep 100 milliseconds"); TimeUnit.MILLISECONDS.sleep (100);//Sleep 100 milliseconds} catch (Interruptedexception e) {E.printstacktrac
            E (); @Override public void Unlock (string lockkey, Long Lockvalue, string threadname) {LOG. Info (threadname + "perform unlock ==========");/normal direct deletion if an exception is closed, the lock determines the expiration time long currt_lock_timeout_str = (long) redistemplate. Opsforvalue (). get (Lockkey); Redis time if (currt_lock_timeout_str!= null && currt_lock_timeout_str = = Lockvalue) {//If lock is added, delete lock if is not waiting for automatic expiration of the re-competition lock Redistemplate.delete (Lockkey);
        Delete key Log.info (ThreadName + "unlock successful-----------------"); }
    }

}

Note: the above interface parameter ThreadName just to test the multithreading data printing, the generation environment can remove the interface Distributionlock and implement class Redisdistributionlock string ThreadName parameter.

Multiple servers take Redis time instead of all the current time System.currenttimemillis () used above.

Public long Currttimefromredis () {//Get Redis Current time return
        Redistemplate.execute (new rediscallback<long> () {
            @Override public
            Long Doinredis (redisconnection connection) throws DataAccessException {
                return Connection.time ();}}
        );
    
Simulation Test Test Code

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

@Test public
    void Testredisdistributionlock () {for
        (int i = 0; i < i++) {
            new Thread (new Runnable () {
   @Override public
                void Run () {
                    task (Thread.CurrentThread (). GetName ());
                }
            }). Start ();
        }

        try {
            TimeUnit.MINUTES.sleep (1);
        } catch (Interruptedexception e) {
            e.printstacktrace ()}
        }


    private void Task (String name) {
        Distributionlock lock = new Redisdistributionlock (); 
        Long Locktime; Lock Time
        if ((Locktime = Lock.lock (rediskeyutil.distributed_lock_no + 1, name))!= null) {
            //start Task
            SYSTEM.OUT.PRINTLN (name + "task Execution");
            Task execution closes lock
            lock.unlock (rediskeyutil.distributed_lock_no + 1, locktime, name);
        }
    
Test Results

Lock ensures that only one thread acquires the current resource and frees the resource after releasing the lock.

Have time to write zookeeper implement 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.