做了个手写redis的项目,redis越学越感觉博大精深,如果要是想深入了解,建议阅读相关技术资料。本文是亲自整理的Redis夺命连环29问,希望能够加深对Redis 的理解。
一、Question
1.什么是Redis?
2.Redis可以用来干什么?
3.Redis有哪些数据类型?
4.Redis为什么快?
5.什么是I/O多路复用?
6.为什么Redis4.0后开始使用多线程?
7.单线程的redis的QPS?
8.什么时候RDB?
9.如何AOF?
10.Redis内存淘汰策略?
11.RDB和AOF优缺点?
12.如何选择RDB/AOF?
13.Redis4.0的混合持久化?
14.主从复制的作用是什么?
15.主从数据不一致怎么办?
16.Redis 主从有几种常见的拓扑结构?
17.主从复制的过程?
18.数据主从复制的方式?
19.新的主节点是怎么被选举出来的?
20.Redis集群有什么作用?
21.切片集群了解吗?
22.集群中数据如何分区?
23.集群的原理?
24.集群的扩缩容?
25.什么是缓存击穿、缓存穿透、缓存雪崩?
26.如何保证缓存和DB数据一致性?
27.如何处理大Key?热Key?
28.缓存预热怎么做呢?
29.假如 Redis 里面有 1 亿个 key,其中有 10w 个 key 是以某个固定的已知的前缀开头的,如何将它们全部找出来?
二、Answer
1. 一种基于键值对(key-value)的 NoSQL 数据库,支持多种数据结构,所有数据都存放在内存当中,具有出色的读写新能。是互联网技术领域中使用最广泛的缓存中间件。
2. 缓存、排行榜/计数器、分布式锁、限流组件。
3. string,list,hash,set,Zset
4. 数据存储在内存、单线程模型(避免了线程切换和锁竞争)、IO多路复用(一个线程监听处理多个请求)、高效的数据结构。
5. 一种允许单个进程或线程同时处理多个 I/O 操作的技术
6. 多线程是用多线程来处理数据的读写和协议解析,但是 Redis执行命令还是单线程的。
7. 每秒超过10万次。
8. Conf配置save second changes、主从复制
9. 四个步骤:命令写入(append)、文件同步(sync)、文件重写(rewrite)、重启加载(load)
10. noeviction:这是默认的淘汰策略,当内存不足以存储新数据时,Redis 将拒绝新的写入操作,但不会淘汰任何数据。可以设置从指定数据集淘汰数据,比如设置了过期时间的数据集volatile-lru、未设置过期时间数据集allkeys-lru
11. RDB 是一个非常紧凑的单文件(二进制文件 dump.rdb),代表了 Redis 在某个时间点上的数据快照。非常适合用于备份数据,比如在夜间进行备份,然后将 RDB 文件复制到远程服务器。但可能会丢失最后一次持久化后的数据。AOF 的最大优点是灵活,实时性好,可以设置不同的 fsync 策略,如每秒同步一次,每次写入命令就同步,或者完全由操作系统来决定何时同步。但 AOF 文件往往比较大,恢复速度慢,因为它记录了每个写操作。
12. 如果需要尽可能减少数据丢失,AOF 是更好的选择。尤其是在频繁写入的环境下,设置 AOF 每秒同步可以最大限度减少数据丢失。如果性能是首要考虑,RDB 可能更适合。RDB 的快照生成通常对性能影响较小,并且数据恢复速度快。
13. 混合持久化模式会在 AOF 重写的时候同时生成一份 RDB 快照,然后将这份快照作为 AOF 文件的一部分,最后再附加新的写入命令。这样,当需要恢复数据时,Redis 先加载 RDB 文件来恢复到快照时刻的状态,然后应用 RDB 之后记录的 AOF 命令来恢复之后的数据更改,既快又可靠。
14. ①数据冗余: 主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
②故障恢复:如果主节点挂掉了,可以将一个从节点提升为主节点,从而实现故障的快速恢复。通常会使用 Sentinel 哨兵来实现自动故障转移,当主节点挂掉时,Sentinel 会自动将一个从节点升级为主节点,保证系统的可用性。
③负载均衡: 在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务 (即写 Redis 时连接主节点,读 Redis 时连接从节点),分担服务器负载。尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis 服务器的并发量。
④高可用基石: 除了上述作用以外,主从复制还是哨兵和集群能够实施的 基础
15. 通过 Redis 的 INFO replication 命令监控主从节点的复制进度,及时发现和处理复制延迟。具体做法是获取主节点的 master_repl_offset 和从节点的 slave_repl_offset,计算两者的差值。如果差值超过预设的阈值,采取措施(如停止从节点的数据读取)以减少读到不一致数据的情况。
16. 一主一从、一主多从、树状主从
17. 从记录主的信息 -> 从主建立socket链接 -> 发送ping命令 -> 权限验证 -> 同步数据集 -> 命令持续复制
18. 全量复制和增量复制
19. 首先对从节点列表进行过滤,过滤不健康;然后选择slave_priority最高的从节点;若无则选择复制偏移量最大的从节点;若无则选择runid最小的节点。
20. ①数据分区:数据分区 (或称数据分片) 是集群最核心的功能。集群将数据分散到多个节点,一方面突破了 Redis 单机内存大小的限制,存储容量大大增加;另一方面 每个主节点都可以对外提供读服务和写服务,大大提高了集群的响应能力。②集群支持主从复制和主节点的自动故障转移 (与哨兵类似),当任一节点发生故障时,集群仍然可以对外提供服务。
21. 切片集群是一种将数据分片存储在多个 Redis 实例上的集群架构,每个 Redis 实例负责存储部分数据。比如说把 25G 的数据平均分为 5 份,每份 5G,然后启动 5 个 Redis 实例,每个实例保存一份数据。
22. 节点取余:其中数据项通过对某个值(通常是键的哈希值)进行取余操作来分配到不同的节点。缺点是扩缩容时,大多数数据需要重新分配,因为节点总数的改变会影响取余结果,这可能导致大量数据迁移。一致性哈希:将哈希值空间组织成一个环,数据项和节点都映射到这个环上。数据项由其哈希值直接映射到环上,然后顺时针分配到遇到的第一个节点。从而来减少节点变动时数据迁移的量。存在问题就是节点在圆环上分布不平均,会造成部分缓存节点的压力较大,同时当某个节点故障时,这个节点所要承担的所有访问都会被顺移到另一个节点上,会对后面这个节点造成压力。用哈希槽解决。哈希槽分区:槽位的数量是固定的(例如 Redis Cluster 有 16384 个槽),每个键通过哈希算法(比如 CRC16)映射到这些槽上,每个集群节点负责管理一定范围内的槽。(删除节点重新分配槽即可)
23. Redis 集群通过数据分区来实现数据的分布式存储,通过自动故障转移实现高可用。建立集群时,通过节点握手感知(节点间通过Gossip协议进行通信,感知彼此)组成集群;集群把所有的数据映射到 16384 个槽中。每个节点对应若干个槽; Redis 集群内节点通过 ping/pong 消息实现节点通信,集群中每个节点都会定期向其他节点发送 ping 消息,接收节点回复 pong 消息作为响应;使用Raft协议选举节点。
24. 扩容和缩容就是将一部分槽和数据迁移给新节点。
25. 缓存穿透是指查询缓存数据未命中(因为数据根本就不存在),请求每次都会穿过缓存去查询数据库,给DB造成压力(布隆过滤器);缓存击穿是指少数高频被访问的热点key过期时,大量查询请求瞬间落入DB(热点数据设置永不过期或者刷新过期时间);缓存雪崩:在某一个时间点,由于大量的缓存数据同时过期或缓存服务器突然宕机了,导致所有的请求都落到了DB(限流、降级、过期时间)
26. 旁路缓存:失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。命中:应用程序从cache中取数据,取到后返回。更新:先把数据存到数据库中,成功后,再让缓存失效。
27. 数据冗余减轻单节点热key压力、大key拆分
28. 缓存预热是指在系统启动时,提前将一些预定义的数据加载到缓存中,以避免在系统运行初期由于缓存未命中(cache miss)导致的性能问题。可以使用定时任务或者启动时加载
29. 使用 keys 指令可以扫出指定模式的 key 列表(会阻塞)scan 指令可以无阻塞的提取出指定模式的 key 列表,但是会有一定的重复概率,在客户端做一次去重就可以了。
评论