Redis
基本概念¶
- 一个内存 key-value 存储系统。 Redis 可用作数据库、缓存、消息代理和队列等。
- Redis 常被称作是一款数据结构服务器。Redis 的键值可以包括字符串类型,同时它还包括哈希、列表、集合和有序集合等数据类型。并且可以执行对这些数据结构的操作
- 优点:
- 性能极高
- 原子操作
- 丰富数据类型
- 方便医用
- 缺点
- 内存限制(数据都存储在内存)
- 高持久化限制(数据写入磁盘过程中可能丢失,如断电)
- 缓存限制:用于缓存时存在缓存雪崩、缓存击穿
- Redis 是一个服务端和客户端配合的程序
Redis 的安装与配置¶
基本操作¶
# 开启 redis-server(服务端)
sudo service redis-server start
# 进入 redis-cli(客户端)
redis-cli
用法¶
Redis 中的数据结构¶
Redis strings¶
- Redis 字符串是二进制安全的,可以存储 base 64 编码的图片以及序列化对象等
- 过大文件不适合存入 Redis,符串类型的值最多能存储 512M 字节的内容。
- 设置和获取 set、get 命令
-
set mykey newval nx set mykey newval xx
-
- set 参数:nx 表示只有 key 不存在才设置新值;xx 表示当 key 已经存在了才设置新值
- 一次获取多个键值
mset a 10 b 20 c 30 mget a b c
Redis Lists¶
- 支持从头尾插入元素
rpush mylist A
向末尾添加元素 A- 一次添加多个元素
rpush mylist 1 2 3 4 5 "foo bar"
lpush mylist B
向头部添加元素 B
- 弹出元素
rpop mylist lpop mylist
-
范围获取元素
lrange mylist 0 -1
-
阻塞操作:数据不存在时阻塞请求队列,超时还没有数据则返回 nil
brpop list 10 brpop mylist 10
Redis Hashes¶
- 字符串字段和字符串值之间的映射
- 定义哈希表
hmset user:1000 username antirez birthyear 1977 verified 1
- 建立一个名称为
user:1000
的哈希表,建立的键值映射关系为username:antirez
、birthyear:1977
、verified:1
- 获取值
hget user:1000 username hget user:1000 birthyear # 获取全部键和值 hgetall user:1000
- 修改值
hincrby user:1000 birthyear 10 hincrby user:1000 birthyear 10
Redis 无序集合¶
- (哈希表 unordered_set)
- 支持进行集合运算
- 创建集合
sadd myset 1 2 3
- 查看集合元素
smembers myset
- 查看集合元素是否存在(返回 01)
sismember myset 3
Redis 有序集合¶
- 支持获取范围元素
- 添加元素\<排序用的键 元素>
zadd hackers 1940 "Alan Kay" zadd hackers 1957 "Sophie Wilson" add hackers 1953 "Richard Stallman"
- 范围查看集合
zrange hackers 0 -1 zrevrange hackers 0 -1
特殊数据类型¶
- Streams:Redis Streams 是一个高性能、持久化、有序的消息传递系统。它的数据模型类似于一个消息队列,支持多个消费者并发消费,还能实现消息确认、重试等功能。
- Geospatial indexes:Redis 可以支持地理位置信息的存储和索引,通过经纬度可以进行地理位置查询。这个特性可以帮助应用程序进行地理位置相关的搜索和推荐等功能。
- Bitmaps:Redis 提供了一种叫做位图(Bitmap)的数据结构,用于存储一些只有 0 或 1 的二进制数据,可以进行位运算和统计等操作。这个特性可以帮助应用程序进行某些计数和排重操作。
- Bitfields:Redis 还支持一种比位图更加灵活的数据结构,叫做位域(Bitfield)。它可以存储不同长度的二进制数据,并支持各种位运算和类型转换。
- HyperLogLog:HyperLogLog 是一种基数估计算法,可以在不占用太多内存的情况下估算出一个集合的基数(即元素个数)。这个特性可以帮助应用程序进行数据统计和分析等操作。
常用命令¶
key 操作¶
- Redis 命令大小不敏感
- 判断 key 是否存在
exits keyname
- 删除 key
del keyname
- 获取 key 元素的数据类型
type keyname
- 返回匹配的 key 列表
keys keypattern
如keys my*
- 随机获取已经存在的 key,数据库为空则返回空字符串
randomkey
- 重命名 key
rename oldname newname
(存在则覆盖新键)renamenx
存在则更新失败 - 获取数据库中 key 的总数目
dbsize
flushdb
:清空当前数据库中的所有键。flushall
:清空所有数据库中的所有键。
时间¶
- 设置 key 的生存周期(多长时间之后自动删除)
expire key 10
表示 10 s 之后自动删除 key- 在添加 key 时设置时间
set key 100 ex 30
- 在添加 key 时设置时间
- 查询 key 的剩余时间
ttl key
设置&配置信息¶
config get
:用来读取运行 Redis 服务器的配置参数。config set
:用于更改运行 Redis 服务器的配置参数。auth
:认证密码。> config get requirepass # 查看密码 > config set requirepass test123 # 设置密码为 test123 > config get requirepass # 报错,没有认证 > auth test123 # 认证密码 > config get requirepass
info [section]
:查询 Redis 相关信息。- server: Redis server 的常规信息
- clients: Client 的连接选项
- memory: 存储占用相关信息
- persistence: RDB and AOF 相关信息
- stats: 常规统计
- replication: Master/Slave 请求信息
- cpu: CPU 占用信息统计
- cluster: Redis 集群信息
- keyspace: 数据库信息统计
- all: 返回所有信息
- default: 返回常规设置信息
高级应用¶
安全性¶
- 为客户端连接制定密码
- 使用
config set
命令的 requirepass 参数,具体格式为config set requirepass [password]"
- 登录时可以使用
redis-cli -a password
。 - 登录后可以使用
auth password
。
- 登录时可以使用
主从复制¶
- 为了分担服务器压力,会在特定情况下部署多台服务器分别用于缓存的读和写操作,用于写操作的服务器称为主服务器,用于读操作的服务器称为从服务器。
- 主从复制过程
- Slave 与 Master 建立连接,发送 psync 同步命令。
- Master 会启动一个后台进程,将数据库快照保存到文件中,同时 Master 主进程会开始收集新的写命令并缓存。
- 后台完成保存后,就将此文件发送给 Slave。
- Slave 将此文件保存到磁盘上。
- 主从复制特点
- 可以拥有多个 Slave。
- 多个 Slave 可以连接同一个 Master 外,还可以连接到其它的 Slave。(当 Master 宕机后,相连的 Slave 转变为 Master)。
- 主从复制不会阻塞 Master,在同步数据时, Master 可以继续处理 Client 请求。
- 提高了系统的可伸缩性。
- 如果在同步过程中,主服务器修改了一篇博客,而同步到从服务器上的博客是修改前的。这时候就会出现时间差,即修改了博客过后,在访问网站的时候还是原来的数据,这是因为从服务器还未同步最新的更改,这也就意味着非阻塞式的同步只能应用于对读数据延迟接受度较高的场景。
事务处理¶
- 只能保证 client 发起的事务中的命令可以连续的执行,而且不会插入其它的 client 命令
- 它不会在事务过程中出错时恢复到之前的状态,这在实际应用中导致我们不能依赖 redis 的事务来保证数据一致性。
- 使用 multi 和 exec 保住事务代码
> multi > set name a > set name b > exec > get name
虚拟化机制¶
- Redis 是一个支持持久化的内存数据库,Redis 需要经常将内存中的数据同步到磁盘来保证持久化。
- 快照:将内存中的数据以快照的方式写入到二进制文件(可以配置快照频率,如时间间隔、操作数目等)使用快照仍然会丢失最后一次快照之后的所有修改
- AOF:将收到的每一个写命令都通过 write 存储到文件,redis 启动时通过保存的写命令来重建数据库
- 由于 os 会在内核中缓存 write 做的修改,所以可能不是立即写到磁盘上,这样 aof 方式的持久化也还是有可能会丢失一部分数据。
虚拟内存¶
- 把不经常访问的数据从内存交换到磁盘,节约内存空间(对于 redis 这样的内存数据库,内存总是不够用的)
八股¶
基础功能及原理¶
- Redis 的使用场景
- 缓存:Redis 最常用的场景是作为缓存,Redis 通过支持多种高级数据结构,例如哈希表、有序集合和位图等,可以提供高效的缓存功能。
- 实时数据处理:Redis 可以用于实时数据处理,例如在大型游戏或社交网络中跟踪用户活动或统计实时事件。由于 Redis 的高性能和低延迟,它可以快速处理大量的实时数据,并提供高效的查询和分析功能。
- 分布式锁:Redis 还可以用于实现分布式锁。分布式锁用于协调分布式系统中的并发访问,确保每个操作都具有唯一的锁。Redis 可以提供原子操作,使其成为一种可靠的分布式锁解决方案。
- 消息队列:Redis 还可以用作消息队列。消息队列用于异步处理任务,例如将电子邮件或推送通知发送到目标用户或将任务传递给后台处理程序。Redis 可以通过支持多种数据结构(例如队列、堆栈和发布/订阅)来简化消息队列的实现。
- 地理位置服务:Redis 还可以用于实现地理位置服务,例如在地图应用程序中查找附近的商店或定位服务。Redis 可以利用其支持的地理位置索引和排序功能来实现这种应用程序需求。
基本数据结构¶
-
字符串:使用 SDS 简单动态字符串
- 可以快速获取字符串长度、防止缓冲区溢出(记录长度、申请空间扩容)、更好的管理空间提高性能(空间预分配、惰性空间释放)
- 二进制安全,可以存储图片、视频等各种二进制文件
- 线程安全:使用 Redis 的 INCR 命令可以实现原子性的自增操作,避免并发访问时出现数据不一致的问题。
-
有序集合 zset
- 当元素较多时使用跳跃表和哈希表实现,哈希表存储键值、使用跳跃表来维护有序
- 元素较少时使用压缩链表(元素编码为连续二进制块,并进行排序)
- 跳表:二分思想,使得链表可以实现在 logn 时间的随机访问
- 为什么使用跳表而不是平衡树:相对平衡树的中序遍历,跳表实现范围访问更为容易;跳表的插入删除更为容易;性能稳定;空间复杂度相对较低
-
有序集合的应用场景:动态排行榜;去重;分页;优先队列等
-
哈希表
- 当哈希表中键值对数量较少,且键和值的大小都比较小时,Redis 使用压缩列表来实现哈希表;当键值对数量增多时,Redis 会自动将其转化为哈希表,使用字典作为底层实现。
-
用途:
- 存储用户信息键值对
- 存储配置信息等
-
HyperLogLog 解决统计问题
- Redis HyperLogLog 是一种基数算法,用于估计一个集合中不重复元素的数量。 占用内存很少,而误差控制在 0.81% 以内
- 通过给定 n 个的元素集合,记录集合中数字的比特串第一个 1 出现位置的最大值 k,也可以理解为统计二进制低位连续为零的最大个数。通过 k 值可以估算集合中不重复元素的数量 m,m 近似等于 2^k。(可以类比为抛硬币得到 00001 需要投多少次)
- 用途:统计活跃用户数、访问 ip 等大数据场景
- 例子:对 ip 的统计过程
- 通过哈希函数将输入的 ip 转化为一组均匀分布的随机数
- 将随机数根据最初几位划分子集
- 在每个子集内,找到哈希值中最大的前导零的数量,并将这个数量存储起来。
- 基于每个子集计数的最大前导零的数量,计算所有子集的估计值的调和平均值。
- 最后,通过对调和平均值进行一些数学处理,我们得到了对整个数据集(所有IP地址)的唯一元素数量的估计。
实践分析¶
性能¶
-
Redis 使用单线程模型,通过使用异步 IO 和 I/O 多路复用,使得单线程的 Redis 实例可以同时处理多个客户端请求,并提供了多线程模式的支持。简化了并发数据处理的复杂性,同时保持了高性能和低延迟
- 文件事件:文件事件与网络I/O操作相关,例如客户端连接、数据读写等。
- 时间事件:时间事件与定时任务相关,例如定期删除过期键、持久化操作等。
- 首先进行 IO 操作,时间选择器将监视 I/O 事件表。一旦文件事件就绪,Redis 将首先处理文件事件,然后处理时间事件;有一个中心循环,负责监听事件(包括文件事件和时间事件),并将它们分发到相应的处理程序。(I/O 多路复用)
- Redis 单线程,指的是"其网络 I/O 和键值对读写是由一个线程完成的",而其他的如持久化存储模块、集群支撑模块等是多线程的。
- 优点:简单易维护、高效
- 缺点:无法利用多核 cpu,无法处理阻塞操作
-
Redis 多线程的实现(6.0 之后)
- Redis 是一个 I/O 操作密集的框架,性能瓶颈不在 CPU 上,而是在内存和网络上,使用多线程来优化 IO 操作,事件处理线程每获取一个可读事件,就会将所有就绪的可读事件分配给 I/O 线程等待。所有 I/O 线程完成读操作后,事件处理线程开始进行任务处理。处理结束后,写事件也分配给 I/O 线程,事件处理线程会等待所有 I/O 线程完成写操作。
- 优点:利用多核 cpu、处理阻塞操作
- 缺点:增加复杂度和配置项、引入线程切换和同步的开销、不能完全解决单线程执行命令的瓶颈
事务¶
- redis 事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。
- 特点:
- 单独的隔离操作(事务执行过程中不会被其它命令打断)
- 没有隔离级别
- 不保证原子性,事务执行失败不会回滚
- 不支持回滚:
- 只能主动放弃事务,不支持回滚
- 因为认为错误通常都是由于编程错误造成,不会出现在生产环境,并且这种复杂功能不符合 redis 简单高效的设计目标
消息队列¶
-
消息队列的设计要点
- 消息可靠性:消息不会丢失或重复
- 消息顺序性:按照发送顺序被处理
- 消息并发性:多个同时收发、高吞吐
- 消息可扩展:根据负载动态增加或减少资源
-
list 实现消息队列
- 支持双向插入删除,可以用于实现 FIFO 消息队列
- 如果消费者在获取或处理消息的过程中出现异常,导致消息没有被正确处理,那么这条消息就会丢失。为了解决这个问题,我们需要引入一个消息确认机制(ACK),即消费者在成功处理完一条消息后,向生产者或队列报告这条消息已经被处理。
- Streams 实现消息队列
- 提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每一个客户端的访问位置,还能保证消息不丢失。
- 它就像是个仅追加内容的消息链表,把所有加入的消息都串起来,每个消息都有一个唯一的 ID 和对应的内容。而且消息是持久化的。
kafka * 订阅发布模式实现 * 发布者(publisher):负责发送消息到指定的频道(channel)。 * 订阅者(subscriber):负责从指定的频道接收消息。 * 频道(channel):负责传递消息,相当于一个消息队列。
- List 实现消息队列:优点是使用 Redis List 数据结构和方法简单易用。缺点是需要手动实现消息确认、消息消费、消息重试等功能。
- 基于发布/订阅模式实现的消息队列:使用 Redis 的发布/订阅功能,发布者发布消息到特定的频道 (channel),订阅者订阅该频道,收到消息后进行处理。优点是高并发性能好,消息传递快速,缺点是不支持消息持久化,不支持消息重试,订阅者需要一直在线才能接收到消息。
-
Streams 实现消息队列:支持消息持久化、消费者组、消息确认等功能。Streams 使用类似于发布/订阅的方式,消息生产者将消息写入 Stream 中,消息消费者通过 XREAD 命令读取消息。优点是支持消息持久化、消费者组、消息确认、消息重试等功能,缺点是相对复杂,需要使用 Redis 5.0 或以上版本。
-
消息队列的应用:异步处理任务、流量削峰、消息通信
性能优化¶
- Dedis 为什么这么快
- 基于内存进行访问
- 简单的数据结构:数据结构被优化以支持快速的数据访问和修改
- 单线程模型
- IO 多路复用
- 支持高速事务
- 主从复制高可用
- 性能影响因素:内存、网络、cpu
- 内存不足:
- 合理地估算数据量和内存需求,根据实际情况选择合适的硬件配置和扩容方案。
- 合理地设置过期时间,让不再需要的数据自动删除,释放内存空间。
- 合理地选择数据结构,利用 Redis 提供的各种数据类型和压缩技术,减少内存占用。
- 启用内存淘汰策略,当内存达到一定阈值时,自动删除一些低优先级的数据。
- 网络延迟:
- 尽量将客户端和服务器部署在同一局域网或同一地区,减少网络距离和中间节点。
- 尽量使用高速稳定的网络设备和线路,避免网络拥塞和丢包。
- 尽量减少单次请求的数据量,避免发送大量的小数据或少量的大数据。
- 尽量使用批量操作和管道技术,减少网络请求次数和等待时间。
- cpu 过载:
- 尽量避免使用 CPU 密集型的命令
- 尽量避免使用慢查询或阻塞查询,如 BLPOP、BRPOP 等。
- 尽量避免使用事务或脚本功能,尤其是包含循环或递归的脚本。
- 尽量使用多个 Redis 实例进行分片或集群,分担 CPU 压力。
缓存问题¶
- 缓存雪崩
- 缓存雪崩指的是大量缓存数据同时失效,导致请求全部落到了数据库上,造成数据库压力瞬间增大,甚至宕机的情况。
- 产生原因
- 大量热点数据同时过期,大量请求需要查询数据库
- Redis 故障、缓存系统异常
-
解决方案
- 配置主从复制:当前主节点宕机时从节点可以接管缓存服务
- 配置 Redis 集群,避免单点故障并提供更高的性能和可靠性
-
缓存击穿
- 缓存击穿指的是某个缓存数据过期或不存在,但是又有大量的并发请求同时查询该数据(会同时去请求数据库),导致缓存和数据库同时受到大量请求的冲击,从而导致数据库瞬间压力增大,性能降低,甚至宕机的情况。
- 穿透表示底层数据库没有数据且缓存内也没有数据,击穿表示底层数据库有数据而缓存内没有数据。当热点数据 key 从缓存内失效时,大量访问同时请求这个数据,就会将查询下沉到数据库层,此时数据库层的负载压力会骤增,我们称这种现象为"缓存击穿"。
-
解决方案
- 延长热点 key 的过期时间或者设置永不过期,如排行榜,首页等一定会有高并发的接口;
- 利用互斥锁保证同一时刻只有一个客户端可以查询底层数据库的这个数据,一旦查到数据就缓存至 Redis 内,避免其他大量请求同时穿过 Redis 访问底层数据库;
-
缓存穿透
- 缓存穿透是指恶意的请求或非法的查询访问一个不存在于缓存和数据库中的数据
- 产生原因:
- 恶意攻击:攻击者通过构造恶意请求,不断查询不存在的数据,来占用服务器的资源。
- 查询条件不合理:有时候用户可能会在查询条件中传入一些不存在的数据,如果没有进行有效的校验,这些请求也会穿透缓存直接访问数据库。
- 解决方案
- 在接口层增加校验,不合法的参数直接返回。
- 在缓存查不到,DB 中也没有的情况,可以将对应的 key 的 value 写为 null,或者其他特殊值写入缓存,同时将过期失效时间设置短一点,以免影响正常情况。
- 网关 NG 作一个配置项,为每一个 IP 设置访问阈值。
- 高级用户布隆过滤器
分布式锁¶
- 什么是分布式锁
- 布式锁的作用就是为了协调多个进程或线程的访问,保证它们之间的同步和互斥
-
分布式锁的特点:
- 互斥性:对于同一条数据,只有一台应用可以获取到分布式锁
- 高可用性:一小部分服务器宕机不影响正常使用,这种情况就需要将提供分布式锁的服务以集群的方式部署;
- 防止锁超时:如果客户端没有主动释放锁,服务器会在一段时间之后自动释放锁,防止客户端宕机或者网络不可达时产生死锁;
- 独占性:加锁解锁必须由同一台服务器进行,也就是锁的持有者才可以释放锁,不能出现你加的锁,别人给你解锁了
-
分布式锁的简易实现
SET lock_name my_random_value NX PX 30000
- 设置一个锁,nx 表示只有锁不存在才能 set,px 表示设置一个自动释放时间
- 确认身份:
GET lock_name
并与自己的信息系进行比对 - 释放锁
DEL lock_name
-
可能出现的问题
- 死锁:客户端在释放锁之前崩溃;设置锁过期时间解决
- 解锁操作的原子性:解锁时需要先 get 比对再进行 del 操作,这是非原子的两个操作
- 使用事务功能、使用 Lua 和脚本
- Redis 节点故障后,主备切换的数据一致性
- 当 Master 节点不可用的时候,系统自动切到 Slave 上。但是由于 Redis 的主从复制(Replication)是异步的,这可能导致在宕机切换过程中丧失锁的安全性。
- 自认为持有锁的客户端在对敏感公共资源进行写操作前,先进行校验,确认自己是否确实持有锁
- RedLock
-
内置分布式算法 Redlock
- 基于多个 Redis 节点的分布式锁,即使有节点发生了故障,锁变量仍然是存在的,客户端还是可以完成锁操作。
- 让客户端和多个独立的 Redis 节点依次请求申请加锁,如果客户端能够和半数以上的节点成功地完成加锁操作,那么我们就认为,客户端成功地获得分布式锁,否则加锁失败。
- 第一步是,客户端获取当前时间。
- 第二步是,客户端按顺序依次向 N 个 Redis 节点执行加锁操作。如果某个 Redis 节点发生故障了,为了保证在这种情况下,Redlock 算法能够继续运行,我们需要给「加锁操作」设置一个超时时间(不是对「锁」设置超时时间,而是对「加锁操作」设置超时时间)。
- 第三步是,一旦客户端完成了和所有 Redis 节点的加锁操作,客户端就要计算整个加锁过程的总耗时(t 1)。
- 如果有超过半数的 Redis 节点成功的获取到了锁,并且总耗时没有超过锁的有效时间,那么就是加锁成功
秒杀场景¶
- 秒杀场景的特点
- 秒杀时大量用户会在同一时间同时进行抢购,网站瞬时访问流量激增。
- 秒杀一般是访问请求数量远远大于库存数量,只有少部分用户能够秒杀成功。
- Redis 实现秒杀系统的基本思路是:
- 使用 Redis 的列表作为商品库存队列,将商品 ID 按照库存数量预先放入列表中。
- 使用 Redis 的散列作为订单记录表,将用户 ID 和商品 ID 作为键值对存储在散列中。
- 当用户请求抢购商品时,从商品库存队列中弹出一个商品 ID,并将用户 ID 和商品 ID 存入订单记录表中。
- 如果商品库存队列为空,则表示商品已经售罄,返回失败信息给用户。
高可用高性能¶
-
高可用手段:主从复制、哨兵模式、集群模式
-
主从复制
- 将一个 Redis 实例(主节点)的数据复制到其他 Redis 实例(从节点)来提高 Redis 的可用性和性能。主节点是唯一可写的节点,而从节点只能进行读操作。
- edis 主从复制可以提高 Redis 的可用性,因为如果主节点发生故障,从节点可以自动升级为主节点,继续提供服务,这就是 Redis 的故障转移机制。
- 工作流程:建立连接,数据同步(发送快照),命令传播(同步写命令)
- 优点:
- 数据备份
- 负载均衡
- 故障转移
-
缺点:
- 数据一致性较差
- 写性能较差(只能主节点写)
- 故障恢复需要人工干预(手动选择新的主节点)
-
哨兵模式
- 监控:Sentinel 会定期检查 Redis 实例的健康状态,如主从节点是否正常运行、网络连接是否正常等。
- 故障检测:当 Sentinel 检测到主节点不可用时,它会自动选举出一个新的主节点,然后通知所有客户端使用新的主节点进行操作。
- 自动故障转移:Sentinel 会自动进行故障转移操作,将一个从节点提升为主节点,保证 Redis 集群在主节点宕机时仍能正常运行。
- Sentinel 通过发布和订阅模式来实现实例状态的监控和管理。当一个 Redis 实例状态发生变化时,它会向 Sentinel 发布一个消息,Sentinel 节点会接收并处理这些消息,并更新集群状态。
- 优点:
- 自动化
- 可靠性
- 扩展性:支持动态添加和删除节点,非常适合分布式环境下的使用。
-
缺点
- 性能影响,占用资源
- 配置复杂
-
集群模式
- 是 Redis 官方提供的一种分布式解决方案,支持数据的自动分片,能将数据分散在不同的节点上,以实现集群的水平扩展和伸缩。
- 将数据分为多个槽位(slot),集群中的每个 Redis 实例负责维护一部分槽以及槽所映射的键值数据。Redis Cluster 会根据请求中的键值对的槽位,将请求转发给对应的主节点处理。如果请求需要修改数据,该主节点会将数据同步给从节点,保证数据的可靠性。如果主节点宕机,从节点会实现的自动故障转移(不需要 Redis sentinel),选举出一个新的主节点,继续提供服务。
- 优点
- 数据分布:支持数据分片,可以将数据存储在多个节点上
- 高可用:支持主从复制、故障转移
- 自动化管理
-
缺点
- 复杂性
- 一致性:异步赋值
- 使用哈希分片,有的那个键值大小的限制
-
选择
- 如果你的数据量很少,主要是承载高并发高性能的场景,比如你的缓存一般就几个 G,单机足够了
- Redis 主从复制适用于数据量不是很大、读写比例适中。常见的部署是一个主节点 (mater)加多个从节点 (slave),具体需要几个从节点跟工作负载中的读操作的吞吐量有关系。由于主从复制在故障转移过程中需要手动干预,因此需要一定的运维能力。
- Redis Sentinel 是对主从复制的扩展,可以自动进行故障检测和故障转移,具有较高的可靠性和自动化程度。但在大规模集群和高并发场景下,性能和可扩展性方面有限制。
- Redis Cluster 是一种分布式集群方案,可以实现水平扩展和高性能的数据处理能力。主要是针对海量数据、高并发,高可用的场景,但是在一些复杂场景下,如事务、跨节点查询等方面仍然存在一些限制。并且,由于 Redis Cluster 在数据迁移和故障转移过程中需要消耗大量网络带宽,因此在一些特殊场景下可能不太适用。