Redis常见分布锁的原理和实现_Redis

来源:脚本之家  责任编辑:小易  
目录
前言基于数据库悲观锁实现原理具体实现乐观锁简介实现原理具体实现Redis实现分布式锁Zooker实现分布式锁加锁过程释放锁的过程异常场景分析具体实现Zookpeer实现分布式锁实现库存扣减总结

前言

Java中的锁主要包括synchronized锁和JUC包中的锁,这些锁都是针对单个JVM实例上的锁,对于分布式环境是无效的,那么基于分布式锁的如何实现呢?

常见的分布式锁的实现如下图:

基于数据库

悲观锁

悲观锁(Pessimistic Lock)顾名思义为很悲观的锁,每次在拿数据的时候都会上锁。这样别人想拿数据就被挡住,直到悲观锁被释放,悲观锁中的共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程,但是在效率方面,处理加锁的机制会产生额外的开销,且容易产生死锁。

实现原理

悲观并发控制实际上是"先取锁再访问"的保守策略,为数据处理的安全提供了保证.

具体实现

例如通过悲观锁来实现库存扣减的伪代码如下:

// 对于库存记录进行行锁

SELECT *FROM sys_goods s WHERE s.Id='1' FOR UPDATE;

//执行库存扣减
update sys_stock s set s.stockQty=s.stockQty-#{number} where s.goodId=1 and s.stockQty>0;

//提交事务,自动释放悲观锁。

乐观锁

简介

乐观锁是基于数据版本号(version)的机制来实现的。数据库表添加"version"字段, 读取出数据时,将此版本号读出,在更新过程中,会对版本号进行比较,如果是一致的,则会成功执行本次操作,且版本号加1,如果版本号不一致,则会更新失败。

实现原理

相对悲观锁,乐观锁的实现不会使用到数据库的锁机制,乐观锁的原理使用的CAS的机制来实现的,CAS(Compare-and-Swap)即比较并替换.

1、比较:读取到了一个值A,在将其更新为B之前,检查原值是否仍为A(未被其他线程改动).2、设置:如果是未发送变化,则将A更新为B结束。如果发生变化,则什么都不做。

具体实现

例如乐观锁来实现库存扣减的伪代码如下:

// 查询库存记录,获取版本号
SELECT stockQty,version FROM sys_goods s WHERE s.Id='1'

//执行库存扣减,防止出现超卖
update sys_stock s set 
  s.stockQty=s.stockQty-#{number},
  s.version=version+1
  where s.goodId=1 and s.stockQty>0 and version=#{version};

Redis实现分布式锁

关于Redis分布式锁的实现,已经在前期的文章中进行了讲解,大家可以参考如下文章

Spring Boot 实现Redis分布式锁原理

Spring Boot 集成Redisson实现分布式锁详细案例

Zooker实现分布式锁

Zookper实现分布式锁,主要是应用zookeeper节点的临时和有序性来实现。

加锁过程

当客户端1请求时,Zookeeper客户端会创建一个持久节点Locks节点,如果客户端1想获取锁,会在locks节点下创建临时节点/node_000000,如果查找Locks下面所有临时有序子节点,当自己为最小的节点是则获取锁成功。

当客户端2尝试获取锁时,也会查看locks下面的临时节点,判断自己的节点/node_000001是不是最小,如果不是最小则获取锁失败,客户端2会向它排序靠前的节点node_000000注册watch事件,用来监听node_000000是否存在,虽然抢锁失败,但是node_000001进入等待状态。

释放锁的过程

Zookeeper的客户端业务完成或者客户端发生故障,都会删除临时节点并且释放锁。如果是任务完成,客户端1还会显式调用删除node_000000的指令。

例如上述图,客户端1断开,临时节点node_000000已被删除,而此时node_000001通过watcher监听发现自己为为最小的临时节点,所以获取锁成功。

异常场景分析

客户端1创建临时节点后,会与Zookeeper服务器维护一个Session,这个Session会依赖客户端 定时心跳来维持连接。由于网路异常原因,Zookeeper长时间收不到客户端1的心跳,就认为这个Session过期了,也会把这个临时节点删除,此时客户端2创建临时节点能够获取锁成功。当客户端网络恢复正常后,它仍然认为持有锁,此时就会造成锁冲突。

具体实现

