文章

Redis介绍

Redis介绍

该文主要介绍 Redis

Redis介绍

Redis 是完全开源的,遵守 BSD 协议,是一个高性能的 key-value 数据库。Redis 发展分为单机版、数据持久化、主从复制、哨兵、分片集群。

1. 单机版1

img

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

img

Redis 写内存由主线程来做,写内存完成后就给客户端返回结果,然后 Redis 用另一个线程去写磁盘,这样就可以避免主线程写磁盘对性能的影响。

缺点:记录每一个写操作导致文件会非常大。

2.3. RDB

缺点:该方式是以固定间隔将数据一次写入磁盘,如果间隔时间是 60 分钟,但是在这期间宕机就会丢失这期间的数据。

2.4. 选择

  • 对于大中型的应用,我们既想保证数据完整性又想保证高效率,就应该结合使用 RDBAOF 两种方式;
  • 如果只是需要保证数据的完整性,保护数据不会丢失,那么优先使用 AOF 方式;
  • 如果是处理大规模的数据恢复,追求更高更快的效率的话,优先使用 RDB 方式。

3. 主从复制

img

Redis 的复制(Replication)功能允许用户根据一个 Redis 服务器来创建任意多个该服务器的复制品,其中被复制的服务器为主服务器(Master),而通过复制创建出来的复制品则为从服务器(Slave)。只要主从服务器之间的网络连接正常,主服务器就会将写入自己的数据同步更新给从服务器,从而保证主从服务器的数据相同。

数据的复制是单向的,只能由主节点到从节点,简单理解就是从节点只支持读操作,不允许写操作。主要是读高并发的场景下用主从架构。主从模式需要考虑的问题是:当 Master 节点宕机,需要选举产生一个新的 Master 节点,从而保证服务的高可用性。

3.1. 优点

  • Master/Slave 角色方便水平扩展,QPS 增加,增加 Slave 即可;
  • 降低 Master 读压力,转交给 Slave 节点;
  • 主节点宕机,从节点作为主节点的备份可以随时顶上继续提供服务;

3.2. 缺点

  • 一旦主节点宕机,从节点晋升成主节点,需要修改应用方的主节点地址,还需要命令所有从节点去复制新的主节点,整个过程需要人工干预;

4. 哨兵模式

img

Redis 2.8 版本开始,引入了哨兵(Sentinel)这个概念,在主从复制的基础上,哨兵实现了自动化故障恢复。如上图所示,哨兵模式由两部分组成,哨兵节点和数据节点:

  • 哨兵节点:哨兵节点是特殊的 Redis 节点,不存储数据;
  • 数据节点:主节点和从节点都是数据节点。

4.1. 特性

Redis Sentinel 是分布式系统中监控 Redis 主从服务器,并提供主服务器下线时自动故障转移功能的模式。其中三个特性为:

  • 监控(Monitoring):Sentinel 会不断地检查你的主服务器和从服务器是否运作正常;
  • 提醒(Notification):当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知;
  • 自动故障迁移(Automatic failover):当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作。

4.2. 工作原理

  1. 每个 Sentinel 以每秒一次的频率向它所知的 MasterSlave 以及其他 Sentinel 节点发送一个 PING 命令;
  2. 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过配置文件 own-after-milliseconds 选项所指定的值,则这个实例会被 Sentinel 标记为主观下线;
  3. 如果一个 Master 被标记为主观下线,那么正在监视这个 Master 的所有 Sentinel 要以每秒一次的频率确认 Master 是否真的进入主观下线状态;
  4. 当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认 Master 的确进入了主观下线状态,则 Master 会被标记为客观下线;
  5. 如果 Master 处于 ODOWN 状态,则投票自动选出新的主节点。将剩余的从节点指向新的主节点继续进行数据复制;
  6. 在正常情况下,每个 Sentinel 会以每 10 秒一次的频率向它已知的所有 MasterSlave 发送 INFO 命令;当 MasterSentinel 标记为客观下线时,Sentinel 向已下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次;
  7. 若没有足够数量的 Sentinel 同意 Master 已经下线,Master 的客观下线状态就会被移除。若 Master 重新向 SentinelPING 命令返回有效回复,Master 的主观下线状态就会被移除。

4.3. 定时任务

4.4. 主观下线

4.5. 客观下线

4.6. 仲裁

5. 集群模式

5.1. 分片集群

