分享下使用分布式缓存和本地缓存的一些设计和问题:
1.什么样的数据,场景需要用到缓存?
数据:访问频率高,修改频率低,比如我们系统的供应商信息,商品标签等等
场景:高并发,时效性强,比如用户下单,批量结算等
2.用什么数据结构保存缓存呢?
简单的数据类型直接String,如果是复杂对象hash
3.如何发现哪些key是热点key?
热点key肯定会有超高访问导致带宽不够的问题,怎么发现呢?
1.个人经验,比如要上线一个秒杀抢购的功能,那是不是参与的商品都是热点呢?
2.有一些热点key没办法判断,需要根据程序运行一段时间才知道,这种可以借助于redis4的redis-cli --hotkeys功能,
但是要注意淘汰策略要改为allkeys-lfu或者volatile-lfu
4.热点key问题怎么解决呢?
1.打散热点key,分散热点key到不同的集群节点,此处要分析redis slot算法:对每个key计算CRC16值,然后对16384取模
2.如何一个节点的一个key访问都很高的话怎么办?通过本地缓存guava来优化,但是要考虑到缓存不一致的问题。暂时没有什么好的方案(1:我们是定时任务从库里取更新本地和redis,会有延迟;2:修改时发布消息通知各个服务更新本地缓存),欢迎指教,因为不一致问题所以本地缓存保存的必须是改动很少的key
5.缓存不一致问题怎么解决?
缓存双删:修改数据库时先删除缓存,再更新数据库,再删除缓存。简单分析下:先删除缓存是为了防止修改数据成功,但是删除缓存失败导致不一致,最后再删除缓存时防止再改库的时候其他线程修改了缓存导致不一致
6.缓存雪崩怎么办?
大量缓存同时失效,热点key失效等访问全打到了DB情况;有几种方案:
1.添加缓存操作时进行加锁
2.请求入队列(比较麻烦,所有热点访问都入队列?)
3.热点key不设置失效
7.缓存穿透怎么办?
访问的数据缓存和数据库都不存在
方案:1.针对不存在数据访问找不到设置特定值过期时间;2,bitmap拦截恶意访问;