背景
项目中有个场景是做数据分析,然后将目标数据保存在db,有个要求是将同类型的目标数据值保存一次,因此每次保存时需要判断之前是否已经存在了,由于qps较高,之前使用redis来缓存已经保存的数据,来抵挡对db的大部分流量,最近业务拓展同类型目标数据的qps可能超大(极限时达到20Wqps以上),此时由于在分布式场景下redis查询未加锁,可能多个线程同时查询redis得到的结果为并未保存,此时问题发生了,可能同时有多个线程执行保存到db操作,虽然db做了unique Key的限制,但担心到db qps过高导致被打挂,影响服务正常运行,因此准备使用redis分布式锁,来阻止此类事故的发生。
总结而言,我们担心的问题有以下特征:
- 分布式场景
- 流量qps 特高,redis不加锁可能直接击穿db
在分布式场景下,我们需要同类型数据保存操作在多个节点不会重复执行,因此需要使用redis分布式锁来实现。
下面我们先简单学习下分布式锁的概念以及如何在redis中实现:
分布式锁
我们参考Martin Kleppmann大佬(很牛的位大佬,有兴趣的同学可以了解下其跟redis之父Antirez关于RedLock(红锁,后续有讲到)是否安全的激烈讨论)的文章 How to do distributed locking 来理解redis锁。
文章地址:https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html
The purpose of a lock is to ensure that among several nodes that might try to do the same piece of work, only one actually does it (at least only one at a time)
分布式锁的作用在于在分布式场景下,当有多个服务结点尝试执行相同的任务,通过该锁确保实际只有1个结点执行。显然这样可以节省资源,避免重复执行,也能减少重复执行导致的错误,此处也涉及到分布式锁的两个特征场景:
- 效率:使用分布式锁避免不同节点执行重复的任务,导致资源浪费。
- 正确性;加分布式锁同样可以避免破