简单来讲,一个实例扛不住写压力,那我们是否可以部署多个实例,然后把这些实例按照一定规则组织起来,把它们当成一个整体,对外提供服务。

  • 每个节点各自存储一部分数据,所有节点数据之和才是全量数据
  • 制定一个路由规则,对于不同的 key,把它路由到固定一个实例上进行读写

5.2. Twemproxy、Codis

img

  • 客户端分片:数据分多个实例存储,那寻找 key 的路由规则需要放在客户端来做。这个方案的缺点是,客户端需要维护这个路由规则,需要把路由规则写到你的业务代码中。
  • 代理:我们可以在客户端和服务端之间增加一个「中间代理层」,这个代理就是我们经常听到的 Proxy,路由转发规则,放在这个 Proxy 层来维护。这样,客户端就无需关心服务端有多少个 Redis 节点了,只需要和这个 Proxy 交互即可。Proxy 会把你的请求根据路由规则,转发到对应的 Redis 节点上,而且,当集群实例不足以支撑更大的流量请求时,还可以横向扩容,添加新的 Redis 实例提升性能,这一切对于你的客户端来说,都是透明无感知的。

它们的特点是集群中的 Redis 节点,都不知道对方的存在,只有客户端或 Proxy 才会统筹数据写到哪里,从哪里读取,而且它们都依赖哨兵集群负责故障自动切换。也就是说我们其实就是把多个孤立的 Redis 节点,自己组合起来使用。

5.3. Redis Cluster

img

  • Redis Cluster 无需部署哨兵集群,集群内 Redis 节点通过 Gossip 协议互相探测健康状态,在故障时可发起自动切换。

  • 路由转发规则,Redis Cluster 也提供了配套的 SDK,只要客户端升级 SDK,就可以和 Redis Cluster 集成,SDK 会帮你找到 key 对应的 Redis 节点进行读写,还能自动适配 Redis 节点的增加和删除,业务侧无感知。

5.4. Proxy + Redis Cluster

img

客户端升级 SDK,对于新业务应用来说,可能成本不高,但对于老业务来讲,「升级成本」还是比较高的,这对于切换官方 Redis Cluster 方案有不少阻力。各个公司有开始自研针对 Redis ClusterProxy,降低客户端的升级成本。

6. 总结

总结一下,我们是如何从 0 到 1,再从 1 到 N 构建一个稳定、高性能的 Redis 集群的,从这之中你可以清晰地看到 Redis 架构演进的整个过程。

  1. 数据怕丢失 -> 持久化(RDB/AOF)
  2. 恢复时间久 -> 主从副本(副本随时可切)
  3. 故障手动切换慢 -> 哨兵集群(自动切换)
  4. 读存在压力 -> 扩容副本(读写分离)
  5. 写存在压力/容量瓶颈 -> 分片集群
  6. 分片集群社区方案 -> Twemproxy、Codis(Redis 节点之间无通信,需要部署哨兵,可横向扩容)
  7. 分片集群官方方案 -> Redis Cluster (Redis 节点之间 Gossip 协议,无需部署哨兵,可横向扩容)
  8. 业务侧升级困难 -> Proxy + Redis Cluster(不侵入业务侧)

7. 适用场景

Redis 适合的场景:

  • 高性能读写:Redis 是基于内存的快速 Key-Value 存储,读写性能非常高。它适用于需要快速读写操作的应用场景,如缓存、会话存储、实时统计等。
  • 数据库查询的缓存:Redis 可以作为一个缓存层,将常用、耗时的查询结果缓存起来,提高数据库性能。
  • 发布订阅系统:Redis 的发布订阅功能可以用于构建实时通信、消息队列等应用。
  • 计数器与排行榜:Redis 具有原子性操作和高性能的特点,它可以用于实现计数器和排行榜等功能。

MySQL 适合的场景:

  • 结构化数据存储:MySQL 是一种关系型数据库,适合存储和处理结构化数据,支持复杂的查询操作。
  • 数据持久化和可靠性:MySQL 使用磁盘存储数据,具有持久化的能力,能够保证数据在故障情况下的可靠性和可恢复性。
  • 复杂查询和数据关系:MySQL 支持复杂的 SQL 查询操作,可以进行数据的连接、关联和聚合等操作,适用于需要进行复杂数据查询的应用场景。
  • 事务处理:MySQL 支持事务处理,可以保证数据的一致性和完整性。

参考

本文由作者按照 CC BY 4.0 进行授权