Redis
1.redis 常见数据类型,应用场景, 底层实现
String 微博数量 基于sds
Hash 存储的对象,例如商品信息
List 微博粉丝列表
Set 共同关注 去重
Zset 弹幕消息 去重后有序
Bitmap:布隆过滤器(false is always false)
Hyperloglog:不精确的去重计数功能 - 统计网站月活
Geospatial:地理位置,附近的人,最优地图路径
2.redis事务
只有一致性和隔离性,
不具有原子性的原因:redis同一个事务中,如果一条命名执行失败,剩下的会继续执行,不会回滚
持久性:开启持久化模式(rdb和aof后)
Rdb:把当前内存数据以快照形式写入磁盘,实际操作是通过fork子进程执行,采用二进制压缩存储。 适合用来灾备 --缺点是快照保存完成之前宕机,这段时间数据将丢失,保存快照时可能导致服务短时间不可用
Aof: 以文本日志记录redis处理的每一个写入或删除操作,有追加模式,灵活的同步策略,支持每秒同步,每次修改同步和不同步,--缺点 效率低于rdb
**注:不管是rdb还是aof都无法完全保证redis数据不丢失!! **
3.缓存击穿,缓存穿透,缓存雪崩概念和解决方案?
1.缓存击穿:某个key失效时,有大量并发请求访问该key
解决方案:key的操作添加全局互斥锁
使用:在缓存失效时(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(Redis的SETNX)去set一个mutex key.当操作返回成功时,再load db的操作并回设缓存;否则,就重试整个get缓存的方法
2.缓存穿透:大量并发查询不存在的key,直接访问到数据库。
解决方案
1.缓存空值的KEY,这样第一次不存在也会被加载会记录,下次拿到有这个KEY
2.Bloom过滤或RoaringBitmap 判断KEY是否存在
3.缓存雪崩:缓存数据同一时刻大规模不可用或都更新
原因:
1.key的过期时间都设置一致
2.更新策略
3.数据热点
4.缓存服务宕机
解决方案
1.在原有失效时间基础上增加一个随机值,比如1~5分钟的随机,这样每个缓存的过期时
重复率就会降低,集体失效概率也会大大降低。
2.更新策略在时间上做到比较均匀
3.使用的热数据尽量分散到不同的机器上
4.1多台机器做主从复制或者多副本,实现高可用
4.2 实现熔断限流机制,对系统进行负载能力控制
4.mysql和redis 数据一致性解决?(*)
1.缓存延时双删 问题:第二步缓存删除失败会导致脏数据,而且阻塞时间不太好评估。影响吞吐
2.删除缓存重试机制 解决上面删除失败的问题 问题:业务代码入侵
3.读取binlog 异步删除缓存 问题:binlog延时,宕机?
总结:
根本原因是因为cache和db不是原子性
要彻底解决的话 必须将cache和db的更新操作归在一个事务下。
根据实际场景来权衡落地方案
4.1.为什么不是更新缓存,而是删除缓存?
答:更新缓存的缺点
1.可能会造成数据一致性问题
2.如果缓存值计算复杂,然后更新频率高,会浪费性能
3.读少写多的场景, 数据还没读到又更新,会浪费性能。
实际上写多的场景 用缓存不划算。
4.2双写的情况下 为什么要先操作数据库而不是缓存
答:还是造成数据一致性问题
5.redis 分布式锁
实现:redisson 。 继承lock ,所以使用和lock没啥区别
还是基于lua,后台会开启一个watch dog线程监听是否过期。
6.高可用 - 主从,哨兵,集群分析
cluster集群:分片机制,内部分为16384个slot插槽,分布在所有master节点。数据写入按key做CRC16算法计算在哪个slot。数据冗余通过slave节点保障
哨兵:- 必须至少3个实例保证健壮性。主从+哨兵 并不能保证数据不丢失,但是可以保证集群的高可用
主从 - 主写从读,轻松实现水平扩容
7.淘汰策略
7.1 为什么需要淘汰?
不管是本地缓存还是分布式缓存,为了保证高性能,都是使用内存来存储数据,但是由于成本和内存限制,当数据超过缓存容量时,就需要对缓存的数据进行剔除。
7.2 常见的淘汰策略
fifo -淘汰最早数据 lru- 淘汰最近最少使用 lfu- 淘汰最近使用频率最低