Zookeeper实现分布式锁,可以采用Curator实现分布式锁,关于SpringBoot如何集成Curator,大家可以参考如下文章:

Java Spring Boot 集成Zookeeper

Zookpeer实现分布式锁实现库存扣减

 @RequestMapping("/lockStock")
    public void lockStock()
    {
       zooKeeperUtil.lock("/Locks", 1000, TimeUnit.SECONDS, ()->{
           //业务逻辑
       });
    }

小结:

关于分布式锁的实现的对比,详情请查看下图:

总结

本文详细的介绍了几种分布式锁的实现和使用,业务需要根据场景选择合适的分布式锁的实现,如有疑问,请随时反馈。

到此这篇关于Redis常见分布锁的原理和实现的文章就介绍到这了,更多相关Redis分布锁原理内容请搜索真格学网以前的文章或继续浏览下面的相关文章希望大家以后多多支持真格学网!

您可能感兴趣的文章:详解Spring Cache使用Redisson分布式锁解决缓存击穿问题Redisson如何解决Redis分布式锁提前释放问题Redis实现分布式锁的五种方法详解redis分布式锁的8大坑总结梳理Redis分布式锁解决秒杀超卖问题Java实现redis分布式锁的三种方式Spring?Boot?集成Redisson实现分布式锁详细案例

  • 本文相关:
  • 详解centos7 yum安装redis及常用命令
  • centos6.4 安装redis 教程详解
  • redis集群搭建过程(非常详细,适合新手)
  • redis实现消息的发布订阅原理分析
  • redis+caffeine实现分布式二级缓存组件实战教程
  • redis的字符串是如何实现的
  • redis删除指定key的实现步骤
  • 面试常问:如何保证redis缓存和数据库的数据一致性
  • redis数据库的使用场景介绍(避免误用redis)
  • redis安装图文教程(windows和linux)
  • 分布式锁原理
  • 分布式锁用zookeeper还是redis好
  • redis或者缓存系统有批量删除的机制吗
  • Redis和Memcache的区别分析
  • 大数据专业主要学习什么语言?
  • Java基础的书有哪些比较好的?
  • 程序员如何做到在当今竞争激烈的市场中不被淘汰?
  • 课工场课程怎么样?
  • java自学需要多长时间?
  • java实习生刚去公司会做什么呢,要求有多高
  • linux下的 数据库 有哪些?
  • 网站首页网页制作脚本下载服务器操作系统网站运营平面设计媒体动画电脑基础硬件教程网络安全mssqlmysqlmariadboracledb2mssql2008mssql2005sqlitepostgresqlmongodbredisaccess数据库文摘数据库其它首页redisspring boot 实现redis分布式锁原理spring boot 集成redisson实现分布式锁详细案例java spring boot 集成zookeeper详解spring cache使用redisson分布式锁解决缓存击穿问题redisson如何解决redis分布式锁提前释放问题redis实现分布式锁的五种方法详解redis分布式锁的8大坑总结梳理redis分布式锁解决秒杀超卖问题java实现redis分布式锁的三种方式spring?boot?集成redisson实现分布式锁详细案例详解centos7 yum安装redis及常用命令centos6.4 安装redis 教程详解redis集群搭建过程(非常详细,适合新手)redis实现消息的发布订阅原理分析redis+caffeine实现分布式二级缓存组件实战教程redis的字符串是如何实现的redis删除指定key的实现步骤面试常问:如何保证redis缓存和数据库的数据一致性redis数据库的使用场景介绍(避免误用redis)redis安装图文教程(windows和linux)超强、超详细redis数据库入门教程redis常用命令、常见错误、配置技巧等分享redis操作命令总结redis中5种数据结构的使用场景介绍redis 密码设置和查看密码的方法64位windows下安装redis教程redis中使用redis-dump导出、导入、还原数据实例推荐几款 redis 可视化工具(太厉害了)redis中统计各种数据大小的方法redis常用命令小结浅谈redis整数集为什么不能降级redis?定长队列探索及实践查看redis内存信息的命令redis操作命令总结gem install redis报错的解决方案redis 2.8-4.0过期键优化过程全纪录redis密码设置与访问限制实现方法redis 单节点部署的实现antd为tree组件标题附加操作按钮功能redis与mongodb的区别总结
    免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved