How do I manipulate Redis and zookeeper to implement distributed locking

  • 2020-05-24 06:26:29
  • OfStack

How do I manipulate Redis and zookeeper to implement distributed locking

In a distributed scenario, there are many situations where final 1 tropism needs to be implemented. Events in the field of design of the remote context, in order to ensure the consistency in the end, in the way of communication through the field events, can be Shared storage (domain model and the persistence of data sources), or to do global XA transaction (two-phase commit, the data source can be separated), can also use the message middleware (consumers need to be able to power, etc.). Publishing domain events in Observer mode provides high concurrency, and the event store can trace event data to a smaller level of granularity, giving each application more autonomy.

1. Distributed locks

Distributed locks are generally used in distributed systems or multiple applications to control whether the same task is executed or in what order. In the project, multiple tomcat applications have been deployed. When executing the timed task, the same task may be executed many times. We can ensure that only one tomcat application executes the timed task at the same time with the help of distributed locking.

2. Implementation of distributed locks

setnx() and expire() using redis getset() using redis Create node node using zookeeper Create temporary sequence nodes using zookeeper's

3. Use setnx() and expire() of redis to implement distributed locking


setnx(key,value)  if key Does not exist, set to current key The value of value; if key Exists, returns directly. 
expire() To set the timeout 

Define the annotation class:


@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Lockable{
  // redis The cache key
  String key();
  // redis The cache key The data in the 
  String value() default "";
  //  Expiration time ( seconds ) By default, 1 minutes 
  long expire() default 60;
}

Scheduled tasks added annotation @Lockable:


 @Lockable(key = "DistributedLock:dealExpireRecords")
 public void dealExpireRecords() {
 }

Define one aop section, LockAspect, and use @Around to handle all annotations @Lockable. Confirm that this annotation is used on the method through the join point. Get the annotation information through the method, and use setIfAbsent to judge whether to acquire the distributed lock. If a distributed lock is acquired, set the expiration time through expire and call the specified method.


@Component
@Slf4j
@Aspect
public class LockAspect {

  @Autowired
  private RedisTemplate redisTemplate;

  @Around("@annotation(com.records.aop.Lockable)")
  public Object distributeLock(ProceedingJoinPoint pjp) {
    Object resultObject = null;

    // Make sure this annotation is used on the method 
    Signature signature = pjp.getSignature();
    if (!(signature instanceof MethodSignature)) {
      log.error("Lockable is method annotation!");
      return resultObject;
    }

    MethodSignature methodSignature = (MethodSignature) signature;
    Method targetMethod = methodSignature.getMethod();

    // Get annotation information 
    Lockable lockable = targetMethod.getAnnotation(Lockable.class);
    String key = lockable.key();
    String value = lockable.value();
    long expire = lockable.expire();

    //  Distributed locks without this key , set this value and return true ; If you have this key , the return false
    boolean result = redisTemplate.boundValueOps(key).setIfAbsent(value);
    if (!result) {
      // Other programs have acquired distributed locks 
      return resultObject;
    }

    // Set expiration time, default 1 minutes 
    redisTemplate.boundValueOps(key).expire(expire, TimeUnit.SECONDS);

    try {
      resultObject = pjp.proceed(); // Call the corresponding method to execute 
    } catch (Throwable throwable) {
      throwable.printStackTrace();
    }
    return resultObject;
  }
}

4. Use redis's getset() to implement distributed locking

This method makes the redisTemplate.boundValueOps (key).getAndSet (value) method, if it returns null, to indicate that the distributed lock has been acquired; If the return is not empty, the distributed lock has been occupied by another program

5. Create node node using zookeeper

Use zookeeper to create the node node. If the node is successfully created, the distributed lock is acquired. If the node creation fails, it means that the distributed lock has been occupied by other programs (multiple programs create 1 node node at the same time, only 1 can be successfully created)

6. Create temporary sequence nodes using zookeeper

Use zookeeper node to implement distributed lock, create a temporary sequence is suitable for the sequential program, general idea is to create a temporary sequence nodes, find out the minimum sequence nodes, access to distributed lock, after completion of the program execution sequence nodes will disappear, to monitor the change of the nodes by watch, find the smallest sequence from the rest of the node, the access to distributed lock, to perform the corresponding processing, and so forth...

Thank you for reading, I hope to help you, thank you for your support of this site!


Related articles: