《分布式锁》原理与实现

hi,已经忘记多久没有写博客,现在正式回归! 今天要分享的是分布式锁的原理与实现;在系统软件开发过程中,很多时候我们会有一种这么一种场景: 我们有很多需要同时处理的任务,而这些任务执行过程中都需要去访问修改一个公共资源;如果每个线程都可以随意的去修改资源,那我们的公共资源的最终结果可能和我们预期的会不一致(例如:扣库存);此时我们就需要同一个时间,只能有一个线程访问修改公共资源;要实现这个功能,我们就需要用到锁;JDK 的JUC提供了很多相关的实现,如:synchronized,ReenreantLock等;但是,程序同时部署到多个服务器上时,我们就需要用到分布式锁。 针对分布式锁的实现,目前比较常用的有以下几种方案:

  • 1、数据库实现分布式锁:原理简单,性能较差
  • 2、redis实现的分布式锁:性能最好
  • 3、zookeeper实现的分布式锁:分布式锁:可靠性最好

一、基于数据库表 方法1:通过创建单独数据库表biz_lock

CREATE TABLE `biz_lock` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `biz_name` varchar(64) NOT NULL DEFAULT '' COMMENT '锁定的业务/资源',
  `remarks` varchar(1024) NOT NULL DEFAULT '备注信息',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '保存数据时间,自动生成',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uidx_biz_name` (`biz_name`) USING BTREE
)
 ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='锁定中的业务/资源';

使用方式:当我们要锁住某个方法或资源的时候,我们就在该表中增加一条记录,想要释放锁的时候就删除这条记录。

(1).获取锁
insert into biz_lock(biz_name,remarks) values ('resort_room_stock_operate','酒店房间库存操作')
(2).释放锁
delete from methodLock where biz_name ='biz_name'

方法2:基于数据库表做乐观锁

   常用的方法是为数据增加一个版本标识,每次修改记录的时候需要比对版本号是否一致;
(1).查询商品记录下本次操作前的version
     select (id,status,version) from t_goods_info where id=#{id}
(2).根据商品信息生成订单
(3).修改商品status为2
     update t_goods_info
     set status=2,version=version+1
     where id=#{id} and version=#{version};

方法3:数据库悲观锁 每次要操作前,先去数据库获取锁,然后做操作完成提交

select * from t_goods_info  where id = #{id}  for update

二、redis实现的分布式锁(大概有三种方式)

(1).jredis自己实现

a.【setnx】+命令实现分布式锁(set if not exist)
b.lua脚本实现redis分布式锁

(2).Redisson实现

RedissonLock、RedissonRedLock

三、zookeeper

(1)、使用zookeeper API根据节点监听和临时有序节点功能实现
(2)、Apache Curator
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章