六、Redis
1. redis为什么快
完全基于内存操作
数据结构简单,对数据操作简单
redis是单线程避免了上下文切换带来的性能问题,也不用考虑锁的问题
采用非阻塞的IO多路复用机制
edis不是完全多线程的,在核心的网络模型中是多线程的用来处理并发连接,但是数据的操作都是单线程。Redis坚持单线程是因为Redis的性能瓶颈是网络延迟而不是CPU,多线程对数据读取不会带来性能提升。
2. redis持久化机制
快照持久化RDB
bgsave 调用之后保存快照
save 根据配置保存 save 600 1 如果600秒执行了一条命令就持久化
redis的默认持久化机制,通过父进程fork一个子进程,子进程将redis的数据快照写入一个临时文件,等待持久化完毕后替换上一次的rdb文件。整个过程主进程不进行任何的io操作。持久化策略可以通过save配置单位时间内执行多少次操作触发持久化。所以RDB的优点是保证redis性能最大化,恢复速度数据较快,缺点是可能会丢失两次持久化之间的数据
追加文件持久化AOF
通过appendfsync配置
always 每个命令追加
everysec 每秒追加
no 丢给操作系统
只能使用everysec,always一次只能写入条指令,会引发严重的写入方法,导致固态硬盘寿命降低,no 很吃性能,redis会变慢,everysec基本和不开一样,几乎不影响性能
AOF一直追加会占用大量空间,需要做重写操作,压缩空间,但是重写依旧需要fork子线程,那么RDB持久化的问题在AOF中同样会出现
以日志形式记录每一次的写入和删除操作,策略有每秒同步、每次操作同步、不同步,优点是数据完整性高,缺点是运行效率低,恢复时间长
3. Redis如何实现key的过期删除?
定期删除 :Redis 每隔一段时间从设置过期时间的 key 集合中,随机抽取一些 key ,检查是否过期,如果已经过期做删除处理。
惰性删除 :Redis 在 key 被访问的时候检查 key 是否过期,如果过期则删除。
4. Redis数据类型应用场景
String:可以用来缓存json信息,可以用incr命令实现自增或自减的计数器
Hash:与String一样可以保存json信息
List:可以用来做消息队列,list的pop是原子性操作能一定程度保证线程安全
Set:可以做去重,比如一个用户只能参加一次活动 ;可以做交集求共友
SortSet :有序的。可以实现排行榜
5. Redis并发缓存三大问题
6. Redis实现发布文章、点赞排序
仅一周内可以点赞,如果长期点赞,取消一个zset即可
需要的数据结构
一个hash存储文章信息 包括点赞
两个zset 一个存储文章发布时间 一个存储分数(每次点赞给一个分数,自定义,利于排序)
一个set存储投票过的用户 保证只能投票一次
发布流程
使用incr计数器创建文章id
sadd将文章发布者id添加到点赞集合,使用expire设置过期时间,一周后自动删除
HMSET存储文章信息到hash中
执行ZADD将文章放到两个zset中
点赞流程
点赞的时候,使用ZSCORE从zset获取发布时间
在一周内就使用SADD将用户添加到set
使用ZINVRBY对文章加分
使用HINCRBY对文章点赞更新+1
取出最高评分和最新发布文章
使用ZREVRANGE可以按照分值大小取出文章id
对每个id执行HGETALL,获取全部信息
分组功能
为每个分组添加一个set,在分组里面的文章id添加到set里面
扩展
ZINTERSTORE可以对两个集合取交集,获取最多点赞和最新发布的文章
如果要实现反对投票可以参考投票减少分值和点赞即可
暂时没有考虑事务问题
7. Redis的扩展数据类型
- Bitmap:主要用来做二进制数据的统计(数据内容只有0/1状态);
- HyperLogLog:主要用来统计海量的不重复数据数量;
- GEO:主要用来保存经纬度数据。
8. 五种基本数据类型的底层实现
String 简单动态字符串
9. Redis事务
redis事务是将多个命令缓存起来,当发送exec命令时,依次执行缓存中的所有命令。redis的事务没有隔离级别,也不保证原子性,更不支持回滚操作。redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。
10. Redis淘汰策略与过期策略
过期策略
定时删除:将设置了TTL的key单独存放到一个字典,通过过期时间去访问是否达到删除时间,这里采用贪心算法,每次随机访问一些key,如果过期就删除,假设每次都遍历全部,那么很吃性能
惰性删除:当我访问key之前先判断是否应该删除。
定时删除会导致有些key应该删了但是没有删,所以使用惰性删除规避。不管是定期采样删除还是惰性删除都不是一种完全精准的删除,就还是会存在key没有被删除掉的场景,所以就需要内存淘汰策略进行补充。
淘汰策略
仅仅列举一些常见的策略
- 加入键的时候如果过期,从所有key随机删除
- 加入键的时候如果过期,从过期键从随机删除
- 过期之后马上删除
- 删除过期键中最少使用频率的