1、单线程的为什么快?
- 纯内存操作
- 基于非阻塞的IO多路复用
- 避免了多线程下的频繁上下文切换带来的性能问题
2、redis分布式锁
setnx (set if not exist) return 0 失败;return 1成功;
3、过期key的删除策略
- 惰性过期:每次用的时候检查是否过期,可能造成积攒大量无用key,造成内存溢出
- 定期过期:每隔一段时间自动将过期的key删除, 可以缓解服务器内存和cpu的压力,但是要合理设置操作的执行时长和操作频率
- 定时过期:内部创建定时器,影响性能
4、redis的持久化机制
- RDB:Redis DataBase将每一时刻的内存快照,以二进制的方式写入磁盘
- 手动触发
- save:会使redis处于阻塞状态,直到RDB持久化结束
- bgsave:fork出子进程进行持久化,主进程只有短暂的阻塞 (关键技术:copy on write,防止子进程读取到脏数据 )
- 自动触发
- save m n :在m秒内,如果有n个键发生改变,则触发持久化
- flushall:
- 主从同步:全量同步的时候会触发bgsave命令,方便持久化
- 手动触发
优点:fork子进程进行持久化,效率高,不会阻塞主进程
缺点:数据安全性较低,会发生数据丢失;数据集较大时,会占用较大cpu资源;
- AOF :append only file 以日志的形式记录服务器处理的每一个写、删除操作,再调操作系统命令将日志文件进程刷盘
同步策略:
每秒同步
每修改同步
不同步
优点:数据安全
缺点:AOF文件比RDB大,恢复速度慢;数据集大的时候,比rdb启动效率低
如果RDB和AOF都开启,默认使用AOF
5、集群方案
- 主从
- 哨兵
- redis cluster 服务端分片
- redis sharding 客户端进行分片
6、数据结构
- 字符串
- 哈希表:存储对象
- 列表:可以当做栈或队列
- 集合:元素不能重复
- 有序集合:可以设置顺序 ,score,设置顺序
7、布隆过滤器
作用: 用于判断元素在集合中是否存在,可以当做缓存的索引,用来保存缓存服务器,防止缓存击穿
BloomFilter 是由一个固定大小的二进制向量或者位图(bitmap)和一系列映射函数组成的。
优点:速度快,占用内存小;可以表示全集;
缺点:可能误判为存在(存在Hash冲突);删除元素比较困难;
8、常见的缓存淘汰算法
- FIFO(先进先出)
- LRU(最近最少使用)
- LFU(最不经常使用):在一段时间内,缓存数据被使用次数最少的会被淘汰
9、什么事缓存穿透、缓存击穿、缓存雪崩
问题:缓存穿透:缓存中查不到,数据库中也查不到,容易被攻击
解决方案:
- 参数合法性校验
- 将数据库中没有查到结果的数据也写入到缓存,但是需要防止redis被撑满,需要设置过期时间较短
- 布隆过滤器
问题:缓存击穿:缓存中没有,数据库中有。可能数据key过期或者正在保存redis数据。问题在于重新写入缓存需要一定时间
解决方案:
- 设置热点缓存永不过期,定期重建缓存
- 数据库写入到缓存的时候,防止并发,添加锁
问题:缓存雪崩:由于缓存失效,缓存大面积没有,瞬间进入数据库
解决方案:
- 把缓存的失效时间分散,在原有的统一失效时间的基础上,增加随机值
- 将热点数据设置永不过期
10、redis事务实现
MULTI 开启事务——》
命令入队——》
EXEC 执行事务(不支持回滚机制,但是会检查每一个事务中的命令是否错误,不支持运行时错误)
11、如果保证redis与数据库的数据一致性
数据更新的时候, 先删缓存,再写数据库?
解决方案:
- 延时双删(先删缓存,再删数据库,等待一小会,再次删除缓存)
- 先修改缓存为特殊值,客户端读取到特殊值后,等待一小会再重试
先写数据库,再删缓存?
总结:没有啥好办法