数据的使用
数据性质分类
- 静态数据
- 一般不变
- 类似于字典表
- 准静态数据
- 变化频率很低
- 部门结构、行政区划等
- 中间态数据
- 计算的可复用的中间态
- 配置中心的本地副本
动态数据
热数据
- 使用频率高
- 读写比较大,读的频率 >>> 写的频率
- 温数据
- 冷数据
-
缓存无处不在
内存可以看作CPU和磁盘的缓存
- CPU里也有L1 L2 L3 cache
- 网络,数据库引擎里的Buffer/Cache都可以看作是缓存
GUI的DoubleBuffer双缓冲是一个经典的性能优化方法
系统各级处理速度不一致
-
缓存加载时机
启动时全量缓存
- 全局有效
- 使用简单
- 服务启动时预热
懒加载
变动频率大、一致性要求高的数据不适合缓存
- 一致性要求高,意味只有使用原始数据,甚至加了事务,才是保险的
有效性
系统预热导致服务启动慢
系统内存资源耗尽
问题
- 并发问题,HashMap不是线程安全的
- 容量问题,一直put内存会爆
- 失效问题,如何管理过期失效
MyBatis/Hibernate框架的Cache
GuavaCache
SpringCache
本地缓存不足
- 如果缓存在本地,即部署10个服务,就要缓存10份,缓存的读写被放大
- 缓存数据一般都在堆内内存,总是会影响GC,每次GC都要扫描,但又不能被回收
-
远程缓存
Redis/Memcached缓存中间件
REmoteDIctionaryServer
- 开源的使用C编写的、支持网络
- 基于内存也可持久化的KV数据库
- https://redis.io
- http://redisbook.com
Memcached
- https://memcached.org
Hazelcast/Ignite内存网格
缓存策略
容量
- https://memcached.org
资源有限
FIFO/LRU
- 固定时间过期
-
常见问题
缓存穿透
问题
- 大量并发查询不存在的KEY,导致都直接将压力透传到数据库
- 如果系统使用的同步加载缓存,缓存不存在时就去查库则可能被利用,查询大量伪造的KEY,造成DDOS
- 分析
- 为什么会多次穿透?因为不存在KEY一直为空
- 需要注意让缓存能够区分KEY不存在还是值就是空值,避免恶性循环
解决
问题
- 当某个KEY失效时,正好有大量并发请求这个KEY
- 分析
- 和前面很像,属于比较偶然
解决
问题
- 某一时刻发生大规模的缓存失效,会有大量的请求直接打到数据库,导致数据库压力过大
- 服务没有滚动发布、定时任务同时启动去更新数据等都会造成雪崩
- 分析
- 一般由于更新策略、数据热点、服务宕机等原因导致大规模不可用
- 需要更新策略要在时间上合适、数据要均匀分布、缓存服务要多台高可用
- 解决
- 更新策略在时间上要比较均匀
- 使用的热点数据尽量分散到不同的机器
- 多台机器做主从复制或多副本,实现高可用
- 实现熔断、限流机制,对系统压力进行负载能力控制
