Redis的数据类型
字符串、集合、有序集合、哈希、列表
Redis的线程模型是怎样的?
Redis内部使用 文件事件处理器(file event handler),该文件处理器是单线程的,因此Redis是单线程模型。它采用多路IO复用机制同时监听多个socket,根据socket上事件来选择对应的事件处理器进行处理。
文件事件处理器的结构包括4个部分:
1、多个socket
2、IO多路复用程序
3、文件事件分派器
4、事件处理器
具体的过程为:IO多路复用程序会监听多个socket,将socket产生的事件放入到队列中排队,文件事件分派器每次从队列中取出一个事件,交给事件处理器处理。
为什么大家都用Redis不用memcached呢?
1、Redis支持的数据类型更加的丰富(5种);memcached只支持字符串类型String
2、Redis可以进行持久化,将内存中的数据保存到内存中,重启时可以再次加载进行使用;而memcached数据只能存储在内存中,断电后数据失效;
3、集群模式:Redis目前支持多种集群模式:主从模式、sentinel模式、cluster模式(最佳);而memcached没有原生的集群模式,需要客户端自己往集群中分片写入数据。
4、Redis是单线程的多路IO复用模型;而memcached是多线程、非阻塞IO复用的网络模型。
举例说明Redis数据类型的使用场景
String
String既可以是字符串。也可以是数字
应用场景——常规计数:微博数、粉丝数、点击数
Hash
hash非常适合存储对象
应用场景:存储用户信息、商品信息
List
list是一个双向链表
应用场景:粉丝列表、好友列表、消息列表;
另外lrange可以实现从某行开始读取多少个元素,可以基于list实现分页查询(如微博下拉不断分页)
Set
集合实现的功能与List相似,区别是它可以排重。可以方便求交集、差集、并集
场景:共同关注好友、共同喜好
Zset
有序集合增加一个权重参数score,使得元素按照score有序排列。
应用场景:直播中实时排行榜——在线用户列表、礼物排行榜、弹幕消息
Redis的过期删除策略?
在set key的时候,可以指定key的过期时间,通常有两种过期删除策略:
1、定期删除:每隔100ms随机抽取一些设置了过期的key,检查其是否过期,若过期则删除。这里随机抽取是为了降低CPU的消耗;
2、惰性删除:定期删除会漏掉一些过期key,只有当你去查询key的时候,才会判断它是否过期做删除处理,这就是惰性删除。
以上两种方式还是无法保证能完全删除过期key,极端情况可能导致内存耗尽,因此还需要Redis的内存淘汰机制。
已知MySQL中有3000w条数据,Redis只有30w,如何保证Redis中的数据都是热点数据?
该问题其实就是在问:Redis的内存淘汰策略。
Redis提供了以下内存淘汰策略:
1、volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰;
2、volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰;
3、volatile-random:从已设置过期时间的数据集中任意选择任意选择数据淘汰;
4、allkeys-lru:当内存不足以容纳新写入数据时间,在键空间中,移除最近最少使用的key(这个是常用的)
5、allkeys-random:从数据集中任意选择数据淘汰;
6、no-eviction:禁止驱逐数据,也就是说当内存不足以容纳新写入时,新写入操作会报错。
如何保证Redis挂掉之后重启数据还能恢复?
该问题其实是在问:Redis的持久化机制。
- RDB方式持久化:快照是将内存中的数据状态进行记录,因此快照的数据量比数据本身小很多倍。Redis以快照方式记录某个时刻内存中数据的状态,定时将内存中的数据加载到磁盘,实现持久化。功能核心函数rdbSave(生成RDB文件)和rdbLoad(从文件加载内存)两个函数。
-
AOF方式持久化:AOF是只记录对Redis的操作命令,通过Redis通信协议(RESP)进行存储,将AOF定时保存到磁盘,在恢复是只需要按照AOF记录的命令执行就能得到和原来一样的数据。
每当定时执行服务器任务或者函数时,flushAppendOnlyFile 函数都会被调用, 这个函数执行以下两个工作
AOF写入保存:
WRITE:根据条件,将 aof_buf 中的缓存写入到 AOF 文件
SAVE:根据条件,调用 fsync 或 fdatasync 函数,将 AOF 文件保存到磁盘中。
-
RDB与AOF对比
1、RDB快照文件更小,恢复效率更高,是Redis默认方式;AOF的文件会越来越大,需要重写机制保证AOF文件的大小;
2、AOF的更新频率更高,且AOF更安全。
3、RDB断电后重启,最近一次快照将丢失,可能丢失最近几分钟的数据;而AOF丢失最近几秒的数据,因此更安全。
-
什么是一致性哈希?哈希槽呢?
一致性哈希流程:
- 对服务器节点进行哈希,将其映射到一个0-2^32范围环上;
- 相同的哈希方法,对key进行哈希,映射到哈希环上;
- 将数据映射的位置顺时针查找,将数据保存到第一个找到的服务器上,如果找了一圈找不到,就放在第一个服务器上。
优点:与传统哈希相比,一致性哈希受节点数据量变动的影响很小,新增或删除节点只影响下一个节点;
哈希槽:Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数。
Redis 集群没有使用一致性hash, 而是使用哈希槽。
哈希槽的优点:
当需要增加节点时,只需要把其他节点的某些哈希槽挪到新节点就可以了;
当需要移除节点时,只需要把移除节点上的哈希槽挪到其他节点就行了;
在这一点上,我们以后新增或移除节点的时候不用先停掉所有的 redis 服务。
Redis事务
事务命令:Multi(标志接下来的命令需要组合执行)、exec(将以上命令组合执行)、watch命令实现;
原理是将多个命令按顺序加入队列中一次性执行;
特点:
1、事务命令无法加塞任务;
2、redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,不支持回滚。
什么是缓存穿透,解决方法?
查询一个不存在的key:当用户查询某个数据,没有命中Redis缓存,于是向数据库中去查询,还是没找到,费了半天功夫查询失败;当用户请求很多都没有命中缓存,就会去持久层查询,给数据库造成很大的压力,这就是缓存穿透。
缓存穿透的解决方法:
1、布隆过滤器:先对请求进行判断,如果请求的结果不在数据库中,将不会执行查询操作;
2、设置空对象:查完一次数据库没找到数据,将一个空对象存入缓存,避免读取数据库;
什么是缓存击穿(热点key),解决方法?
缓存中热点key在某个时间点失效,此时刚好有大量的并发请求过来,在缓存中没命中都去数据库查询,相当于缓存被击穿了,数据库可能被压垮;
缓存击穿的解决方法:
使用互斥锁(mutex key),对缓存查询加锁,如果key不存在,就加锁,然后读取数据库,将key放入缓存,解锁;
什么事缓存雪崩,解决方法?
缓存在某个时间点大面积失效,请求落到数据库上,造成数据库崩掉。
缓存雪崩的解决方法:
1、在过期时间上加一个随机时间,避免同时失效;或缓存
2、保持缓存层你的高可用:使用Redis 哨兵模式或 Redis Cluster模式,保证请求落在Redis;
3、限流+降级:限制流量,服务降级,保证核心功能可用;
4、互斥锁:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。
Redis与数据库的一致性实现
保证一致性的关键措施:
1、读数据从缓存读,不要从数据库读;
2、数据先淘汰缓存,再写入数据库;先更新DB数据,然后通过发送操作缓存的消息到消息队列,进行更新缓存操作,这里还需要的一个操作就是利用消息队列的重试机制,保证缓存能够更新成功,如果多次消费失败,可能是由于网络原因或者redis服务挂了,此处可以添加告警处理。
Redis集群方案
1、主从模式
2、哨兵模式
3、Cluster模式(最优)
本文参考:https://blog.csdn.net/qq_34337272/article/details/80012284