Redis介绍
该文主要介绍 Redis
。
Redis介绍
Redis
是完全开源的,遵守 BSD
协议,是一个高性能的 key-value
数据库。Redis
发展分为单机版、数据持久化、主从复制、哨兵、分片集群。
1. 单机版1
1.1. 缺点
- 数据丢失:可靠性保证不是很好,单节点有宕机的风险。
redis
数据是在内存中的,redis
宕机重启数据就会丢失。 - 性能问题:单机高性能受限于
CPU
的处理能力,Redis
是单线程的。
2. 数据持久化2
把内存数据写到磁盘上的过程,就是数据持久化。
2.1. 常见数据持久化
- RDB(Redis Database):RDB 以指定的时间间隔执行数据集的时间点快照。
- AOF(Append Only File):AOF 记录服务器接收到的每个写操作。然后可以在服务器启动时再次重播这些操作,从而重建原始数据集。
- RDB + AOF:Redis 先以 RDB 格式在 AOF 文件中写入一个数据快照,再把在这期间产生的每一个写命令,追加到 AOF 文件中。
Redis 4.0 以上版本才支持混合持久化。 注意:混合持久化是对 AOF rewrite 的优化,这意味着使用它必须基于 AOF + AOF rewrite。
2.2. AOF
Redis
写内存由主线程来做,写内存完成后就给客户端返回结果,然后 Redis
用另一个线程去写磁盘,这样就可以避免主线程写磁盘对性能的影响。
缺点:记录每一个写操作导致文件会非常大。
2.3. RDB
缺点:该方式是以固定间隔将数据一次写入磁盘,如果间隔时间是 60 分钟,但是在这期间宕机就会丢失这期间的数据。
2.4. 选择
- 对于大中型的应用,我们既想保证数据完整性又想保证高效率,就应该结合使用
RDB
和AOF
两种方式; - 如果只是需要保证数据的完整性,保护数据不会丢失,那么优先使用
AOF
方式; - 如果是处理大规模的数据恢复,追求更高更快的效率的话,优先使用
RDB
方式。
3. 主从复制
Redis
的复制(Replication)功能允许用户根据一个 Redis
服务器来创建任意多个该服务器的复制品,其中被复制的服务器为主服务器(Master),而通过复制创建出来的复制品则为从服务器(Slave)。只要主从服务器之间的网络连接正常,主服务器就会将写入自己的数据同步更新给从服务器,从而保证主从服务器的数据相同。
数据的复制是单向的,只能由主节点到从节点,简单理解就是从节点只支持读操作,不允许写操作。主要是读高并发的场景下用主从架构。主从模式需要考虑的问题是:当 Master
节点宕机,需要选举产生一个新的 Master
节点,从而保证服务的高可用性。
3.1. 优点
Master/Slave
角色方便水平扩展,QPS
增加,增加Slave
即可;- 降低
Master
读压力,转交给Slave
节点; - 主节点宕机,从节点作为主节点的备份可以随时顶上继续提供服务;
3.2. 缺点
- 一旦主节点宕机,从节点晋升成主节点,需要修改应用方的主节点地址,还需要命令所有从节点去复制新的主节点,整个过程需要人工干预;
4. 哨兵模式
在 Redis 2.8
版本开始,引入了哨兵(Sentinel)这个概念,在主从复制的基础上,哨兵实现了自动化故障恢复。如上图所示,哨兵模式由两部分组成,哨兵节点和数据节点:
- 哨兵节点:哨兵节点是特殊的
Redis
节点,不存储数据; - 数据节点:主节点和从节点都是数据节点。
4.1. 特性
Redis Sentinel
是分布式系统中监控 Redis
主从服务器,并提供主服务器下线时自动故障转移功能的模式。其中三个特性为:
- 监控(Monitoring):
Sentinel
会不断地检查你的主服务器和从服务器是否运作正常; - 提醒(Notification):当被监控的某个
Redis
服务器出现问题时,Sentinel
可以通过API
向管理员或者其他应用程序发送通知; - 自动故障迁移(Automatic failover):当一个主服务器不能正常工作时,
Sentinel
会开始一次自动故障迁移操作。
4.2. 工作原理
- 每个
Sentinel
以每秒一次的频率向它所知的Master
,Slave
以及其他Sentinel
节点发送一个PING
命令; - 如果一个实例(instance)距离最后一次有效回复
PING
命令的时间超过配置文件own-after-milliseconds
选项所指定的值,则这个实例会被Sentinel
标记为主观下线; - 如果一个
Master
被标记为主观下线,那么正在监视这个Master
的所有Sentinel
要以每秒一次的频率确认Master
是否真的进入主观下线状态; - 当有足够数量的
Sentinel
(大于等于配置文件指定的值)在指定的时间范围内确认Master
的确进入了主观下线状态,则Master
会被标记为客观下线; - 如果
Master
处于ODOWN
状态,则投票自动选出新的主节点。将剩余的从节点指向新的主节点继续进行数据复制; - 在正常情况下,每个
Sentinel
会以每 10 秒一次的频率向它已知的所有Master
,Slave
发送INFO
命令;当Master
被Sentinel
标记为客观下线时,Sentinel
向已下线的Master
的所有Slave
发送INFO
命令的频率会从 10 秒一次改为每秒一次; - 若没有足够数量的
Sentinel
同意Master
已经下线,Master
的客观下线状态就会被移除。若Master
重新向Sentinel
的PING
命令返回有效回复,Master
的主观下线状态就会被移除。
4.3. 定时任务
4.4. 主观下线
4.5. 客观下线
4.6. 仲裁
5. 集群模式
5.1. 分片集群
简单来讲,一个实例扛不住写压力,那我们是否可以部署多个实例,然后把这些实例按照一定规则组织起来,把它们当成一个整体,对外提供服务。
- 每个节点各自存储一部分数据,所有节点数据之和才是全量数据
- 制定一个路由规则,对于不同的
key
,把它路由到固定一个实例上进行读写
5.2. Twemproxy、Codis
- 客户端分片:数据分多个实例存储,那寻找
key
的路由规则需要放在客户端来做。这个方案的缺点是,客户端需要维护这个路由规则,需要把路由规则写到你的业务代码中。 - 代理:我们可以在客户端和服务端之间增加一个「中间代理层」,这个代理就是我们经常听到的
Proxy
,路由转发规则,放在这个Proxy
层来维护。这样,客户端就无需关心服务端有多少个Redis
节点了,只需要和这个Proxy
交互即可。Proxy
会把你的请求根据路由规则,转发到对应的Redis
节点上,而且,当集群实例不足以支撑更大的流量请求时,还可以横向扩容,添加新的Redis
实例提升性能,这一切对于你的客户端来说,都是透明无感知的。
它们的特点是集群中的 Redis
节点,都不知道对方的存在,只有客户端或 Proxy
才会统筹数据写到哪里,从哪里读取,而且它们都依赖哨兵集群负责故障自动切换。也就是说我们其实就是把多个孤立的 Redis
节点,自己组合起来使用。
5.3. Redis Cluster
Redis Cluster
无需部署哨兵集群,集群内Redis
节点通过Gossip
协议互相探测健康状态,在故障时可发起自动切换。路由转发规则,
Redis Cluster
也提供了配套的SDK
,只要客户端升级SDK
,就可以和Redis Cluster
集成,SDK
会帮你找到key
对应的Redis
节点进行读写,还能自动适配Redis
节点的增加和删除,业务侧无感知。
5.4. Proxy + Redis Cluster
客户端升级 SDK
,对于新业务应用来说,可能成本不高,但对于老业务来讲,「升级成本」还是比较高的,这对于切换官方 Redis Cluster
方案有不少阻力。各个公司有开始自研针对 Redis Cluster
的 Proxy
,降低客户端的升级成本。
6. 总结
总结一下,我们是如何从 0 到 1,再从 1 到 N 构建一个稳定、高性能的 Redis
集群的,从这之中你可以清晰地看到 Redis 架构演进的整个过程。
- 数据怕丢失 -> 持久化(RDB/AOF)
- 恢复时间久 -> 主从副本(副本随时可切)
- 故障手动切换慢 -> 哨兵集群(自动切换)
- 读存在压力 -> 扩容副本(读写分离)
- 写存在压力/容量瓶颈 -> 分片集群
- 分片集群社区方案 -> Twemproxy、Codis(Redis 节点之间无通信,需要部署哨兵,可横向扩容)
- 分片集群官方方案 -> Redis Cluster (Redis 节点之间 Gossip 协议,无需部署哨兵,可横向扩容)
- 业务侧升级困难 -> Proxy + Redis Cluster(不侵入业务侧)
7. 适用场景
Redis
适合的场景:
- 高性能读写:
Redis
是基于内存的快速Key-Value
存储,读写性能非常高。它适用于需要快速读写操作的应用场景,如缓存、会话存储、实时统计等。 - 数据库查询的缓存:
Redis
可以作为一个缓存层,将常用、耗时的查询结果缓存起来,提高数据库性能。 - 发布订阅系统:
Redis
的发布订阅功能可以用于构建实时通信、消息队列等应用。 - 计数器与排行榜:
Redis
具有原子性操作和高性能的特点,它可以用于实现计数器和排行榜等功能。
MySQL
适合的场景:
- 结构化数据存储:
MySQL
是一种关系型数据库,适合存储和处理结构化数据,支持复杂的查询操作。 - 数据持久化和可靠性:
MySQL
使用磁盘存储数据,具有持久化的能力,能够保证数据在故障情况下的可靠性和可恢复性。 - 复杂查询和数据关系:
MySQL
支持复杂的SQL
查询操作,可以进行数据的连接、关联和聚合等操作,适用于需要进行复杂数据查询的应用场景。 - 事务处理:
MySQL
支持事务处理,可以保证数据的一致性和完整性。