Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the principle of distributed lock implementation?

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly explains "what is the principle of distributed lock implementation". The content of the explanation in this article is simple and clear, and it is easy to learn and understand. let's follow the editor's train of thought to study and learn "what is the principle of distributed lock implementation"!

Overview

At present, almost many large websites and applications are distributed, and the problem of data consistency in distributed scenarios has always been an important topic. Distributed CAP theory tells us that "no distributed system can satisfy Consistency, Availability and Partition tolerance at the same time, but only two at the same time." Therefore, many systems have to make a choice between these three at the beginning of their design. In the vast majority of scenarios in the Internet field, strong consistency needs to be sacrificed for high availability of the system, and systems often only need to ensure "ultimate consistency", as long as the final time is within the range acceptable to the user.

In many scenarios, in order to ensure the ultimate consistency of data, we need a lot of technical solutions to support, such as distributed transactions, distributed locks and so on.

Redis implements distributed Lock reason

Redis has high performance.

The Redis command supports this well and is easy to implement.

Use commands to introduce SETNXSETNX key val

If and only if key does not exist, set a string whose key is val and returns 1; if key exists, it does nothing and returns 0.

Expireexpire key timeout

Set a timeout for key in second, after which the lock will be automatically released to avoid deadlock.

Deletedelete key

Delete key, and these three commands are mainly used when using Redis to implement distributed locks.

The simple implementation uses jedis to connect to Redis. Realization thought

When acquiring a lock, use setnx to add a lock, and use the expire command to add a timeout for the lock, after which the lock is automatically released. The value of the lock is a randomly generated UUID, which can be judged when the lock is released.

When acquiring the lock, you also set a timeout for the acquisition, and if it exceeds this time, the acquisition lock is discarded.

When releasing the lock, the UUID determines whether it is the lock, if it is the lock, delete is executed to release the lock, or the lock time is set to 0.

The core code of the distributed lock is as follows: lock code import redis.clients.jedis.Jedis;import redis.clients.jedis.JedisPool;import redis.clients.jedis.Transaction;import redis.clients.jedis.exceptions.JedisException;import java.util.List;import java.util.UUID;public class DistributedLock {private final JedisPool jedisPool; public DistributedLock (JedisPool jedisPool) {this.jedisPool = jedisPool } / * * Lock * @ param locaName lock key * @ param acquireTimeout get timeout * @ param timeout lock timeout * @ return lock ID * / public String lockWithTimeout (String locaName, long acquireTimeout, long timeout) {Jedis conn = null; String retIdentifier = null Try {/ / get connection conn = jedisPool.getResource (); / / randomly generate a value String identifier = UUID.randomUUID () .toString (); / / lock name, that is, the key value String lockKey = "lock:" + locaName / / timeout, after which the lock is automatically released int lockExpire = (int) (timeout / 1000); / / the timeout of the lock is obtained. If the timeout is exceeded, the lock long end = System.currentTimeMillis () + acquireTimeout; while (System.currentTimeMillis ()) is abandoned

< end) { if (conn.setnx(lockKey, identifier) == 1) { conn.expire(lockKey, lockExpire); // 返回value值,用于释放锁时间确认 retIdentifier = identifier; return retIdentifier; } // 返回-1代表key没有设置超时时间,为key设置一个超时时间 if (conn.ttl(lockKey) == -1) { conn.expire(lockKey, lockExpire); } try { Thread.sleep(10); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } catch (JedisException e) { e.printStackTrace(); } finally { if (conn != null) { conn.close(); } } return retIdentifier; }解锁代码/** * 释放锁 * @param lockName 锁的key * @param identifier 释放锁的标识 * @return */ public boolean releaseLock(String lockName, String identifier) { Jedis conn = null; String lockKey = "lock:" + lockName; boolean retFlag = false; try { conn = jedisPool.getResource(); while (true) { // 监视lock,准备开始事务 conn.watch(lockKey); //通过前面返回的value值判断是不是该锁,若是该锁,则删除,释放锁 if (identifier.equals(conn.get(lockKey))) { Transaction transaction = conn.multi(); transaction.del(lockKey); List results = transaction.exec(); if (results == null) { continue; } retFlag = true; } conn.unwatch(); break; } } catch (JedisException e) { e.printStackTrace(); } finally { if (conn != null) { conn.close(); } } return retFlag; }} 解锁代码此部分最好采用原子性更好,性能更好的Lua的脚本去执行解锁删除锁的机制功能实现。 测试 下面就用一个简单的例子测试刚才实现的分布式锁。 例子中使用50个线程模拟秒杀一个商品,使用--运算符来实现商品减少,从结果有序性就可以看出是否为加锁状态。模拟秒杀服务,在其中配置了jedis线程池,在初始化的时候传给分布式锁,供其使用。 import redis.clients.jedis.JedisPool;import redis.clients.jedis.JedisPoolConfig;public class Service { private static JedisPool pool = null; static { JedisPoolConfig config = new JedisPoolConfig(); // 设置最大连接数 config.setMaxTotal(200); // 设置最大空闲数 config.setMaxIdle(8); // 设置最大等待时间 config.setMaxWaitMillis(1000 * 100); // 在borrow一个jedis实例时,是否需要验证,若为true,则所有jedis实例均是可用的 config.setTestOnBorrow(true); pool = new JedisPool(config, "127.0.0.1", 6379, 3000); } DistributedLock lock = new DistributedLock(pool); int n = 500; public void seckill() { // 返回锁的value值,供释放锁时候进行判断 String indentifier = lock.lockWithTimeout("resource", 5000, 1000); System.out.println(Thread.currentThread().getName() + "获得了锁"); System.out.println(--n); lock.releaseLock("resource", indentifier); }}// 模拟线程进行秒杀服务public class ThreadA extends Thread { private Service service; public ThreadA(Service service) { this.service = service; } @Override public void run() { service.seckill(); }}public class Test { public static void main(String[] args) { Service service = new Service(); for (int i = 0; i < 50; i++) { ThreadA threadA = new ThreadA(service); threadA.start(); } }} 结果如下,结果为有序的。 若注释掉使用锁的部分 public void seckill() { // 返回锁的value值,供释放锁时候进行判断 //String indentifier = lock.lockWithTimeout("resource", 5000, 1000); System.out.println(Thread.currentThread().getName() + "获得了锁"); System.out.println(--n); //lock.releaseLock("resource", indentifier);} 从结果可以看出,有一些是异步进行的。

In a distributed environment, it is sometimes important to lock resources, such as snapping up a resource, which can be well controlled by using distributed locks.

Of course, in the specific use, we also need to consider many factors, such as the selection of timeout time, the selection of acquisition lock time has a great impact on the concurrency, the above implementation of the distributed lock is only a simple implementation, mainly an idea.

Thank you for your reading. the above is the content of "what is the principle of distributed lock implementation". After the study of this article, I believe you have a deeper understanding of what is the principle of distributed lock implementation. the specific use also needs to be verified by practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report