缓存Bigkey坚决不要用,拆分是王道
大家好,我是架构摆渡人。这是实践经验系列的第四篇文章,这个系列会给大家分享很多在实际工作中有用的经验,如果有收获,还请分享给更多的朋友。
背景介绍
在高并发的业务场景中,缓存是必须要上的,用来扛高并发。在某个业务场景中,增加了对一个配置信息的缓存,最开始是直接读取DB的,为了性能考虑在前面加了一层缓存。
加完后很长一段时间也没问题,DB的压力也减小了很多。不幸的是在某天的一个时间点内,流量增加了好几倍,RT直线上升,接口各种超时,就这样,一个线上故障诞生了。
整个过程持续了1分钟左右,监控告警稍微有点延迟,刚看完监控告警,准备介入处理时流量已经跌下来了,接口也恢复了正常。
事后,通过监控发现接口超时的原因是因为底层Redis超时了,说到这可能大家都抱着怀疑的态度,Redis这么快也能超时?是的,你没看错,就是Redis超时了。
而Redis超时的原因并不是说Redis性能不行,而是在同一时刻有大量的请求访问了同一个Key,这个Key缓存的内容很大,导致一瞬间就把网络带宽给占用完了,后续请求都进不来。
解决方案
扩容带宽
直接扩容是最简单有效的方式,如果有持续的高流量造成了影响,紧急扩容是必须要走的,先解决当前问题。
等流量平稳后再考虑代码层面的改造,因为带宽也不是无限的,程序不处理好,始终是个风险点。
拆分BigKey
数据量大了,我们会分库分表。耦合严重了,我们会拆新的模块或者独立的服务。小组人多了,我们会拆分成多个组。遇到BigKey,那就是拆它拆它拆它。
假设这是你的缓存内容,里面是一个很大的Json字符串,存储的是配置信息:
{
"a":"....",
"b":"....",
"c":"...."
.........
}
那么可以把对象中的每个Key再拆分一次,作为一个独立的Key,这样它的Value就小了很多。不同的key会在集群中的不同节点上,也就不会出现集中访问某个节点,带宽不够的场景。

当然我这边说的是String类型,如果你的是List, Set这种,其实原理是一样的,同样是拆分成多个小的List, Key的前缀或者后缀不一样即可。
本地缓存
本地缓存,也是应对热点Key的常用解决方案。大家想想,一个固定的Key存储在Redis中,然后存储的内容也很大,访问量也比较高,带宽很容易成为瓶颈,因为要远程访问获取缓存内容。
如果将缓存存储在本地,那么就可以不用远程访问,从而带宽也就不会成为瓶颈。

如果用了本地缓存,相信很多读者第一想法就是一致性怎么维护,这个无论是在实际应用中还是面试中都是一个高频的问题。
还是得从业务场景触发,用缓存的场景肯定就是没有强一致性的要求,能够容忍短暂的不一致。所以在Redis缓存失效或者数据有变更的时候,本地缓存也需要同步清除。
一般都会采用消息广播的方式进行通知本地缓存失效,因为服务是集群部署的,每个节点上都有一份缓存数据,所以需要广播通知。

