分布式锁的一点看法

分布式锁的主流方案

基于数据库

 +	select for update。这个锁理论上没有超时能力,只能等客户端断开连接才行。所以实际上不能用于高并发&执行高耗时的场景。
 +	另外一种方案是仿照redis,在数据库里insert行。并设置唯一索引。这其实和redis锁的原理是一致的。

基于zookeeper

https://blog.csdn.net/define_us/article/details/79698940
zookeepr的锁其实和数据库是一样的问题。如果有临时节点的机器没有正确处理监听器逻辑。那么,整个锁就会被卡死。解决的办法也和redis锁一样。(本质上zk的znode也是一个key-value格式嘛)。机器会循环遍历,一旦发现自己的前序临时节点的前序临时节点已经删除。就在本地计时。在超时后,直接将该节点删除。唤醒本节点。但是zookeeper作为分布式锁的最大问题,是它仅保证最终一致性。你不能假设每台服务器都能从zookeeper看到相同的状态。
所以这种方案其实是不可行的。

基于redis

https://blog.csdn.net/define_us/article/details/79698408
可以说,redis的锁是唯一在大规模并发场景中可以使用的锁。

数据库和redis可以实现在不考虑超时的情况下实现严格的分布式锁。因为他们本身就是单点。但是,如果考虑超时,这个问题就无解了。没有一种考虑超时的分布式锁能够保证全局唯一执行。

所以,一个简单的办法是,redis作为第一层,数据库行锁作为第二层。为了克服数据库行锁没有超时时间的问题,
Spring事务提供了超时时间的配置

@Transactional(timeout=1)

但可惜,这个超时能力是spring计时器提供的。不是数据库本身提供的。可能会存在比如说获取行锁后展开大规模的GC,整个JVM被卡住。(但是数据库session不会超时,因为为了配合数据库连接池,一般数据库session超时配置到很大)。让然会造成整个系统卡住。

https://qingmiaogu.blog.csdn.net/article/details/80108576

其实,这样的问题出现的概率很低才对。第一层的redis锁已经把压力降下来了,第二层数据库操作却意外超时了。这简直是不可接受的。所以,我们需要努力在代码和系统配置容量上,避免上述出现的问题。这也其实是所有使用select for update的系统必须要考虑的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值