书号、书名、更新标识获取到的数量不一致_面试系列 redis 分布式锁&数据一致性...

分布式锁

63e7c9a79e23c687241115198dc1bf9d.png

多个系统同时操作一个redis,因为jvm锁是线程级别的,所以没有办法锁住多个系统。

Redis锁实现:

  • setnx key value 只有在key不存在时设置key的值
    • 此时key相当于锁的唯一标识,若key存在则会返回失败
  • EXPIRE key timeout 设置带过期时间的key,动态设置
    • 保证即使锁没有被显式释放,锁也可以在一定时间后自动释放,避免资源被永远锁住(万一拿到锁之后挂了就不会被显式释放)。

0dd341fe33438bf96aa2cf2239daf98e.png

SETNX 和 EXPIRE 非原子性

  • 如果 SETNX 成功,在设置锁超时时间后,服务器挂掉、重启或网络问题等,导致 EXPIRE 命令没有执行,锁没有设置超时时间变成死锁。
  • 使用 lua 脚本保证原子性

锁误解除

本质上就是redis自动删除锁和主动删除锁的重复冲突

如果线程 A 成功获取到了锁,并且设置了过期时间 30 秒,但线程 A 执行时间超过了 30 秒,锁过期自动释放,此时线程 B 获取到了锁;随后 A 执行完成,线程 A 使用 DEL 命令来释放锁,但此时线程 B 加的锁还没有执行完成,线程 A 实际释放的线程 B 加的锁。

  1. 在 value 中设置一个 UUID 标识当前线程
  2. 每次解锁前判断一下锁的value是否为当前线程的UUID
  3. 获取锁的value和删除锁通过Lua脚本变成原子操作

21b092a3a9b06c0cd712bf4fcda70d98.png

超时解锁导致并发

如果线程 A 成功获取锁并设置过期时间 30 秒,但线程 A 执行时间超过了 30 秒,锁过期自动释放,此时线程 B 获取到了锁,线程 A 和线程 B 并发执行。

解决方案:

  1. 将过期时间设置足够长,确保代码逻辑在锁释放之前能够执行完成。
  2. 为获取锁的线程增加守护线程,为将要过期但未释放的锁增加有效时间

3770ae0c55dcb37ea9617f70411f2bce.png
  • 保证锁不会自动过期自动删除,就算程序挂了,依然是有过期时间不会造成死锁。
  • 这个线程必须是主线程的守护线程,如果主线程挂了,定时任务也会挂了

锁等待

  • 可以通过客户端轮询的方式解决该问题,当未获取到锁时,等待一段时间重新获取锁,直到成功获取锁或等待超时。这种方式比较消耗服务器资源,当并发量比较大时,会影响服务器的效率。
  • 另一种方式是使用 Redis 的发布订阅功能,当获取锁失败时,订阅锁释放消息,获取锁成功后释放时,发送锁释放消息。

整理来源

分布式锁的实现之 redis 篇

《吊打面试官》系列-Redis终章_凛冬将至 FPX_新王登基

RedLock

基于 Redis 的分布式锁到底安全吗? 待整理

Redis与Mysql双写一致性方案解析

根据缓存是删除还是更新,以及操作顺序大概是可以分为下面四种情况

  1. 先更新数据库,再更新缓存
  2. 先更新缓存,再更新数据库
  3. 先删除缓存,再更新数据库
  4. 先更新数据库,再删除缓存

更新缓存 VS 删除缓存

  • 更新缓存的优点: 缓存不会增加一次Miss,命中率高
  • 删除缓存的优点: 操作简单,能防止更新出现的线程安全问题

通常场景下删除缓存操作简单,并且带来的副作用只是增加了一次Cache Miss,建议作为通用的处理方式,因为:

  • 更新缓存的代价可能很高,因为可能掺杂复杂的数据计算,而且频繁的更新缓存并不代表它会被频繁的访问到。举个栗子:一个缓存涉及的表的字段,在 1 分钟内就修改了 20 次,或者是 100 次,那么缓存更新 20 次、100 次;但是这个缓存在 1 分钟内只被读取了 1 次,有大量的冷数据
  • 删除缓存,而不是更新缓存,就是一个 Lazy 计算的思想,不要每次都重新做复杂的计算,不管它会不会用到,而是让它到需要被使用的时候再重新计算。

Redis与数据库一致性 | 笔记 详情

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值