Redis 只有单线程吗
Redis 是单线程的,主要是指 Redis 的网络 IO 线程。Redis 的持久化,集群同步等操作,则是由另外的线程来执行
Redis 采用单线程为什么还这么快
redis 4.0 版本之前
Redis 的大部分操作都在内存中完成
使用了多种优秀的数据结构
单线程模型避免了多线程之间的竞争
Redis 采用了 IO 多路复用机制处理大量的客户端 Socket 请求
redis 6.0 版本之后新增了多线程 IO 的读写并发能力
- 网络硬件不断升级,性能瓶颈出现在单线程的 IO 处理上
- 网络请求采用多线程并行,但是读写命令依然是单线程处理
Redis 数据持久化
- AOF 日志:记录所有的操作命令,并以文本的形式追加到文件中
- RDB 快照:将某一时刻的内存数据,以二进制的方式写入磁盘
- 混合持久化方式:Redis 4.0 新增混合之久话的方式,集成了 RDB 和 AOF 的优点
AOF 日志如何实现的?
通常情况下,关系型数据库的日志都是“写前日志”,而 AOF 里记录的是 Redis 收到的每一条命令,这些命令时以文本形式保存的,不同的是,Redis 的 AOF 日志的记录顺序与传统关系型数据库正好相反,它是写后日志,“写后”是指 Redis 要先执行命令,把数据写入内存,把数据写入内存,然后再记录日志到文件
- 执行命令写入内存
- 记录日志
why:因为 Redis 在写入日志之前,不对命令进行语法检查。所以,只记录执行成功的命令,避免了出现记录错误命令的情况。并且,在命令执行完之后在记录,不会阻塞当前的写操作
but:数据可能会丢失(数据在写入内存时宕机);可能阻塞其他操作(在执行记录日志的操作的时候依然会阻塞将要写入内存的数据操作)
so:为了解决 AOF 方法做故障恢复时操作缓慢这个问题,Redis 增加了 RDB 内存快照的操作,它既可以保证可靠性,又能在宕机时实现快速恢复;和 AOF 不同的是,RDB 记录 Redis 某一时刻的数据,而不是操作。所以在做数据恢复的时候,只需要直接把 RDB 文件写入内存,完成快速恢复
RDB 主要原理主要考点
-
RDB 做快照时会阻塞线程吗?
- 为了解决阻塞线程问题,Redis 提供了两个命令来生成 RDB 快照文件,分别是 save 和 bgsave。save命令在主线程中执行,会导致阻塞。而 bgsave 命令会创建一个子线程,用于写入 RDB 文件的操作,避免了对主线程的阻塞
-
RDB 在做快照的时候数据能修改吗?
question 1:如果此时可以执行写操作:意味着 Redis 还能正常处理写操作,就可能出现正在执行快照的数据是已经被修改了的情况
question 2:如果此时不可以执行写操作:意味着 Redis 的所有写操作都得等到快照执行完成之后才能执行,那么就又出现了阻塞主线程的问题
RDB 如何解决上述问题的呢?
- 如果主线程执行读操作,则主线程和 bgsave 子线程互相不影响
- 如果主线程执行写操作,则被修改的数据会复制一份副本,然后 bgsave 子线程会把该副本数据写入 RDB 文件,在这个过程中,主线程依然可以直接修改原来的数据
注意:Redis 对 RDB 的执行频率非常重要,因为这会影响快照数据的完整性以及 Redis 的稳定性,所以在 Redis 4.0 后,增加了 AOF 和 RDB 混合的数据持久化机制:把数据以 RDB 的方式写入文件,再将后续的操作命令以 AOF 的格式存入文件,即保证了 Redis 重启速度,又降低数据丢失风险
Redis 如何实现服务高可用?
-
主从同步
- 一主多从实现数据读写分离承担更多的并发操作
-
哨兵模式 (Redis Sentinel)
- 当 Redis 主从服务器出现故障宕机,需要手动进行恢复,Redis 增加了烧饼模式(哨兵模式做到了可以监控主从服务器,并且提供主动容灾恢复的功能)
-
Redis Cluster(集群)
-
Redis Cluster 是一种分布式去中心化的运行模式,它将数据分布在不同的服务器上,以此来降低系统对单节点的依赖,从而提高 Redis 服务的读写性能(多主多从)
-
Redis Cluster 方案采用哈希槽来处理数据与实例之间的映射关系,在 Redis Cluster 方案中,一个切片集群共有 16384 个哈希槽,这些哈希槽类似于数据分区,每个键值对都会根据它的 key,被映射到一个哈希槽中,具体执行过程分为两大步
- 根据键值对的 key,按照 CRC16 算法计算一个 16bit 的值
- 再用 16bit 值对 16384 取模,得到 0~16384 范围内的模数,每个模数代表一个对应编号的哈希槽
哈希槽怎么被映射到具体的 Redis 实例上的呢?
- 平均分配:在使用 cluster create 命令创建 Redis 集群时,Redis 会自动把所有哈希槽平均分布到集群实例上 (16384 / 实例个数)
- 手动分配:可以使用 cluster meet 命令手动建立实例间的连接,组成集群,再使用 cluster addslots 命令,指定每个实例上的哈希槽个数
-