码迷,mamicode.com
首页 > 其他好文 > 详细

分布式锁

时间:2020-03-26 23:09:46      阅读:73      评论:0      收藏:0      [点我收藏+]

标签:key   获得   随机   height   没有   cal   系统   成本   midnight   

1)锁的概念

技术图片

 

同步方式:

  • 原子变量
  • volatile

锁的性能优化

  • 缩小锁的范围
  • 减小锁的粒度
  • 锁分段

锁的分类

  • 公平锁:synchronized, ReentrantLock
  • 非公平锁: ReentrantLock, CAS(自旋锁)
  • 独享锁: synchronized, ReentrantLock
  • 共享锁:Semaphore

2)分布式锁

  • 互斥性:在任意时刻只有一个客户端可以获取锁
  • 防死锁:即使有一个客户端持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁
  • 持锁人解锁:加锁与解锁必须为同一客户端,客户端自己不能把别人的加的锁给解开了
  • 可重入:当一个客户端获取对象锁后,这个客户端可以再次获取本对象上的锁

A. Redis分布式锁

1)加锁流程

技术图片

 

2)Redis分布式锁算法

a. 加锁:
  • setnx命令,set if not exists
  • 设置锁的有效时间防止死锁
  • 设置一个随机值用来标识锁的持有人
b. 解锁:
  • 检查是否持有锁
  • 删除锁
c. 使用lua脚本保证解锁操作的原子性
if redis.call("get", KEYS[1]) == ARGV[1]
then return redis.call("del", KEYS[1])
else return 0
end 

B. 基于数据库的分布式锁

1)实现方式

  • 新建一张锁表
  • 获取锁时插入一条数据
  • 解锁时删除数据

2)主要问题:

  • 可用性差,数据库挂掉会导致业务系统不可用,连接数量有限
  • 锁的失效时间难以控制,容易造成死锁
  • 非阻塞锁,未获得锁的线程需要需次出发获得锁操作
  • 非重入锁,同一个线程在没有释放锁之前无法再次获取该锁

C. 基于zk的分布式锁

1)实现方式:

每个客户端对某个方法加锁时,在zookeeper上的与该方法对应的指定节点的目录下,生成一个唯一的临时有序节点。判断是否获取锁的方式很简单,只需要判断有序节点中序号最小的一个。

当释放锁的时候,只需将这个临时节点删除即可。同时,其可以避免服务宕机导致的锁无法释放,而产生的死锁问题。

2)主要问题:

性能一般,加减锁的时候需要通过Leader创建或删除临时节点

D.  分布式锁比较

1)理解成本

数据库 > 缓存 > Zookeeper

2)复杂性

Zookeeper > 缓存 > 数据库

3)性能

缓存 > Zookeeper > 数据库

4)可靠性

Zookeeper > 缓存 > 数据库

3)幂等性

处理幂等性常用的方法

  • A. 生成全局唯一id(uuid),借助redis存储
  • B. 乐观锁机制(cas)
  • C. 悲观锁机制(for update)?
  • D. Token机制(类全局id)
  • E. 防重表(支付订单号,唯一索引)
  • F. 异步处理

分布式锁

标签:key   获得   随机   height   没有   cal   系统   成本   midnight   

原文地址:https://www.cnblogs.com/Terry-Wu/p/12578170.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!