Redis系列-生产应用篇-分布式锁(5)-单进程Redis分布式锁的Java实现(Redisson使用与底层实现)-原子锁类
Redisson單進程Redis分布式樂觀鎖的使用與實現
本文基于Redisson 3.7.5
4. 原子鎖類
Redisson中實現了兩種原子鎖類:RAtomicLong和RAtomicDouble,還有RLongAdder和RDoubleAdder
RAtomicDouble和RAtomicLong其實一樣的,RLongAdder和RDoubleAdder其實原理也是一樣的,這里我們只說RAtomicLong和RLongAdder。
4.1. RedissonAtomicLong - 基于Redis實現的原子Long類
原子類的incrementAndGet,decrementAndGet,addandGet,主要通過INCR,DECR,INCRBY,DECRBY實現,其實redis的這些操作本身就是原子性的。
@Override public RFuture<Long> getAndAddAsync(final long delta) {//getAndAdd通過INCRBY實現return commandExecutor.writeAsync(getName(), StringCodec.INSTANCE, new RedisStrictCommand<Long>("INCRBY", new SingleConvertor<Long>() {@Overridepublic Long convert(Object obj) {return ((Long) obj) - delta;}}), getName(), delta); } @Override public RFuture<Long> getAndSetAsync(long newValue) {//getAndSet通過GetSet實現return commandExecutor.writeAsync(getName(), LongCodec.INSTANCE, RedisCommands.GETSET, getName(), newValue); } @Override public RFuture<Long> incrementAndGetAsync() {//incrementAndGet通過INCR實現return commandExecutor.writeAsync(getName(), StringCodec.INSTANCE, RedisCommands.INCR, getName()); } @Override public RFuture<Long> decrementAndGetAsync() {//減一通過DECR實現return commandExecutor.writeAsync(getName(), StringCodec.INSTANCE, RedisCommands.DECR, getName()); }那么CAS更新呢?可以利用lua腳本的特性,也就是因為redis是單線程的,同時只能處理一個lua腳本,所以lua腳本具有原子性。
@Override public RFuture<Boolean> compareAndSetAsync(long expect, long update) {//CAS操作//通過lua腳本的特性實現,lua腳本的原子性//先檢查值是否符合,如果符合再更新,返回true,否則返回falsereturn commandExecutor.evalWriteAsync(getName(), StringCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,"local currValue = redis.call('get', KEYS[1]); "+ "if currValue == ARGV[1] "+ "or (tonumber(ARGV[1]) == 0 and currValue == false) then "+ "redis.call('set', KEYS[1], ARGV[2]); "+ "return 1 "+ "else "+ "return 0 "+ "end",Collections.<Object>singletonList(getName()), expect, update); }4.2. RedissonLongAdder 基于Redis實現的LongAdder
在統計場景下(寫多讀少,且數值不用考慮并發安全),LongAdder表現比AtomicLong更好,那么基于redis是怎么實現呢?
Redisson的實現思路比較簡單,本地留存一個longAdder,只有調用get或者sum的時候,才把本地的longAdder的數值加到redis中。
統計但不get的操作都是對于本地longAdder操作:
@Override public void add(long x) {counter.add(x); }@Override public void increment() {add(1L); }@Override public void decrement() {add(-1L); }與get還有sum相關的操作會把本地longAdder的數值加到redis中:
@Override protected RFuture<Long> addAndGetAsync() {return atomicLong.getAndAddAsync(counter.sum()); } @Override protected RFuture<Long> getAndDeleteAsync() {return atomicLong.getAndDeleteAsync(); } @Override public long sum() {return get(sumAsync()); }總結
以上是生活随笔為你收集整理的Redis系列-生产应用篇-分布式锁(5)-单进程Redis分布式锁的Java实现(Redisson使用与底层实现)-原子锁类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Zbrush基础《二》
- 下一篇: 激光SLAM | SuMa++:基于激光