分布式锁选型+缓存db一致性

基于Redis Cluster模式

setnx就可以实现加锁,del实现解锁,但是这样不具备原子性,存在无法释放的可能。

因此可以使用在加锁时增加过期时间命令,做到原子性的加锁并且可以自动释放。

一些问题:

  • key的过期时间不能设置太长,避免其他线程阻塞
  • 可能出现误解锁,比如当前线程在锁期间没有完成,解锁时锁已经被别人占据,导致解掉别人的锁
  • 获取锁是非阻塞的,直接返回结果
  • 存在锁公平问题,需要自己实现

解决:

  • 守护线程对当前任务进度进行监控,及时续过期时间,知道锁释放或任务完成
  • 释放验证,释放时比对线程id和锁的value,防止释放不属于自己的锁
  • 阻塞机制,只能通过代码比如死循环去实现
  • 公平机制需要依赖等待队列来实现

可重入性需要自己开发,安全性方面可能丢失锁(redis主从复制)

可以了解一下基于多节点的高可用分布式锁的算法 RedLock。

缓存一致性问题解决讨论(增加思考能力)

加入缓存就不可避免的引入数据一致性的问题,所以在这里讨论,先说结论,我在项目上使用的是旁路缓存模式——

读策略:

从缓存中读取数据;如果缓存命中,则直接返回数据;如果缓存不命中,则从数据库中查询数据;查询到数据后,将数据写入到缓存中,并且返回给用户。

写策略:

更新数据库中(HBASE,Redis)的记录;删除缓存记录。

然后探讨一下各种模式的优缺点以及相应的解决方案。

再来对比一下几种策略:

一共分为四种

先更新数据库,再更新缓存
先更新数据库,再删除缓存
先更新缓存,再更新数据库
先删除缓存,再更新数据库

先更新数据库,再更新缓存

第一个问题是这个过程不具备原子性,可能存在

a改库
b改库
b更新缓存
a更新换粗

导致出现了更改丢失的情况,同时每次更新db都去更新缓存,如果是写多读少的情况下,无疑是浪费感情。

先更新数据库,再删除缓存

问题:

缓存失效
a去查数据库
b改库
b删缓存
a放置旧数据缓存

但是细想就会发现这个事情的概率比较低,因为并发的情况下,写库要比读库的耗时更长,正常情况下应该是b执行删缓存放到最后。

另外更新可以看做先删后加,删除就只有一步,相当于一个惰性处理,即懒加载的思想,只有用到的时候才去加在,因为缓存的成本是较高的,尽量需要保证会被访问到才缓存。

遗留问题,如果删缓存失败也会导致存在数据不一致问题,这种情况下可以依赖过期时间(缓存尽量不要设置为永久,如果能永久的我相信本地缓存或数据库更合适一些),允许一段时间的脏数据来达到最终一致性。

或者再引入一个中间件,删除缓存失败的时候入mq,随机时间后进行重试(不推荐,搞这么复杂还是别用缓存了)

先更新缓存,再更新数据库

同样属于双更模式,双更模式带来的不确定性比较大,并非原子操作,不推荐。

先删除缓存,再更新数据库

可能删完马上又有读请求过来查库读到了脏数据放入缓存中,毕竟读快于写,不推荐

  • 10
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值