https://www.cnblogs.com/gustavo

Gustavo's Blog

人类的赞歌是勇气的赞歌!

Redis知识点总结

Redis的淘汰策略有哪几种?
volatile-lru 从已设置过期时间的数据集中挑选最近最少使用的数据淘汰
volatile-ttl 从已设置过期时间的数据集中挑选将要过期的数据淘汰
volatile-random 从已设置过期时间的数据集中任意选择数据淘汰
对于以上三种策略,如果没有符合条件的,则和noeviction一样返回错误。
allkeys-lru 从所有数据集中挑选最近最少使用的数据淘汰
allkeys-random 从所有数据集中任意选择数据进行淘汰
noeviction 禁止驱逐数据,默认策略,对于写请求会报错,删除和其他部分请求除外


Redis高性能的原因?
Redis是单线程的,避免了多线程的上下文切换和并发控制开销;
Redis大部分操作时基于内存,读写数据不需要磁盘I/O,所以速度非常快;
Redis采用了I/O多路复用机制,提高了网络I/O并发性;
Redis提供高效的数据结构,如跳跃表、哈希表等;

全局哈希表:读取是通过哈希表来存储和读取

一些数据结构的优化


Redis到底是单线程还是多线程?
版本5.0之前的版本是单线程,工作线程是单线程。指令串行执行。
6.0版本之后,还是单work线程。但是会开辟单独的IO子线程。去read和write。计算还是在work线程中,将结果返回io子线程中。

Redis主线程,主要做三个事情
• 监听io多路复用器上发生的读写事件,在监听到读事件的时候,主线程就会把发生读事件的连接分发给io线程。io线程会读取和解析请求然后把解析好的命令和参数放到缓冲区里面去
• 执行io线程读取好的命令
• 执行定时任务,更新时钟,检查心跳

IO线程主要干两个事情
• 从连接里面读取数据,反序列化,得到redis命令
• 把命令执行完的返回值序列化成字节数组,通过连接返回到客户端

回收内存空间的操作放在后台线程。


Redis的使用场景?
计数器
排行榜计算
生成订单号
点赞功能
消息队列
会话缓存
分布式锁
共同好友

Redis支持哪些数据类型?
String
List
Set
Hash
Zset

Redis的持久化策略有哪些?
AOF文件
将写命令添加到 AOF 文件(Append Only File)的末尾。
使用 AOF 持久化需要设置同步选项,从而确保写命令同步到磁盘文件上的时机。这是因为对文件进行写入并不会马上将内容同步到磁盘上,而是先存储到缓冲区,然后由操作系统决定什么时候同步到磁盘。
直接保存命令。

能否保证不丢数据,要看刷盘策略。有以下三种。
always 每个写命令都同步,选项会严重减低服务器的性能;
everysec 每秒同步一次,选项比较合适,可以保证系统崩溃时只会丢失一秒左右的数据,并且 Redis 每秒执行一次同步对服务器性能几乎没有任何影响;
no 让操作系统来决定何时同步,选项并不能给服务器性能带来多大的提升,而且也会增加系统崩溃时数据丢失的数量。

aof 回单独开一个子线程进行rewrite,就是合并一个key的多次修改

RDB快照
将某个时间点的所有数据都存放到硬盘上。
可以将快照复制到其它服务器从而创建具有相同数据的服务器副本。
如果系统发生故障,将会丢失最后一次创建快照之后的数据。
如果数据量很大,保存快照的时间会很长。

rdb是一个二进制文件 文件头 控制信息 按照redis自己的格式存储了不同的键值对格式最后加上一个文件尾

什么是缓存穿透?解决办法?
缓存穿透 [不断的穿透到数据库上]
访问一个缓存和数据库都不存在的 key,此时会直接打到数据库上,并且查不到数据,没法写缓存,所以下一次同样会打到数据库上。
解决办法
接口校验,可以在最外层先做一层校验:用户鉴权、数据合法性校验等,例如商品查询中,商品的ID是正整数,则可以直接对非正整数直接过滤等等。
缓存空值。当访问缓存和DB都没有查询到值时,可以将空值写进缓存,但是设置较短的过期时间,该时间需要根据产品业务特性来设置。
布隆过滤器。使用布隆过滤器存储所有可能访问的 key,不存在的 key 直接被过滤,存在的 key 则再进一步查询缓存和数据库。

如何保证缓存一致性?
读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应。
更新的时候,先更新数据库,然后再删除缓存。

Redis几种数据结构的实际应用?
• String
对象缓存
单值缓存 SET user:1 value(json格式数据)
分布式锁 SETNX product:10001
计数器 INCR article:readcount:{文章id}
序列号生成 INCRBY orderId 1000 //redis批量生成序列号提升性能

• Hash

购物车 添加商品:hset cart:1001 10088 1

• List

消息流

• Set

共同关注 SINTER zhangsanSet yijiaoqianSet--> {lisi, wangwu}
可能认识 SDIFF yijiaoqianSet zhangsanSet->(zhangsan, zhaoliu}

• Zset

排行榜 ZREVRANGE hotNews:20201221 0 9 WITHSCORES

什么是多路复用?
redis利用epoll实现IO多路复用,将连接信息和事件放到队列中,依次放到文件事件分派器,事件分派器将事件分发给事件处理器。

socket —>多路复用程序 —>队列 —>文件事件分派器
redis客户端先去select循环询问服务端是否可以发起read 这个过程是阻塞的 但是速度很快,当服务端准备好了数据报告诉客户端readable,客户端即可发起read请求,此时因为服务端已经准备好了数据报,直接返回即可。整个过程只在调用select、poll、epoll这些调用的时候才会阻塞,收发客户消息是不会阻塞的。这种方式避免了线程的阻塞,又称为非阻塞I/O模型
这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗)

