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使用与底层实现)-原子锁类相关推荐

  1. Redis系列-第四篇持久化与事务

    一.持久化 Redis是一个内存数据库,为了保证数据的持久性,它提供了两种持久化方案: RDB方式(默认) AOF方式 持久化功能有效地避免因进程退出造成的数据丢失问题, 当下次重启时利用之前持久化的 ...

  2. 《Redis系列第三篇、incr与decr使用|CSDN创作打卡》

    incr与decr的效率要高于set操作,故而个人在开发过程中用作高并发的时候的限制器,效果非常nice的. 接下来看看具体用法与官方解释啊. incr自增·将存储的key数字加一 使用方法 incr ...

  3. Redis系列教程(八):分布式锁的由来、及Redis分布式锁的实现详解

    在很多场景中,我们为了保证数据的最终一致性,需要很多的技术方案来支持,比如分布式事务.分布式锁等.那具体什么是分布式锁,分布式锁应用在哪些业务场景.如何来实现分布式锁呢?今天来探讨分布式锁这个话题. ...

  4. Redis教程--redis分布式锁+企业解决方案+redis实战

    Redis,目前全国甚至是全球最常用的缓存中间件之一,在现在公司的开发中,可以说是离不开Redis. 在企业越来越注重用户体验的今天,Redis因具有高性能.高响应的特性,大大提升应用的响应速度和用户 ...

  5. Redis系列教程(五):Redis哨兵、复制、集群的设计原理,以及区别

    前一篇文章高并发架构系列:Redis为什么是单线程.及高并发快的3大原因详解谈了Redis高并发快的3个原因,本篇主要谈Redis的高可用,两篇合起来就可以把redis的高并发和高可用搞清楚了. 谈到 ...

  6. Redis系列教程(三):如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题

    Java相关的面试都会问到缓存的问题:史上最全Redis面试49题(含答案):哨兵+复制+事务+集群+持久化等,除此之外还会问到缓存雪崩.缓存穿透.缓存预热.缓存更新.缓存降级等不常见的问题,但却是非 ...

  7. Redis系列内容完整版

    文章目录 Redis系列之_Redis介绍安装配置 第一章 redis初识 1.1 Redis是什么 1.2 Redis特性(8个) 1.3 Redis单机安装 1.3.1下载安装 1.3.2三种启动 ...

  8. 2020年11个Redis系列高频面试题,哪些你还不会?

    前言 现在大家的工作生活基本已经是回归正轨了,最近也是迎来了跳槽面试季,有些人已经拿到了一两个offer了. 这段时间收集了阿里.腾讯.百度.京东.美团.字节跳动等公司的Java面试题,总结了Redi ...

  9. Redis系列教程(四):Redis为什么是单线程、及高并发快的3大原因详解

    Redis的高并发和快速原因 1.redis是基于内存的,内存的读写速度非常快: 2.redis是单线程的,省去了很多上下文切换线程的时间: 3.redis使用多路复用技术,可以处理并发的连接.非阻塞 ...

  10. Redis系列教程(七):Redis并发竞争key的解决方案详解

    Redis高并发的问题 Redis缓存的高性能有目共睹,应用的场景也是非常广泛,但是在高并发的场景下,也会出现问题: 高并发架构系列:Redis缓存和MySQL数据一致性方案详解 如何解决Redis缓 ...

最新文章

  1. python浪漫代码-使用Python代码的程序员也浪漫
  2. 2021.02.04 Visual QA论文阅读
  3. 热点的ap频段哪个快_WLAN中无线AP信道的划分
  4. 边际概率条件概率_数据科学家解释的边际联合和条件概率
  5. 程序员谈网络改变我们的生活
  6. Z-Stack Home Developer's Guide—6. Clusters, Commands and Attributes中文翻译【Z-Stack Home 1.2.0的开发文档】
  7. TensorFlow2.0(四)--Keras构建深度神经网络(DNN)
  8. 辞去程序员一职,我后悔了吗?
  9. webstrom默认是白色背景,如何修改
  10. JAVA访问控制权限
  11. dbt(data build tool) is an open source data transformation, and using Jinji templating
  12. windows搭建wordpress方法-windows搭建wordpress教程
  13. Word2007、Word2010、Word2013空格变成小点解决
  14. php图片留白,PHP:图片不变形处理(留白处理与截取处理)-奇乐网
  15. JAVA将日期类型(xx年xx月xx日)转化 成字符串变量
  16. 2022安全员-B证操作证考试题库及答案
  17. Delphi 把字符串复制到剪贴板
  18. java内存可视化_JVM系列(六)、可视化工具介绍
  19. vmm_xactor
  20. SpelResolverConfigurationOnMissingBean.spelResolver 找不到方法问题

热门文章

  1. mysql中获取时间的年月日_MySQL如何获取一个指定日期中的年份信息(YEAR函数)呢?...
  2. 关于电脑突然蓝屏后,重启idea报错HttpServlet不存在的问题
  3. bash ps1变量_Shell PS1变量:命令提示符设置
  4. ue字符编码_用ultraedit实现编码转换
  5. 重庆2021年高考二诊成绩查询,2021年重庆二诊,2021年4月重庆二诊考试,重庆二诊康德卷...
  6. 程序员面试注意几点就够了
  7. 新编计算机组装与维护教程,新编计算机组装与维护教程/21世纪高等学校计算机科学与技术规划教材...
  8. 最快下月!地表最强语言模型GPT-4发布在即?CEO暗示:已通过图灵测试
  9. matlab练习程序(图像放大/缩小,双线性插值)
  10. uniapp 日期时间 计算