当前位置:网站首页>How to encapsulate distributed locks more elegantly

How to encapsulate distributed locks more elegantly

2020-11-06 01:19:00 Yin Jihuan

Distributed locks usually have many choices , be based on Redis Of , be based on Zookeeper Of , Based on database and so on .

Redis For caching data , It's used in projects , So use Redis There will be a little more distributed locks .

If you use Redis To make a lock , You can use open source solutions directly , such as redisson.

The most common uses are as follows :

  
  1. RLock lock = redisson.getLock("anyLock");
  2. lock.lock();
  3. run();
  4. lock.unlock();

Get lock object , call lock() Lock , Execute business logic , call unlock() Release the lock .

Although the framework provides a very simple way to use it , But we still need to do a layer of packaging for the lock . The purpose of packaging is to improve scalability and ease of use .

Abstract interface

If we use it directly redisson The native API Make locks , So many places will appear RLock Related code , And then one day , For some reason , The lock needs to be replaced , At this time, the scope of change is relatively large . Each uses RLock Everything has to be changed .

Here's the picture : quite a lot Service Are used to RLock.lock() Method , When we need to replace locks , All the classes and methods involved have to be modified , The change points are shown in the red section .

 picture

So we need to do a layer of abstraction , You can define a DistributedLock Interface to provide lock related capabilities , Provides multiple implementations , This makes it easy to replace and expand .

Here's the picture : Every Service It's all for DistributedLock Interface to lock , When we need to replace the lock implementation , It doesn't need to be changed , Just replace DistributedLock The realization of .

 picture

Automatic release

Automatic release refers to after locking , After the execution of business logic, the lock needs to be closed automatically . In front of Redisson We need to manually call unlock() To release the lock held .

Of course Redisson It also provides the function of timeout release , Under normal circumstances, the lock must be released after the completion of business execution , The next request for the same lock can continue to be processed .

The most common problem with manually releasing resources is forgetting to release , So in JDK7 Introduced in try-with-resources To release resources automatically , I believe everyone is familiar with .

So when we encapsulate , Try not to let the user release it manually , Reduce the probability of error . For those with results, we can use Supplier To deliver your logic , For those that do not return results, you can use Runnable To deliver your logic .

  
  1. /**
  2. * Lock
  3. * @param key lock Key
  4. * @param waitTime Try to lock , Waiting time (ms)
  5. * @param leaseTime Failure time after locking (ms)
  6. * @param success The logic of successful lock execution
  7. * @param fail Logic of lock failure execution
  8. * @return
  9. */
  10. <T> T lock(String key, int waitTime, int leaseTime, Supplier<T> success, Supplier<T> fail);

Use :

  
  1. String result = distributedLock.lock("1001", 1000, () -> {
  2. System.out.println(" Came in ....");
  3. try {
  4. Thread.sleep(1000);
  5. } catch (InterruptedException e) {
  6. e.printStackTrace();
  7. }
  8. return "success";
  9. }, () -> {
  10. System.out.println(" Locking failed ....");
  11. return "fail";
  12. });

Disaster recovery

Another issue to note is the availability of locks , In case the corresponding Redis Something is wrong. , This time to lock is bound to fail , If nothing is done , It will affect normal business operations , Make the business unavailable .

In addition to realizing Redis Outside the lock of , Other locks can be implemented , Like database locks . When Redis When a lock is not available, it is demoted to a database lock , Although performance has an impact , But it doesn't affect the business .

 picture

If the database lock is not available ( Digression : It's very unlikely that everything will be available ), It's better to let business operations fail . Because we use the lock scene , It must be to prevent problems caused by concurrent scenarios , If the lock is not available , You're going to spend abnormally , Let business operations continue , There may be business problems without locking .

Of course, monitoring is also very necessary ,Redis, Database monitoring . When something goes wrong , There's a timely intervention .

Monitoring system

Redis, database ,Zookeeper The monitoring of these middleware supporting distributed implementation is definitely necessary . Another monitoring is the fine-grained monitoring of the lock action .

For example, the time to lock , Time to release lock , Time to execute business in a lock , Lock concurrency , Number of executions , The number of lock failures .

These data indicators are very important , It can help you find problems in time . such as 10 Hundreds of lock failures per second , All demoted to database locks , This is when you get an alert , It's easy to see Redis Something is wrong. , Timely solution .

The way of monitoring is just as casual , Every company is different , You can expose data to Prometheus Grab , You can also integrate Cat Do a good job , As long as you can monitor , Just give an alarm .

About author : Yin Jihuan , Simple technology enthusiasts ,《Spring Cloud Microservices - Full stack technology and case analysis 》, 《Spring Cloud Microservices introduction Actual combat and advanced 》 author , official account Ape world Originator .

I have compiled a complete set of learning materials , Those who are interested can search through wechat 「 Ape world 」, Reply key 「 Learning materials 」 Get what I've sorted out Spring Cloud,Spring Cloud Alibaba,Sharding-JDBC Sub database and sub table , Task scheduling framework XXL-JOB,MongoDB, Reptiles and other related information .

版权声明
本文为[Yin Jihuan]所创,转载请带上原文链接,感谢