中间层 事件处理器

什么是缓存击穿?解决办法有哪些?
热点key过期
某一个热点 key,在缓存过期的一瞬间,同时有大量的请求打进来,由于此时缓存过期了,所以请求最终都会走到数据库,造成瞬时数据库请求量大、压力骤增,甚至可能打垮数据库。
解决方案
加互斥锁。在并发的多个请求中,只有第一个请求线程能拿到锁并执行数据库查询操作,其他的线程拿不到锁就阻塞等着,等到第一个线程将数据写入缓存后,直接走缓存。
热点数据不过期。直接将缓存设置为不过期,然后由定时任务去异步加载数据,更新缓存。

什么是缓存雪崩?有哪些解决方案?
缓存雪崩
大量热点key过期
大量的热点 key 设置了相同的过期时间,导在缓存在同一时刻全部失效,造成瞬时数据库请求量大、压力骤增,引起雪崩,甚至导致数据库被打挂。(升级版的缓存击穿)
解决方案
过期时间打散。既然是大量缓存集中失效,那最容易想到就是让他们不集中生效。可以给缓存的过期时间时加上一个随机值时间,使得每个 key 的过期时间分布开来,不会集中在同一时刻失效。
热点数据不过期。该方式和缓存击穿一样,也是要着重考虑刷新的时间间隔和数据异常如何处理的情况。
加互斥锁。[基本就两种处理方式,过滤或者加锁] 该方式和缓存击穿一样,按 key 维度加锁,对于同一个 key,只允许一个线程去计算,其他线程原地阻塞等待第一个线程的计算结果,然后直接走缓存即可。

使用过Redis做异步队列么,你是怎么用的?
一般使用list结构作为队列,rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。

Redis的同步机制了解么?
Redis可以使用主从同步,从从同步。第一次同步时,主节点做一次bgsave,并同时将后续修改操作记录到内存buffer,待完成后将RDB文件全量同步到复制节点,复制节点接受完成后将RDB镜像加载到内存。
加载完成后,再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。后续的增量数据通过AOF日志同步即可,有点类似数据库的binlog。

redis如何实现分页查询
通过SortedSet的zrevrange topicId (page-1)×10 (page-1)×10+perPage指令可以实现分页功能。

什么是布隆过滤器
就是bitmap

上图就是将每个key经过三个不同hash算法计算后插入bit数组的位置状态。可以推断出一个结论:
这个过滤器能够查询到key说明这个key不一定存在
这个过滤器不能够查询到key说明这个key一定不存在

Redis的key和value可以存储的最大值分别是多少?
虽然Key的大小上限为512M,
但是一般建议key的大小不要超过1KB
这样既可以节约存储空间,又有利于Redis进行检索。
value的最大值也是512M。对于String类型的value值上限为512M,而集合、链表、哈希等key类型,单个元素的value上限也为512M。

怎么利用Redis实现数据的去重?
Redis的set:它可以去除重复元素,也可以快速判断某一个元素是否存在于集合中,如果元素很多(比如上亿的计数),消占用内存很大
Redis的bit:它可以用来实现比set内存高度压缩的计数,它通过一个bit设置为1或者0,表示存储某个元素是否存在信息。例如网站唯一访客计数,可以把user_id作为 bit 的偏移量 offset,如设置为1表示有访问,使用1 MB的空间就可以存放800多万用户的一天访问计数情况。
HyperLogLog:实现超大数据量精确的唯一计数都是比较困难的,HyperLogLog可以仅仅使用 12 k左右的内存,实现上亿的唯一计数,而且误差控制在百分之一左右。
bloomfilter布隆过滤器:布隆过滤器是一种占用空间很小的数据结构,它由一个很长的二进制向量和一组Hash映射函数组成,它用于检索一个元素是否在一个集合中

Redis什么时候需要序列化?Redis序列化的方式有哪些?
比如想把内存中的对象状态保存到一个文件中或者数据库中的时候(最常用,如保存到redis);
再比喻想用套接字在网络上传送对象的时候,都需要序列化。

RedisSerializer接口 是 Redis 序列化接口,用于 Redis KEY 和 VALUE 的序列化
JDK 序列化方式 (默认)
String 序列化方式
JSON 序列化方式
XML 序列化方式

Redis如何通过跳表来存储元素的
最开始的有序索引就是通过分值进行链表存放,跳表是通过有序链表优化而来的,就是在元素的上一层添加冗余元素来构建索引。通过上层来进行定位查找,类似于折半查找。


Redis修改key需要注意的
如果以前的key存在过期时间,那修改时要注意,如果没设置过期时间则需会一直不过期

Redis过期了为什么 内存没释放
1 修改了某个有过期时间的key,并没有重新给定过期时间
2 删除策略暂时没删到 (没有到达最大使用内存)


redLock实现原理
类似zk


Redisson分布式锁原理


缓存击穿
缓存失效
随机失效时间

缓存穿透
都穿透了,缓存没有数据库也没有

redis -sds
没有用C语言提供的字符串是用的自己实现的结构体来存储字符串,空间预留方便字符串添加
会根据字符串长度决定使用哪种结构体

可以支持特殊字符的存储,安全的二进制存储,方便获取字符串长度

zset 的底层数据结构
压缩列表

跳表 (多级索引)

posted @ 2022-08-20 16:50  BitBean  阅读(96)  评论(0编辑  收藏  举报