分布式锁
分布式锁的两个特性:
安全:互斥,针对同一资源只能同时有一个访问者
活性:避免死锁
活性:容错
简易分布式锁
SET resource_name my_random_value NX PX 30000
- 通过setNx来决定是否已经存在对应的key,也就是是否有client已经获取锁
- key的值是一个随机数,目的是:一个client误删除了另外一个client的锁,通过value的随机性避免此类问题
分布式锁的优化提升
举个例子,针对redis集群,clientA通过master节点获取了一个锁,在该锁还没有同步到slave时,master宕机了,clientB也同时获取了锁,这就违背了上面说的安全性中的互斥原则,那应该如何优化呢:红锁(RedLock)
- 是基于多节点集群模式
- 在总的失效时间一定比例的范围内获取锁
- 多数原则
缓存一致性策略
比较通用的策略主要有三种:
- cache aside 模式(常用)以单边的数据库为准
读:先读缓存,缓存没有数据后从库里读取,然后加载到缓存中
写:写数据库成功之后,删除缓存(异步补偿,有时序风险),通过上面的读来完成缓存加载
总结下来,该模式缓存只有写入和删除,没有更新操作
- write through/read through
读:缓存没有数据从库里读取,然后通过cache-provider同步加载到缓存
写:如果缓存中有数据则更新缓存,同时通过cache-provider同步到数据库
- write back
写:只同步写缓存,cache-provider择机异步更新
简易并发锁
SET resource_name 1 NX PX 30000
并发锁和分布式锁在key和失效时间有些不同,不需要设置随机值,同时失效时间根据并发具体场景设置
缓存雪崩
当积雪内部凝聚力抗拒不了重力拉引,雪体下滑,遭殃的是下游;同样,当缓存抵抗不了洪峰流量,流量下放,遭殃的是数据库,出现雪崩的场景包括:
- 缓存失效:对预热或缓存的过期时间上,在基础时间的基础上可以增加随机值,或关键缓存不失效
- 节点失效:集群部署
- 限流:这属于下策,迫不得已
缓存穿透
大量请求打过来时,缓存中 根本没有对应的key,导致请求直接透过缓存打到数据库上,解决方案:
- 缓存无效的key:比如新系统区域推广,很多配置都没有配置,大部分请求获取的都是空值,那我们就将空值缓存起来,时间不要太长
- 布隆过滤器:提前刷进去,并根据hash函数设置位数组对应下标的值为1,请求进来之后使用同样的hash函数读取下标值
缓存热点
类似于热搜等话题,很容易产生热key,而将洪峰流量达到一个节点,解决方案:
-
发现热点key。
-
通过将该key的后面拼上编号,比如
key#01
、key#02
。。。key#10
多个副本,hash后落到多个缓存节点上。