.NET面试题系列(14)分布式锁、接口幂等性、限流
序言
分布式锁
/// <summary> /// 分布式锁的类型 /// </summary> public enum DLockType { /// <summary> /// 基于数据库的分布式锁 /// </summary> DataBase, /// <summary> /// 基于Redis的分布式锁 /// </summary> Redis, /// <summary> /// 基于MemCache的分布式锁 /// </summary> MemCache, /// <summary> /// 基于本机的Mutex锁,仅允许同线程持有者释放。 /// </summary> Local, /// <summary> /// 基于本机文件的锁,允许其它进程或线程释放。 /// </summary> File }
C#中基于StackExchange.Redis的分布式锁
LockTake
LockRelease
接口幂等性
数据库的唯一约束,比如订单号,多次创建同一个订单号会违反唯一约束。
Redis SetNX命令
状态机 比如订单状态
去重表
悲观锁 for update
乐观锁 version
幂等性的使用场景
1、前端重复提交
就好比有个新增商品的功能,有个保存按钮
,如果前端连续多次点击保存,后端就会收到多次请求接口,如果没做好幂等就会重复创建了多条记录,
就会出现脏数据。
这个也就是我们所说的如何防止前端重复提交的问题。
2、接口超时重试
当我们调取第三方接口的时候,有可能会因为网络等原因导致调用失败,所以我们会对接口调用添加失败重试的机制,Spring可以通过@Retryable
注解实现重试机制。
既然重试就可能出现重复调用接口。这时再次调用时如果没有做好幂等,就可能出现脏数据。
3、消息重复消费
这个是无法避免的,因为我们说MQ在生产端和消费端都有重试机制,也就是同一消息很可能会被重复消费。
如果业务保证多次消费的结果是一样的那没问题,但是如果业务无法满足那就需要通过其它方式来保证消费端的幂等。
https://www.cnblogs.com/qdhxhz/p/16308097.html
https://www.cnblogs.com/QG-whz/p/10372458.html
https://www.cnblogs.com/jajian/p/10926681.html
限流
限流桶
其他
如何解决分布式锁超时问题
我们可以让获得锁的线程开启一个守护线程,用来给快要过期的锁“续航”
当过去了29秒,线程A还没执行完,这时候守护线程会执行expire指令,为这把锁“续命”20秒。守护线程从第29秒开始执行,每20秒执行一次。
当线程A执行完任务,会显式关掉守护线程。
另一种情况,如果节点1 忽然断电,由于线程A和守护线程在同一个进程,守护线程也会停下。这把锁到了超时的时候,没人给它续命,也就自动释放了。
代码实战
资料
https://blog.csdn.net/LongtengGensSupreme/article/details/104322232
https://www.cnblogs.com/axel10/p/9001800.html
https://www.bilibili.com/video/BV1vY411M7q9/?vd_source=a56db24cb8cab4dd8153f9a519787c89
c# redis 利用锁(StackExchange.Redis LockTake)来保证数据在高并发情况下的正确性
https://github.com/StackExchange/StackExchange.Redis.git
https://github.com/madelson/DistributedLock
https://github.com/cyq1162/Taurus.Idempotent
https://github.com/cyq1162/Taurus.DistributedLock
C:\Users\wangzl\Downloads\DistributedLock-master\src\DistributedLock.Tests
http://www.360doc.com/content/18/0528/08/36490684_757590223.shtml
https://www.cnblogs.com/qdhxhz/p/16308097.html