文章大纲
一, 基础知识学习
二, Redis 常见的几种架构及优缺点总结
三, Redis 之 Redis Sentinel(哨兵)实战
四, Redis 之 Redis Cluster(分布式集群)实战
五, Java 之 Jedis 连接 Redis(Redis Cluster 版本)
六, Redis 之云平台介绍
七, 项目源码与资料下载
八, 参考文章
一, 基础知识学习
Redis 的基础包括以下内容, 可参考文章 https://www.cnblogs.com/WUXIAOCHANG/p/10832330.html 进行学习
(1)安装并设置开机自动启动
(2)Redis 文件结构
(3)Redis 启动方式
(4)Redis 持久化
(5)Redis 配置文件详解
(7)Redis 图形化工具
(8)Java 之 Jedis 连接 Redis 单机
二, Redis 常见的几种架构及优缺点总结
1. Redis 单副本
Redis 单副本, 采用单个 Redis 节点部署架构, 没有备用节点实时同步数据, 不提供数据持久化和备份策略, 适用于数据可靠性要求不高的纯缓存业务场景.
优点
架构简单, 部署方便;
高性价比: 缓存使用时无需备用节点(单实例可用性可以用 supervisor 或 crontab 保证), 当然为了满足业务的高可用性, 也可以牺牲一个备用节点, 但同时刻只有一个实例对外提供服务;
高性能.
缺点
不保证数据的可靠性;
在缓存使用, 进程重启后, 数据丢失, 即使有备用的节点解决高可用性, 但是仍然不能解决缓存预热问题, 因此不适用于数据可靠性要求高的业务;
高性能受限于单核 CPU 的处理能力(Redis 是单线程机制),CPU 为主要瓶颈, 所以适合操作命令简单, 排序, 计算较少的场景. 也可以考虑用 Memcached 替代.
2. Redis 多副本(主从)
Redis 多副本, 采用主从 (replication) 部署结构, 相较于单副本而言最大的特点就是主从实例间数据实时同步, 并且提供数据持久化和备份策略. 主从实例部署在不同的物理服务器上, 根据公司的基础环境配置, 可以实现同时对外提供服务和读写分离策略.
优点
高可靠性: 一方面, 采用双机主备架构, 能够在主库出现故障时自动进行主备切换, 从库提升为主库提供服务, 保证服务平稳运行; 另一方面, 开启数据持久化功能和配置合理的备份策略, 能有效的解决数据误操作和数据异常丢失的问题;
读写分离策略: 从节点可以扩展主库节点的读能力, 有效应对大并发量的读操作.
缺点
故障恢复复杂, 如果没有 RedisHA 系统(需要开发), 当主库节点出现故障时, 需要手动将一个从节点晋升为主节点, 同时需要通知业务方变更配置, 并且需要让其它从库节点去复制新主库节点, 整个过程需要人为干预, 比较繁琐;
主库的写能力受到单机的限制, 可以考虑分片;
主库的存储能力受到单机的限制, 可以考虑 Pika;
原生复制的弊端在早期的版本中也会比较突出, 如: Redis 复制中断后, Slave 会发起 psync, 此时如果同步不成功, 则会进行全量同步, 主库执行全量备份的同时可能会造成毫秒或秒级的卡顿; 又由于 COW 机制, 导致极端情况下的主库内存溢出, 程序异常退出或宕机; 主库节点生成备份文件导致服务器磁盘 IO 和 CPU(压缩)资源消耗; 发送数 GB 大小的备份文件导致服务器出口带宽暴增, 阻塞请求, 建议升级到最新版本.
3. Redis Sentinel(哨兵)
Redis Sentinel 是社区版本推出的原生高可用解决方案, 其部署架构主要包括两部分: Redis Sentinel 集群和 Redis 数据集群.
其中 Redis Sentinel 集群是由若干 Sentinel 节点组成的分布式集群, 可以实现故障发现, 故障自动转移, 配置中心和客户端通知. Redis Sentinel 的节点数量要满足 2n+1(n>=1)的奇数个.
优点
Redis Sentinel 集群部署简单;
能够解决 Redis 主从模式下的高可用切换问题;
很方便实现 Redis 数据节点的线形扩展, 轻松突破 Redis 自身单线程瓶颈, 可极大满足 Redis 大容量或高性能的业务需求;
可以实现一套 Sentinel 监控一组 Redis 数据节点或多组数据节点.
缺点
部署相对 Redis 主从模式要复杂一些, 原理理解更繁琐;
资源浪费, Redis 数据节点中 slave 节点作为备份节点不提供服务;
Redis Sentinel 主要是针对 Redis 数据节点中的主节点的高可用切换, 对 Redis 的数据节点做失败判定分为主观下线和客观下线两种, 对于 Redis 的从节点有对节点做主观下线操作, 并不执行故障转移.
不能解决读写分离问题, 实现起来相对复杂.
建议
如果监控同一业务, 可以选择一套 Sentinel 集群监控多组 Redis 数据节点的方案, 反之选择一套 Sentinel 监控一组 Redis 数据节点的方案.
sentinel monitor <master-name> <ip> <port> <quorum> 配置中的 < quorum > 建议设置成 Sentinel 节点的一半加 1, 当 Sentinel 部署在多个 IDC 的时候, 单个 IDC 部署的 Sentinel 数量不建议超过(Sentinel 数量 - quorum).
合理设置参数, 防止误切, 控制切换灵敏度控制:
- a. quorum
- b. down-after-milliseconds 30000
- c. failover-timeout 180000
- d. maxclient
- e. timeout
部署的各个节点服务器时间尽量要同步, 否则日志的时序性会混乱.
Redis 建议使用 pipeline 和 multi-keys 操作, 减少 RTT 次数, 提高请求效率.
自行搞定配置中心(zookeeper), 方便客户端对实例的链接访问.
4. Redis Cluster
Redis Cluster 是社区版推出的 Redis 分布式集群解决方案, 主要解决 Redis 分布式方面的需求, 比如, 当遇到单机内存, 并发和流量等瓶颈的时候, Redis Cluster 能起到很好的负载均衡的目的.
Redis Cluster 集群节点最小配置 6 个节点以上(3 主 3 从), 其中主节点提供读写操作, 从节点作为备用节点, 不提供请求, 只作为故障转移使用.
Redis Cluster 采用虚拟槽分区, 所有的键根据哈希函数映射到 0~16383 个整数槽内, 每个节点负责维护一部分槽以及槽所印映射的键值数据.
优点
无中心架构;
数据按照 slot 存储分布在多个节点, 节点间数据共享, 可动态调整数据分布;
可扩展性: 可线性扩展到 1000 多个节点, 节点可动态添加或删除;
高可用性: 部分节点不可用时, 集群仍可用. 通过增加 Slave 做 standby 数据副本, 能够实现故障自动 failover, 节点之间通过 gossip 协议交换状态信息, 用投票机制完成 Slave 到 Master 的角色提升;
降低运维成本, 提高系统的扩展性和可用性.
缺点
Client 实现复杂, 驱动要求实现 Smart Client, 缓存 slots mapping 信息并及时更新, 提高了开发难度, 客户端的不成熟影响业务的稳定性. 目前仅 JedisCluster 相对成熟, 异常处理部分还不完善, 比如常见的 "max redirect exception".
节点会因为某些原因发生阻塞(阻塞时间大于 clutser-node-timeout), 被判断下线, 这种 failover 是没有必要的.
数据通过异步复制, 不保证数据的强一致性.
多个业务使用同一套集群时, 无法根据统计区分冷热数据, 资源隔离性较差, 容易出现相互影响的情况.
Slave 在集群中充当 "冷备", 不能缓解读压力, 当然可以通过 SDK 的合理设计来提高 Slave 资源的利用率.
Key 批量操作限制, 如使用 mset,mget 目前只支持具有相同 slot 值的 Key 执行批量操作. 对于映射为不同 slot 值的 Key 由于 Keys 不支持跨 slot 查询, 所以执行 mset,mget,sunion 等操作支持不友好.
Key 事务操作支持有限, 只支持多 key 在同一节点上的事务操作, 当多个 Key 分布于不同的节点上时无法使用事务功能.
Key 作为数据分区的最小粒度, 不能将一个很大的键值对象如 hash,list 等映射到不同的节点.
不支持多数据库空间, 单机下的 Redis 可以支持到 16 个数据库, 集群模式下只能使用 1 个数据库空间, 即 db 0.
复制结构只支持一层, 从节点只能复制主节点, 不支持嵌套树状复制结构.
避免产生 hot-key, 导致主库节点成为系统的短板.
避免产生 big-key, 导致网卡撑爆, 慢查询等.
重试时间应该大于 cluster-node-time 时间.
Redis Cluster 不建议使用 pipeline 和 multi-keys 操作, 减少 max redirect 产生的场景.
5. Redis 自研
Redis 自研的高可用解决方案, 主要体现在配置中心, 故障探测和 failover 的处理机制上, 通常需要根据企业业务的实际线上环境来定制化.
优点
高可靠性, 高可用性;
自主可控性高;
贴切业务实际需求, 可缩性好, 兼容性好.
缺点
实现复杂, 开发成本高;
需要建立配套的周边设施, 如监控, 域名服务, 存储元数据信息的数据库等;
维护成本高.
三, Redis 之 Redis Sentinel(哨兵)实战
1. 实战的项目架构
采用一主 (MASTER) 二从 (SLAVE) 三哨兵 (SENTINEL) 的架构
2. 将下载的 Redis 复制 3 分, 分别命名如下:
3. 修改三个 Reids 的配置文件
3.1 配置主从
(1)master_6379 文件夹中 Redis.Windows.conf 文件配置
port 6379
(2)slave_6380 文件夹中 Redis.Windows.conf 文件配置
- port 6380
- slaveof 127.0.0.1 6379
(3)slave_6381 文件夹中 Redis.Windows.conf 文件配置
- port 6381
- slaveof 127.0.0.1 6379
3.2 哨兵配置
每一个 Redis 目录中都创建一个文 sentinel.conf 文件
master_6379 的 sentinel.conf 文件配置如下
- # 当前 Sentinel 服务运行的端口
- port 26379
- #master
- #Sentinel 去监视一个名为 mymaster 的主 Redis 实例, 这个主实例的 IP 地址为本机地址 127.0.0.1, 端口号为 6379,
- # 而将这个主实例判断为失效至少需要 2 个 Sentinel 进程的同意, 只要同意 Sentinel 的数量不达标, 自动 failover 就不会执行
- sentinel monitor mymaster 127.0.0.1 6379 1
- # 指定了 Sentinel 认为 Redis 实例已经失效所需的毫秒数. 当 实例超过该时间没有返回 PING, 或者直接返回错误, 那么 Sentinel 将这个实例标记为主观下线.
- # 只有一个 Sentinel 进程将实例标记为主观下线并不一定会引起实例的自动故障迁移: 只有在足够数量的 Sentinel 都将一个实例标记为主观下线之后, 实例才会被标记为客观下线, 这时自动故障迁移才会执行
- sentinel down-after-milliseconds mymaster 5000
- # 指定了在执行故障转移时, 最多可以有多少个从 Redis 实例在同步新的主实例, 在从 Redis 实例较多的情况下这个数字越小, 同步的时间越长, 完成故障转移所需的时间就越长
- sentinel config-epoch mymaster 12
- # 如果在该时间 (ms) 内未能完成 failover 操作, 则认为该 failover 失败
- sentinel leader-epoch mymaster 13
slave_6380 中的 sentinel.conf 文件配置
- # 当前 Sentine2 服务运行的端口
- port 26479
- #slave1
- sentinel monitor mymaster 127.0.0.1 6379 1
- sentinel down-after-milliseconds mymaster 5000
- sentinel config-epoch mymaster 12
- sentinel leader-epoch mymaster 13
slave_6381 中的 sentinel.conf 文件配置
- # 当前 Sentine3 服务运行的端口
- port 26579
- #slave2
- sentinel monitor mymaster 127.0.0.1 6379 1
- sentinel down-after-milliseconds mymaster 5000
- sentinel config-epoch mymaster 12
- sentinel leader-epoch mymaster 13
4. 启动服务
编写启动 Redis 脚本
编写一个 bat 来启动 Redis, 在每个节点目录下建立 startup.bat, 内容如下:
- title master_6379
- Redis-server.exe Redis.Windows.conf
温馨提示:
(1)title 后名称需与 Reids 文件夹名称一致
(2)可以直接运行 startup.bat 来启动 Redis, 也可以在 Redis 安装目录下用命令 Redis-server.exe Redis.Windows.conf 直接启动
编写 sentinel 启动脚本
编写一个 bat 来启动 sentinel, 在每个节点目录下建立 startup_sentinel.bat, 内容如下:
- title master_6379
- Redis-server.exe sentinel.conf --sentinel
温馨提示:
(1) title 命名规则 Redis 文件夹名, 注意 "--sentinel" 不是注释, 必须存在
(2) 另外启动 sentinel 还可以在 Redis 安装目录下用命令 Redis-sentinel sentinel.conf 来启动
5. Redis 服务启动成功
master 6379
slave 6380
slave 6381
6. sentinel 服务启动成功
sentinel 26379
sentinel 26479
sentinel 26579
7. 服务查看
7.1 查看 Redis 服务状态, 命令: info replication
master 6379
slave 6380
slave 6381
7.2 查看 sentinel 的状态, 命令: info sentinel
8. Redis 主从自动 failover 测试
停止 master 服务器, 查看剩余服务器的状态
slave 6380
slave 6381
从上图中可以看出来, master 的服务器端口从 6379 变成了 6380, 也就是说 Redis 自动的实现了主从切换,
我们可以在查看下 sentinel 的状态, 如下:
我们发现 sentinel 监控到 127.0.0.1:6379 已经无法 ping 通了, 切换 master 服务器为 127.0.0.1:6380
温馨提示: 在实际操作中, 不一定 master 为 6380, 可能是 6381, 具体看当时执行策略.
四, Redis 之 Redis Cluster(分布式集群)实战
1. 实战的项目架构
(1)3 个主节点, 建议配置 3 个从节点, 其余 3 个作为各个主节点的从节点(也是官网推荐的模式), 所以需要 6 台虚拟机. 主节点崩溃, 从节点的 Redis 就会提升为主节点, 代替原来的主节点工作, 崩溃的主 Redis 恢复工作后, 会再成为从节点
(2)集群
(3)主从复制
(4)哨兵模式
(5)分片
2. 所需软件
(1)Redis
(2)Ruby 语言运行环境
(3)Redis 的 Ruby 驱动 Redis-xxxx.Gem
(4)创建 Redis 集群的工具 Redis-trib.rb
3. 下载 Redis 并创建相应集群目录
把 Redis 解压后, 再复制出 5 份, 配置 三主三从集群. 由于 Redis 默认端口号为 6379, 那么其它 5 份的端口可以为 6380,6381,6382,6383,6384. 并且把目录使用端口号命名
4. 修改配置文件
打开每个 Redis 目录下的文件 Redis.Windows.conf, 修改里面的端口号分别对应相对应的文件夹名: 6379,6380,6381,6382,6383,6384, 再修改集群支持配置, 将以下配置前面的 #去掉.
- cluster-enabled yes
- cluster-config-file nodes-6379.conf
- cluster-node-timeout 15000
- appendonly yes
cluster-config-file nodes-6379.conf 是为该节点的配置信息, 这里使用 nodes - 端口. conf 命名方法. 服务启动后会在目录生成该文件(为 cluster-config-file nodes - 文件夹名字. conf)
编写启动脚本, 或者进入每个端口命名的文件夹下启动服务, 具体可以参考第三的内容
编写一个 bat 来启动 Redis, 在每个节点目录下建立 startup.bat, 内容如下:
- title Redis-6379
- Redis-server.exe Redis.Windows.conf
温馨提示: title 后面为文件夹名称
5. 安装 Ruby
Redis 的集群使用 Ruby 脚本编写, 所以系统需要有 Ruby 环境 , 下载地址
https://rubyinstaller.org/downloads/
安装时 3 个选项都勾选.
6. 安装 Redis 的 Ruby 驱动 Redis-xxxx.Gem
下载地址 :https://rubygems.org/pages/download
下载后解压, 当前目录切换到解压目录中, 如 D:\Program Files\Redis_cluster\RubyGems-2.7.7 然后命令行执行 Ruby setup.rb
再用 Gem 安装 Redis : 切换到 Redis 安装目录, 需要在命令行中, 执行 Gem install Redis
7. 安装集群脚本 Redis-trib
下载地址 https://raw.githubusercontent.com/antirez/redis/unstable/src/redis-trib.rb
打开该链接把里面的脚本保存为 Redis-trib.rb, 建议保存到一个 Redis 的目录下(不用每个都放), 例如放到 6379 目录下.
温馨提示: 现在打开这个链接中的代码已不支持 Redis 5.0 以下的版本了, 因为 redis5.0 以上不再需要 Redis-trib.rb 了, 而是使用自带的 Redis-cli 作为创建集群的命令了, 老版本的 Redis-trib.rb 可在文章的项目源码与参考资料中进行下载
8. 启动每个节点并且执行集群构建脚本
把每个节点下的 start.bat 双击启动, 在切换到存放了 Redis-trib.rb 的 Redis 目录在命令行中执行以下内容:
Redis-trib.rb create --replicas 1 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384
温馨提示:
(1)--replicas 1 表示每个主数据库拥有从数据库个数为 1.master 节点不能少于 3 个, 所以我们用了 6 个 Redis
(2)三个主从之间的对应关系由策略进行决定, 不一定是 6379 是主, 6380 是它的从, 但是分配完之后, 会有三主三从
(3)如果出现 Redis-trib.rb is not longer available! 如果 Redis 版本是 5.0 以上, 则使用如下命令:
Redis-cli --cluster create 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 --cluster-replicas 1
(4) 集群命令创建一次后, 以后都不需要再次执行, 就算服务器重启都不需要, 集群伸缩应该需要
在出现 Can I set the above configuration? (type 'yes' to accept): 请确定并输入 yes . 成功后的结果如下:
9. 连接集群进行测试
使用 Redis 客户端 Redis-cli.exe 来查看数据记录数, 以及集群相关信息
命令: Redis-cli -c -h "地址" -p "端口号" ; c 表示集群
查看集群的信息, 命令: cluster info
查看主从关系, 命令: info replication
主库显示信息:
从库显示信息:
查看各个节点分配 slot, 命令 cluster nodes
可以看到有 3 个 master,3 个 slave
以及可以看到 master 各自的 slot 分布情况
10. Redis 集群数据分配策略
采用一种叫做哈希槽 (hash slot)的方式来分配数据, Redis cluster 默认分配了 16384 个 slot, 当我们 set 一个 key 时, 会用 CRC16 算法来取模得到所属的 slot, 然后将这个 key 分到哈希槽区间的节点上, 具体算法就是: CRC16(key) % 16384
注意的是: 必须要 3 个以上的主节点, 否则在创建集群时会失败, 三个节点分别承担的 slot 区间是:
节点 A 覆盖 0-5460;
节点 B 覆盖 5461-10922;
节点 C 覆盖 10923-16383.
五, Java 之 Jedis 连接 Redis(Redis Cluster 版本)
1. 使用 idea 新建 maven 项目
创建后的项目结构如下:
2. pom.xml 文件添加 jar 包依赖
- <?xml version="1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>com.wxc</groupId>
- <artifactId>com-redis2</artifactId>
- <version>1.0-SNAPSHOT</version>
- <dependencies>
- <!-- 添加测试依赖 -->
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.12</version>
- </dependency>
- <!-- 添加 redis 依赖 -->
- <dependency>
- <groupId>Redis.clients</groupId>
- <artifactId>jedis</artifactId>
- <version>2.7.2</version>
- </dependency>
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-lang3</artifactId>
- <version>3.3.2</version>
- </dependency>
- </dependencies>
- </project>
3. 新建 JedisclusterTest.java 进行集群连接测试
- package com.wxc.Redis;
- import org.junit.Test;
- import Redis.clients.jedis.HostAndPort;
- import Redis.clients.jedis.JedisCluster;
- import Redis.clients.jedis.JedisPoolConfig;
- import java.io.IOException;
- import java.util.HashSet;
- import java.util.Set;
- public class JedisclusterTest {
- // 连接 Redis 集群
- @Test
- public void testJedisCluster() throws Exception {
- // 创建一个 JedisCluster 对象
- Set<HostAndPort> nodes = new HashSet<HostAndPort>();
- nodes.add(new HostAndPort("127.0.0.1", 6379));
- nodes.add(new HostAndPort("127.0.0.1", 6380));
- nodes.add(new HostAndPort("127.0.0.1", 6381));
- nodes.add(new HostAndPort("127.0.0.1", 6382));
- nodes.add(new HostAndPort("127.0.0.1", 6383));
- nodes.add(new HostAndPort("127.0.0.1", 6384));
- System.out.println("开始连接 redis 集群");
- // 在 nodes 中指定每个节点的地址
- //jedisCluster 在系统中是单例的.
- JedisCluster jedisCluster = new JedisCluster(nodes);
- System.out.println("初始化数据");
- jedisCluster.set("name2", "zhangsan");
- jedisCluster.set("value2", "100");
- String name = jedisCluster.get("name");
- String value = jedisCluster.get("value");
- System.out.println(name);
- System.out.println(value);
- // 系统关闭时关闭 jedisCluster
- jedisCluster.close();
- }
- }
4. 运行项目
5. 测试集群故障转移与主从备份
5.1 查看主从关系
从图中我们可以看出, 6379,6381,6383 是主节点, 其他是从节点
5.2 测试故障自动转移
现在我们将 6381 的服务断开, 之后再查看一次服务
我们可以看到这两个服务已经挂了, 之后我们再次运行 java 项目, 这次我们把 key 改为 name3,value3
再次运行 java 项目
可以看到集群数据操作成功
5.3 查看集群自动主从备份
现在我们用 Redis 客户端工具打开连接, 进行数据查看, 我们可以看到 name3 和 value3 都插入成功了
刚刚我们的 6381 服务是关闭的, 我们现在重新打开, 再看看 6381 数据是否会自动同步
打开之后, 我们发现其数据已经自动同步
七, 参考文章
- http://database.ctocio.com.cn/239/14564239.shtml
- https://blog.csdn.net/weixin_41846320/article/details/83654766
- https://blog.csdn.net/weixin_41846320/article/details/83753182
来源: https://www.cnblogs.com/WUXIAOCHANG/p/10851334.html