BigKey的治理
最后要进行BigKey的治理,梳理出来目前已有的BigKey,根据业务场景进行优化。同时在后续使用缓存的场景对缓存内容严格把关,防止出现类似的问题。
缓存Bigkey坚决不要用,拆分是王道的更多相关文章
- Hibernate缓存集成IMDG
1 第三方缓存插件 除了Ehcache这种轻量级的缓存方案外,几乎所有IMDG产品都提供了对Hibernate二级缓存的直接支持,常用的有: Ø Hazelcast Ø GridGain Ø J ...
- 详解Nacos 配置中心客户端配置缓存动态更新的源码实现
Nacos 作为配置中心,当应用程序去访问Nacos动态获取配置源之后,会缓存到本地内存以及磁盘中. 由于Nacos作为动态配置中心,意味着后续配置变更之后需要让所有相关的客户端感知,并更新本地内存! ...
- iOS企业级开发
2015移动技术白皮书 Android篇 iOS篇 项目管理篇 综合篇 结束语 iOS项目框架设计 项目结构的设计 基类的设计 自定义生命周期 跳转器 自定义UV打点控件 图片缓存 iOS网络底层框架 ...
- iOS WKWebView详解
UIWebView就不用说了,这个过时了,现在iOS8以后建议都使用WKWebView. WKWebView 是现代 WebKit API 在 iOS 8 和 OS X Yosemite 应用中的核心 ...
- [iOS开发]WKWebView加载JS
最近项目要用webView加载js文件,挺同事说WKWebView比UIWebView更加好用,于是我今天就试试,百度一发,自己写了个demo. 先看我写的代码,然后再来看WKWebView跟UIWe ...
- MySQL优化之表结构优化的5大建议(数据类型选择讲的很好)
殊不知,在N年前被奉为"圣经"的数据库设计3范式早就已经不完全适用了.这里我整理了一些比较常见的数据库表结构设计方面的优化技巧,希望对大家有用. 由于MySQL数据库是基于行(Ro ...
- 构建高并发&高可用&安全的IT系统-高并发部分
什么是高并发? 狭义来讲就是你的网站/软件同一时间能承受的用户数量有多少 相关指标有 并发数:对网站/软件同时发起的请求数,一般也可代表实际的用户 每秒响应时间:常指一次请求到系统正确响的时间(以秒为 ...
- Kafka对Java程序员有多重要?连阿里都再用它处理亿万级数据统计
一.了解淘宝Kafka架构 在ActiveMQ.RabbitMQ.RocketMQ.Kafka消息中间件之间,我们为什么要选择Kafka?下面详细介绍一下,2012年9月份我在支付宝做余额宝研发,20 ...
- 连阿里都在用它处理亿万级数据统计,论其对Java程序员的重要性!
一.了解淘宝Kafka架构 在ActiveMQ.RabbitMQ.RocketMQ.Kafka消息中间件之间,我们为什么要选择Kafka?下面详细介绍一下,2012年9月份我在支付宝做余额宝研发,20 ...
随机推荐
- 曼哈顿距离最小生成树 codechef Dragonstone
曼哈顿距离最小生成树 codechef Dragonstone 首先,对于每一个点来说有用的边只有它向它通过 x=0,y=0,y=x,y=-x 切出来的八个平面的最近点. 证明 我不会 反正当结论记住 ...
- CF1466G Song of the Sirens
题目传送门 题意简述:给出 \(n,s_0,t\ (n=|t|)\),定义 \(s_i=s_{i-1}+t_i+s_{i-1}\).多次询问给出 \(k,m\),求 \(m\) 在 \(s_k\) 中 ...
- .net与java建立WebService再互相调用
A: .net建立WebService,在java中调用. 1.在vs中新建web 简单修改一下Service.cs的[WebMethod]代码: using System; using System ...
- 『学了就忘』Linux文件系统管理 — 64、磁盘配额的配置步骤
目录 1.手工建立一个5GB的分区 2.建立需要做限制的三个用户 3.在分区上开启磁盘配额功能 4.建立磁盘配额的配置文件 5.开始设置用户和组的配额限制 6.启动和关闭配额 7.磁盘配额的查询 8. ...
- 学习java 7.6
学习内容: 方法重写注意事项:子类不能重写父类的私有方法 子类的访问权限不比父类的低(父类默认,子类可以是默认也可以是public) java中继承的注意事项:java中类只支持单继承,java中类支 ...
- 学习java 6.30
学习内容:Java的运算符与C中类似,虽是类似,还是有点区别,在这里详细说明一下,即字符以及字符串的+操作,字符的+操作执行后需要赋值给表达式中数据范围最大的类型, 字符串的+操作,当+中有字符串,则 ...
- Leetcode中的SQL题目练习(一)
595. Big Countries https://leetcode.com/problems/big-countries/description/ Description name contine ...
- Hadoop、Hive【LZO压缩配置和使用】
目录 一.编译 二.相关配置 三.为LZO文件创建索引 四.Hive为LZO文件建立索引 1.hive创建的lzo压缩的分区表 2.给.lzo压缩文件建立索引index 3.读取Lzo文件的注意事项( ...
- flink03-----1.Task的划分 2.共享资源槽 3.flink的容错
1. Task的划分 在flink中,划分task的依据是发生shuffle(也叫redistrubute),或者是并行度发生变化 1. wordcount为例 package cn._51doit ...
- 零基础学习java------38---------spring中关于通知类型的补充,springmvc,springmvc入门程序,访问保护资源,参数的绑定(简单数据类型,POJO,包装类),返回数据类型,三大组件,注解
一. 通知类型 spring aop通知(advice)分成五类: (1)前置通知[Before advice]:在连接点前面执行,前置通知不会影响连接点的执行,除非此处抛出异常. (2)正常返回通知 ...