Redis - Redis Distributed Lock

Redis Distributed Lock

What is a distributed lock Dian

  Ordinary lock for different threads within the same process at the same time operating resources, conflict resolution and plus, making single-threaded to multi-threaded execution order when operating the unified resource.

  JVM memory model :

 

 

  Main memory for variables, each thread has its own memory, in general, the thread in the present operation data memory, in memory brush White, if multiple threads simultaneously in the respective memory operation data, in the brush White memory, may lead to incorrect results. the main memory variable a = 1, the thread t1 and T2, while a read after adding a variable, the final brush into the main memory, the main memory may be a 2, the correct 3. If the result of the operation of a method of synchronization with the variable lock, t1 before adding to a 1, the brush into the main memory a = 2, then add a 1 t2 fishes, such as main memory 3 results.

  Because jvm memory model, each thread-local memory and the main memory variables are different, each thread local memory independent of each other, there is also the variable invisibility. Multi-threaded operation will be easy to go wrong

 

 

  In distributed systems deployed in different servers of different application services, then there is more than a process. Similar problems with the multi-threaded, multi-process operation when the same resources, you need to add synchronization lock up. But ordinary synchronization lock, only valid for multi-threading. to solve this problem, we need to use a distributed lock in the same process.

 

 

 Two Dian redis Distributed Lock

 

  redis distributed lock is achieved based on set key value px milliseconds nx command.

  Where value is a random value, usually with uuid achieve. Why do I need to set the expiration time? Is to prevent the lock to get the service, collapsed, can not normally release the lock, resulting in a deadlock. Redis by the need to remove the lock expired service.

  Generally divided into two steps to achieve

  1. lua script acquire the lock (atomicity guarantees) is equivalent to the set key value px milliseconds nx (key set does not exist)

local lockClientId = redis.call('GET', KEYS[1])
if lockClientId == ARGV[1] then
  redis.call('PEXPIRE', KEYS[1], ARGV[2])
  return true
elseif not lockClientId then
  redis.call('SET', KEYS[1], ARGV[1], 'PX', ARGV[2])
  return true
end
return false

 

  2. Use the lua script releases the lock

   If value is specified random value, indicating that the client gets to lock, you can delete the key, otherwise it will directly return 

if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end

 

 

 

 Wed and redis distributed lock usage scenarios

  Redis in stand-alone mode, when the service to acquire a lock, redis hung up, reboot, lock disappeared, and the service can be acquired b lock, service a and b can be performed simultaneously, z, and which is obviously designed contrary to the original intention.

  Stand-alone mode, single point of failure, then redis using trunked mode, master-slave synchronization is asynchronous, there is a delay. In extreme cases, a service node is acquired after the main lock, the lock case is not synchronized to the slave node, the master node hung up in the Sentinel mode, the upgrade from the master node node, service b can be acquired lock, time, and service a and b are executed simultaneously.

  In essence, distributed lock required on the same time, only one lock to get the service to meet the CP model CAP model, are strong consistency lock. Redis clusters for high availability appears, belongs AP model, so redis distributed lock is AP model. but why would anyone use redis distributed lock it? out of business architecture bullying. in the final consistency of the business, you can use the AP model lock, such as send a message, send a duplicate data , not so much in the strong consistency of the business, we need to use the CP model lock, such as financial services.

  Posted Gangster analysis conclusion, in addition to redis also provides another strong consistency lock - red locks Redlock , are interested can study on their own the following

 

 

 

 Four Dian redis support for distributed lock Spting provided

  1. introducing dependencies

        <dependency>
            <groupId>org.springframework.integration</groupId>
            <artifactId>spring-integration-redis</artifactId>
        </dependency>

 

   Second配置RedisLockRegistry

    @Bean("defaultRedisLockRegistry")
    public RedisLockRegistry defaultRedisLockRegistry(RedisConnectionFactory connectionFactory){
        //默认1分钟超时
        RedisLockRegistry lockRegistry=new RedisLockRegistry(connectionFactory,
                RedisKeyConfig.LOCK_DEFAULT_REGISTRY_KEY);
        return lockRegistry;
    }

 


  3. 简单使用与测试

@SpringBootTest
public class LockTests {
    @Autowired
    RedisLockRegistry defaultRedisLockRegistry;
    private final String lockKey ="test:lock:key";

    @Autowired
    RedisManager<String,String> stringRedisManager;

    @Test
    public void shouldLock(){

        //1分钟超时
        Lock lock=defaultRedisLockRegistry.obtain(lockKey);
        boolean locked=lock.tryLock();
        if(!locked){
            return;
        }

        //获取到锁
        String lockRedisKey=RedisKeyConfig.LOCK_DEFAULT_REGISTRY_KEY+":"+lockKey;
        try {
            //一般在try{}中写业务逻辑, 报错时, finally中可以释放锁
            String clientId=stringRedisManager.get(lockRedisKey);
            Assert.state(clientId!=null && clientId.length()>0, "没有获取到redis锁");
            System.out.println("获取到redis锁(clientId:"+clientId+")");


        }catch (Exception e){
            throw new RuntimeException(e);
        }finally {
            //释放锁, 有可能之前锁已超时,被清除, 然后报错
            lock.unlock();
        }


        String clientId=stringRedisManager.get(lockRedisKey);
        Assert.state(clientId==null, "锁没有被正常释放");

    }



}

 

   完整源码

 

 

学习资料:

  官方文档  

   基于CAP模型设计企业级真正高可用的分布式锁

Guess you like

Origin www.cnblogs.com/timfruit/p/12147039.html