日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Redis系列-生产应用篇-分布式锁(5)-单进程Redis分布式锁的Java实现(Redisson使用与底层实现)-原子锁类

發布時間:2023/12/20 java 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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中。

public class RedissonLongAdder extends RedissonBaseAdder<Long> implements RLongAdder {//利用RAtomicLong實現redis中保存的數值private final RAtomicLong atomicLong;//本地longAdderprivate final LongAdder counter = new LongAdder(); }

統計但不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使用与底层实现)-原子锁类的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。