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

How to implement ​ distributed Lock based on redis

2025-03-10 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)05/31 Report--

< 0 ) return -1; else return 0; } return 0; } @Override public long getDelay(TimeUnit unit) { long d = unit.convert(cleartime - System.currentTimeMillis(), TimeUnit.MILLISECONDS); return d; } } /***使用Redis实现的分布式锁*基本工作原理如下:*1. 使用setnx(key,时间戮+超时),如果设置成功,则直接拿到锁*2. 如果设置不成功,获取key的值v1(它的到期时间戮),跟当前时间对比,看是否已经超时*3. 如果超时(说明拿到锁的结点已经挂掉),v2=getset(key,时间戮+超时+1),判断v2是否等于v1,如果相等,加锁成功,否则加锁失败,等过段时间再重试(200MS)*/public class RedisLock implements LockListener{ private String key; private boolean owner = false; private AbstractLockObserver observer = null; private LockListener lockListener = null; private boolean waiting = false; private long expire;//锁超时时间,以秒为单位 private boolean expired = false; public RedisLock(String key, LockListener lockListener, AbstractLockObserver observer) { this.key = key; this.lockListener = lockListener; this.observer = observer; } public boolean trylock(long expire) { synchronized(this){ if(owner){ return true; } this.expire = expire; this.expired = false; if(!waiting){ owner = observer.tryLock(key,expire); if(!owner){ waiting = true; observer.addLockListener(key, this); } } return owner; } } public boolean isOwner() { return owner; } public void unlock() { synchronized(this){ observer.unLock(key); owner = false; } } public void clear() { synchronized(this){ if(waiting) { observer.removeLockListener(key); waiting = false; } } } public boolean doExpire(){ synchronized(this){ if(owner) return true; if(expired) return false; expired = true; clear(); } return false; } @Override public void lockAcquired() { synchronized(this){ if(expired){ unlock(); return; } owner = true; waiting = false; } lockListener.lockAcquired(); } @Override public long getExpire() { return this.expire; } @Override public void lockError() { synchronized(this){ owner = false; waiting = false; lockListener.lockError(); } }} public class LockObserver extends AbstractLockObserver implements Runnable{ private CacheRedisClient client; private Object mutex = new Object(); private Map lockMap = new ConcurrentHashMap(); private boolean stoped = false; private long interval = 500; private boolean terminated = false; private CountDownLatch doneSignal = new CountDownLatch(1); public LockObserver(String schema){ client = new CacheRedisClient(schema); SystemExitListener.addTerminateListener(new ExitHandler(){ public void run() { stoped = true; try { doneSignal.await(); } catch (InterruptedException e) { } } }); } public void addLockListener(String key,LockListener listener){ if(terminated){ listener.lockError(); return; } synchronized(mutex){ lockMap.put(key, listener); } } public void removeLockListener(String key){ synchronized(mutex){ lockMap.remove(key); } } @Override public void run() { while(!terminated){ long p1 = System.currentTimeMillis(); Map clone = new HashMap(); synchronized(mutex){ clone.putAll(lockMap); } Set keyset = clone.keySet(); if(keyset.size() >

0) {ConnectionFactory.setSingleConnectionPerThread (keyset.size ()); for (String key: keyset) {LockListener ll = clone.get (key) Try {if (tryLock (key,ll.getExpire () {ll.lockAcquired (); removeLockListener (key) }} catch (Exception e) {ll.lockError (); removeLockListener (key) }} ConnectionFactory.releaseThreadConnection ();} else {if (stoped) {terminated = true DoneSignal.countDown (); return;}} try {long p2 = System.currentTimeMillis () Long cost = p2-p1; if (cost ex) {Long old = client.getSet (key, new Long (ne+1)) If (old==null | | (ex = = null&&old==null) | | (exex.equals (old)) {return true;} return false } public void unLock (String key) {client.del (key);}}

The distributed lock implemented by this scheme can perfectly solve the problem of lock reentry, and the problem of deadlock can be avoided by introducing timeout. In terms of performance, the author's self-test results are as follows:

500 threads tps = 35000

[root@DB1 benchtest-util] # target/benchtest/bin/TestFastRedis / data/config/util/config_0_11.properties lock 500 500000

Total thread time: 6553466; average: 13.106932

Actual total time: 13609; average: 0.027218

The TPS reached 35000, a full order of magnitude better than that of option 1.

This is the end of the content of "how to implement distributed locks based on redis". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

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

Servers

Wechat

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

12
Report