缓存的本质
1:操作系统的磁盘性能很差,才会有更加昂贵的,同时速度更加快的缓存模块,就是用钱换时间。
2:合理的使用缓存可以极大的提高系统性能
缓存中的数据
1:静态数据
2:变化很低的数据
3:一些计算的中间数据。
总之都是一些 读>写 的数据,可以通过 命中率 和 读写比 指标来衡量,可以通过日志记录,来收集指标数据。
缓存数据的加载时刻
1:全量启动加载
2:懒加载
3:异步加载,就是客户端的线程只从缓存哪里取数据,取不到就取不到了,然后后端有个异步线程进行从数据库更新到缓存中。
使用不当带来的问题
1:内存被耗尽,没有合理的缓存失效机制
2:应用启动的时候会比较慢
缓存框架
1:hashMap
2: guava cache:https://guava.dev/releases/21.0/api/docs/com/google/common/cache/Cache.html
3: spring cache : https://docs.spring.io/spring-framework/docs/4.3.x/spring-framework-reference/html/cache.html
4: redis ,memcache
缓存过期策略
1:FIFO,LUR
2: 定期时间过期
3:业务加权过期 例如 3+5x
缓存穿透
问题:大量并发查询不存在的KEY,导致都直接将压力透传到数据库。分析:为什么会多次透传呢?不存在一直为空。需要注意让缓存能够区分KEY不存在和查询到一个空值。
解决办法:
1、缓存空值的KEY,这样第一次不存在也会被加载会记录,下次拿到有这个KEY。
2、Bloom过滤(https://zhuanlan.zhihu.com/p/43263751)或RoaringBitmap 判断KEY是否存在。
3、完全以缓存为准,使用 延迟异步加载 的策略2,这样就不会触发更
缓存击穿
问题:某个KEY失效的时候,正好有大量并发请求访问这个KEY。
分析:跟前面一个其实很像,属于比较偶然的。
解决办法:
1、KEY的更新操作添加全局互斥锁。
2、完全以缓存为准,使用 延迟异步加载 的策略2,这样就不会触发更新
缓存雪崩问题
当某一时刻发生大规模的缓存失效的情况,会有大量的请求进来直接打到数据库,导致数据库压力过大升值宕机。
分析:一般来说,由于更新策略、或者数据热点、缓存服务宕机等原因,可能会导致缓存数据同一个时间点大规模不可用,或者都更新。所以,需要我们的更新策略要在时间上合适,数据要均匀分散,缓存服务器要多台高可用。
解决办法:
1、更新策略在时间上做到比较均匀。
2、使用的热数据尽量分散到不同的机器上。
3、多台机器做主从复制或者多副本,实现高可用。
4、实现熔断限流机制,对系统进行负载能力控制
Redis
性能测试:https://redis.io/topics/benchmarks
基本数据结构
备注:所有的数据类型都会被一个hash桶里面,所以储存数据量很大的话 会导致数据冲突,所以会导致rehash,redis为了优化,实现分配了两个hash桶,默认刚开始只用一个,但是后面会hash冲突很严重的时候会对第二个hash桶进行扩容,然后在逐渐移动过去。是渐进式的。
字符串:: 简单动态字符串,二进制安全的
简单来说,二进制安全就是,字符串不是根据某种特殊的标志来解析的,无论输入是什么,总能保证输出是处理的原始输入而不是根据某种特殊格式来处理
typedef char *sds;
struct sdshdr {
// buf 已占用长度
int len;
// buf 剩余可用长度
int free;
// 实际保存字符串数据的地方
char buf[];
};
操作:set/get/getset/del/exists/appendincr/decr/incrby/decrby
List
1:按照插入顺序排序的字符串链表
2:
基本数据的使用场景
线程模型
持久化机制
高可用
数据分片
//todo