Redis笔记(二、Redis单实例到集群)

Redis 部署方案
单节点
默认情况下Redis 为单示例模式,安装简单,使用也便捷. 生产环境中存在单节点问题,受限于单机的内存,不具备扩展的能力。
Redis 安装
1. 下载安装包 https://redis.io 下载最最新版本
2. 解压缩 tar -zxf redis-3.0.1.tar.gz
3. cd redis-3.0.1 ;make install;
4. 修改配置文件配置守护后台运行
vi redis.conf; daemonize yes
5. 启动Redis
redis-server   /app/redis-3.0.1/redis.conf
6. 使用redis-cli 环境连接,默认的端口为6379,不修改可以不填
redis-cli  -p 6379
  Redis笔记(二、Redis单实例到集群)_第1张图片
7. 安装完毕后可使用Java客户端实现Jedis来操作Redis.指令可参考官网文档和Jedis Api.
Redis 主从复制
预备知识
主从架构--> 主[Master],从[Slave]
基于Redis的复制特性,允许Slave节点从Master节点中精确进行数据复制,类似于关系型数据库Oracle\Mysql的数据复制.链接断开时Slave节点自动重连到Master节点,始终尝试进行精确数据复制.有以下三种复制策略.
主从节点状态良好-->主节点发送一系列的命令到从节点保持对从节点的更新[写入\过期\删除]等
主从网络中断-->从节点重新连上后先试图同步自网络断开期间错过的数据流.
局部同步不可用-->从节点要求重新同步,执行更复杂的操作,主节点创建所有数据的完整快照并发送到从节点,并在数据集更改时继续发送命令流.
Redis 默认使用异步复制,从节点异步确认接收到来自于主节点的数据.
客户端可以使用WAIT命令请求同步复制某些数据,只能确保在另一个Redis实例中有指定数量的公认副本.在故障转移期间由于不同原因造成的故障转移,或者依赖于Redis持久性的配置,仍然可能在故障期间丢失数据.
Redis 复制采用异步方式,从节点异步的确认回复主节点同步到从节点的数据量
一个Master可以有多个Slaves
Slaves 节点也可以拥有Slaves节点
Master节点上复制是非阻塞的
复制很大程度上也是非阻塞的
复制可用于扩展伸缩性,也可用于为只读查询提供多个Slave
可以使用复制来避免主节点向磁盘写入数据,***   -->实验特性

主节点关闭持久化时安全复制
主从模式中建议对主从都进行持久化,当由于磁盘缓慢导致延迟的时候这是不可取的,如果对主节点采用非持久化则应该配置在机器重启后避免主节点自动重启.
以下故障模式,数据将从主从以及所有从节点中删除
A作为主节点关闭其持久化,B、C作为A的从节点.
节点A奔溃,系统重启后A节点配置了自动重启,由于关闭了持久化,导致A节点以一个空的数据集启动.
节点B\C从A节点复制数据,从而销毁自己的数据副本.数据丢失!
复制的工作原理
Master节点存储了副本的ID,一个大的随机字符串,用于标记数据集发送情况,主节点持有发送给从节点的复制流的偏移,主节点将对新数据集的修改更新到从节点,偏移量由主节点进行维护,偏移量保持递增的   -->  [Replication ID, offset]
定义主节点数据集的版本
Slave连接到Master时使用自己的PSYNC命令发送旧的在Master中的复制ID,和自己当前消费的偏移量,通过这种方式Master只需发送所需的增量部分,如果Master缓存区没有足够的backlog,或者Slave引用了一个过期的偏移,这种情况下从头开始获取数据集的完整副本.
完整的数据同步过程:
Master启动一个后台进程将数据写入并生成RDB文件,并开始缓存从客户端收到的所有的写命令,后台进程保存完成后,Master将数据库文件传输给Slave节点,Slave将数据保存在磁盘上加载到内从中.Master向Slave发送缓存的命令,复制正常运行.
无磁盘复制
2.8.18后的版本支持直接将RDB文件发送到Slave节点从而绕靠缓慢的磁盘同步.
见redis.conf配置
主从复制配置
在Slave节点中配置 slaveof 192.168.1.1 6379
其它参数见redis.conf说明
只读的副本
默认情况下副本为只读的 -->slave-read-only 选项控制 -->可以通过进一步的禁用Redis命令来提高只读的安全性[网络不一定被禁用-->Redis-cli可访问].
可写的Slave是本地化的,其写指令不具备传播性.
Master-Slave权限验证
Master可要求Slave认证
只在满足最小副本数时写
Redis2.8+可以配置只有至少N个Slave节点连接到主服务器的情况下才允许Master执行写操作.
原理
Reids 每秒向Master服务器发送ping信号,并确认复制流的数量.
Master记录Slave发送ping信号的时间作为最后的心跳时间.
用户可配置最小Master数量,以及不得大于的最大延迟时间
min-slaves-to-write -->Master写要求的最小Slaves数量
min-slaves-max-lag -->Slave ping请求的最大延迟时间
Redis Replication 处理Keys过期
Keys的过期依赖于节点计算过期时间的能力.即使使用Lua 脚本修改这些Keys Redis也可以正确的处理Keys的过期
Reidis 不依赖于Master\Slave的时钟同步
1. Slaves 不过期keys,相反等待master将keys过期,当Master中的一个key过期[或者被LRU淘汰],会生成一个DEL 命令发送给所有的Slaves.
2. Master不能实时提供DEL 指令,Slaves使用自己的逻辑时钟检查并为只读操作报告Key并不存在,这样不违反数据一致性[Slave随后将收到DEL指令],通过这种逻辑,Slave避免过期的key任然存在并被客户端感知。
3. Lua Scripting 执行期间不执行任何keys过期操作,Lua 运行期间Master中时间被冻结,给定的key只处于存在和不存在状态,Lua脚本被完全复制到Slaves中执行.
如果一个Slave被提升为Master,将开始独立过期Keys,不在依赖于Master
Info & Role
info -->info [replication] -->显示复制相关的信息
rele -->显示当前节点的角色信息
Redis 持久化
Reids为内从数据库,运行时数据被加载到内存中加速读写速度,Redis提供了一定的策略用于数据的持久化,防止数据丢失.
RDB在指定时间间隔持续性的创建数据集在指定时间点的快照
AOF[Append-only file]记录服务记录接收到的每一个写操作,在服务意外重启后进行数据集重建.AOF记录的格式为Redis协议相同-->数据量非常大的情况下快速重建数据集
Redis 允许禁用持久性,
同一Reids示例,可以结合RDB和AOF,这种情况下AOF文件将被用来重建完整数据集 -->AOF文件保存的是最完整的
RDB优势
非常紧凑的单文件时间节点表示,指定时间间隔进行数据快照.
非常适于灾备恢复,将单一压缩文件传输到远程数据中心.
使Redis性能最大化,快照由独立线程维护
允许更快速的重新启动大型集群
RDB劣势
不能将数据丢失的几率降低到0,
需要子进程fork()完成快照任务,数据集很大的话可能会耗费大量时间
AOF优势
使Redis持久化更有保证,可以有不同的同步策略,[不同步,每秒,每次查询],默认每秒同步一次到磁盘,刷新使用后台线程执行,不影响写入,默认的配置最多损失1S的写入.
AOF是附加日志文件,如果断电不用查找,不会出现损坏问题,Redis提供了AOF文件修复工具,
当AOF文件过大的时候Redis会自动重写它,重写是完全安全的,Redis 继续追加到旧文件,会创建一个能容下当前数据集的最小文件,一旦第二个文件准备好Redis交换两文件.开始追加到新的文件.
AOF易于理解,包含了一个一个的操作日志.AOF文件可以被导出.
AOF缺点
对于同一数据集,AOF通常被RDB大
按精确的语意AOF比RDB慢
罕见的BUG[BRPOPLPUSH导致AOF产生不能在重新加载时复制完全相同的数据集]
快照
默认情况下Reids的快照文件名为dump.rdb,可以配置Redis在N秒有M个变化就执行快照.或者手动调用SAVA \BGSAVE 命令
fork()子进程-->写新的快照文件-->替换旧的快照文件
追加文件
完全持久化的保证,使用一下配置启用
appendonly yes
日志重写
Redis支持在不中断响应的情况下重写AOF日志文件,2.4+可自动触发日志重写.
Redis可配置AOF缓存刷新到磁盘的策略:
每个命令都刷新到磁盘 --> Very very slow  very safe.
每秒刷新一次 --> 足够块,灾难时可能丢失1S的数据
从不刷新 -->
AOF文件修复
创建AOF文件的备份,--> redis-check-aof --fix 修复--> diff -u 查看区别 -->使用修复的文件重启集群
日志重写工作原理
fork()子进程
子进程写新的AOF文件到缓存目录,
父进程在内存中缓存所有新的更改,(同时在旧文件总写入更改)
子进程重写完成后,父进程收到信号,在新的文件末尾追加缓冲区的内容
重写完成,开始将新数据添加到新文件中.
备份Redis 数据
直接定期的备份RDB文件即可.
灾备
将RDB定期上传云存储
定期上传远端存储
Redis HA
Reids Sentinel(哨兵)用来为Redis提供高可用特性,Sentinel还提供了监控\通知\为客户端提供配置等特性.
监控--> Sentinel不断检查Redis Master实例的工作状态
通知-->Sentinel通过API方式通知系统管理员\其它的计算机程序-->Redis实例故障
自动故障转移-->Master节点故障后,Sentinel可以启动故障转移过程,将一个Slave提升为Master,其它的Slave也修改使用行的Master来复制数据,并且告知使用Redis服务期的应用程序使用新的地址.
提供配置-->充当发现客户端的角色,客户端连接到Sentinel-->请求当前Redis Master节点的地址,如果发生故障转移将报告客户端新的Master地址。
Sentinel 分布式特性
Redis Sentinel 是一个分布式系统,Sensinel可以同时运行多个实例之间互相协调
多个Sensinel 同时确认一个给定的Master是否故障,确认后执行故障检测-->降低误报概率
即使不是所有的Sentinel都正常工作,也可以使系统更强壮
Sentinel入门
基础知识
1. Sentinel支持分布式部署,使用最好三个以上的Sentinel节点
2. Sentinel应该以独立的虚拟机或者计算机进行隔离 -->独立失败
3. Sentinel +Redis 分布式部署不能保证在故障期间保留Master已经确认的写入,由于Redis使用异步复制
4. 客户端需要支持Sentinel连接
5. 配置需要在开发环境中配置测试好在上线
6. 涉及Docker, 或者其它网络地址转换或端口映射的时候需要谨慎配置
创建Sentinel
最新版本为Sentinel2 -->使用更强大和简单的预测算法重写最初的Sentinel实现.
使用2.8+版本.
运行Sentinel
两种启动方式
redis-sentinel /path/to/sentinel.conf -->
redis-server /path/to/sentinel.conf --sentinel -->
Sentinel运行时必须使用自己的配置文件,默认情况下Sentinel监听26379端口,
配置Sentinel
参考Reids提供的默认的Sentinel的配置文件sentinel.conf
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1

sentinel monitor resque 192.168.1.3 6380 4
sentinel down-after-milliseconds resque 10000
sentinel failover-timeout resque 180000
sentinel parallel-syncs resque 5
指定监控的Master,给不同的Master一个指定的名字,不需要配置Slave节点[由Sentinel自动发现]
Sentinel自动发现并更新配置,并提供相关Slave的信息(重启时保留),每次故障转移一个Slave被提升为Master,每发现一个新的哨兵都会重写配置文件.
配置Sentinel监控
sentinel monitor -->第一个参数指定Master的名字-->第二个指定Master的IP-->第三个指定Master的端口
quorum 指的是需要判定Master不可用的Sentinel的数量,该参数只是用于检测故障,为执行故障转移其中一个Sentinel将被选举为Leader执行故障转移.Leader通过选举投票产生,负责执行故障转移的Sentinel至少要获得半数以上Senginel的投票.
其它配置
sentinel ,
down-after-milliseconds -->毫秒,超过该时间若收不到Master的ping信号或者收到一个错误,则Sentinel认为Master节点失败.
parallel-syncs -->设置在失败后有多少个Slave可以同步新的Master的数据
Sentinal标准配置

Redis笔记(二、Redis单实例到集群)_第2张图片

  如上所示,有三个隔离的节点,一个节点部署Master+Sentinel,另外两节点部署Slave+Sentinel.

M1故障-->S2+S3判定M1故障-->进行故障转移-->客户端正常访问 -->可能会存在以下情况

Redis笔记(二、Redis单实例到集群)_第3张图片

由于网络分区M1S1被隔离,R2被提升为Master客户端C1任然和M1在同一个网络分区,C1写入的这部分数据将永久丢失. 可通过一下配置来尽可能的避免:

min-slaves-to-write 1 -->至少需要一个Slave可用

min-slaves-max-lag 10 -->Slave超时时间

Sentinal在客户端
如果只有两个节点,一个Master一个Slave,可以将Sentinel放在客户端 -->quorum = 2
  Redis笔记(二、Redis单实例到集群)_第4张图片
Sentinel和客户端在一起,大多数客户端都能连接到Master就没什么问题,M1故障可进行自动故障转移,
Sentinel和客户端绑定在一起,客户机和M1网络断开Sentinel无法进行设置.
混合设置
如果客户端数量少于三个,可以使用混合设置.

Redis笔记(二、Redis单实例到集群)_第5张图片

案例

A节点-->Master+Sentinel
B 节点-->Slave+Sentinel
C 节点-->Slave+Sentinel
A配置
1. redis.conf -->
min-slaves-to-write 1
min-slaves-max-lag 10
2. sentinel.conf-->
port 26379
sentinel monitor mymaster 111.111.111.224 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 2
4. 启动Redis  &Sentinel
redis-server  /app/redis-3.0.1/redis.conf
redis-server  /app/redis-3.0.1/sentinel.conf  --sentinel 或者
redis-sentinel  /app/redis-3.0.1/sentinel.conf
B配置
1. redis.conf
slaveof 111.111.111.224 6379
slave-read-only yes
2. sentinel.conf
port 26379
sentinel monitor mymaster 111.111.111.224 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 2
3. 启动Redis&Sentinal
redis-server /app/redis-3.0.1/redis.conf
redis-sentinel  /app/redis-3.0.1/sentinel.conf
C配置
1. redis.conf
slaveof 111.111.111.224 6379
slave-read-only yes
2. sentinel.conf
port 26379
sentinel monitor mymaster 111.111.111.224 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 2
3. 启动Redis&Sentinal
redis-server /app/redis-3.0.1/redis.conf
redis-sentinel  /app/redis-3.0.1/sentinel.conf
查看Sentinel状态
使用Redis-cli连接Sentinel
redis-cli  -p 26379
1. 查看指定master的状态,--> sentinel master mymaster
 
2. 查看Slave状态 --> SENTINEL slaves mymaster
 
3. 查看Sentinel状态 --> SENTINEL sentinels mymaster
 
4. 获取当前主机的地址 --> SENTINEL get-master-addr-by-name mymaster
5. 其它命令
redis-cli  -p 6379 DEBUG sleep 50 -->阻塞当前节点50秒

Redis 集群
3.0+
Redis集群解决方案-->数据自动分布在多个Redis节点中共享,Redis集群为Redis节点提供了一定的可用性,大多数节点不可用时集群故障.
多个节点之间自动分割数据的能力.
节点的子集或者部分出现通信故障时,能够继续操作.
Redis 集群TCP端口
每个Redis集群节点都需要打开两个TCP端口,一个用于给客户端连接[6379],和一个数据端口[连接端口+10000]用于集群的数据总线,是一个使用二进制协议的点到点的通信协议.总线用于故障检测、配置更新、故障转移授权等.
Redis 集群数据分片
Redis没有使用一致性哈希,使用”hash slot”的概念进行数据切分.Redis 集群中有16384个散列槽,Redis的键经过取模对应到16384槽中的一个上.Redis集群中的每个节点都负责Hash solt中的一个子集[0-16383].
只要所有涉及到单个命令执行(事物、Lua脚本)的键都属于同一个Hash Solt,那么Redis集群就支持多个键的操作.用户可以使用一个名为 hash tags强制多个键成为同一个Hash Solt的一部分. hash tags使用{}标识,放在key的最后部分,
Redis 集群主从模型
Reids集群使用主从复制,每个Hash Solt 使用一个Master(1)主节点 --> Slaves(N)从节点的主备模型.
Redis 集群一致性保证
Redis集群不能保证数据的强一致性,Redis集群使用异步的复制方式,允许同步复制,需要在性能和一致性之间取得平衡.
Redis 集群配置参数
cluster-enabled --> 是否启用Redis集群
cluster-config-file -->集群自动维护,不需要手动维护
cluster-node-timeout -->集群节点最大超时时间,如果主节点超时将被Slave节点替换.
cluster-slave-validity-factor -->0,Slave将始终尝试进行故障转移对应的Master,
如果为正数用来判断slave与master断开的时间,如果为正数则Slave节点断开Master节点的时间大于节点超时时间(cluster-node-timeout)*有效因子(cluster-slave-validity-factor)的值则该节点不能被选为Master节点,防止过期的Slave节点被选为Master而导致数据丢失.
cluster-migration-barrier -->Master的Slave数大于该值时,Slave才能迁移到其它节点.
cluster-require-full-coverage --> 默认yes,只有所有的Hash Solt都被分配出去集群才允许接受写入,no允许在Hash Solt没有完全分配时提供查询服务,只有部分键可以被处理.
创建Redis集群
以下配置一个Redis集群,建议至少使用6个节点,三个主节点每个主节点一个从节点.
#后台运行
daemonize yes
#pid文件位置
pidfile "/app/redis-3.0.1/7000/redis.pid"
#节点端口
port 7000
#节点日志文件位置
logfile "/app/redis-3.0.1/7000/7000.log"
#数据库数量
databases 1
#快照文件位置
dbfilename "7000.rdb"
#实例的工作目录
dir "/app/redis-3.0.1/7000"
#启用AOF文件
appendonly yes
#启用Redis集群模式
cluster-enabled yes
#集群节点配置文件-->不需要手动配置
cluster-config-file nodes.conf
#集群中节点超时
cluster-node-timeout 5000
下面流程在一个Linux主机上创建一个有6个节点的Redis集群.
1. mkdir 7000 7001 7002 7003 7004 7005
2. 拷贝redis.conf到7000 7001 7002 7003 7004 7005目录参考以上配置修改700*为对应的目录,其余保持一致.
3. 启动Redis节点
redis-server  /app/redis-3.0.1/7000/redis.conf
分别启动6个节点
 
4. 通过redis-trib 创建Redis集群,是一个Ruby程序,需要安装redis gem去运行redis-trib脚本.

gem install redis

Redis笔记(二、Redis单实例到集群)_第6张图片

5. 检查当前集群状态
./redis-trib.rb  check localhost:7000

当前集群16384个槽都未被分配出去

Redis笔记(二、Redis单实例到集群)_第7张图片

6. 创建Redis集群

./redis-trib.rb  create  --replicas  1  localhost:7000 localhost:7003 localhost:7001 localhost:7004  localhost:7002 localhost:7005 

Redis笔记(二、Redis单实例到集群)_第8张图片

使用Redis默认的Solt分配方案,集群创建失败… 总结下不能使用主机名…

Redis笔记(二、Redis单实例到集群)_第9张图片

7. 删除节点,同时会将节点下线,在此加入的时候需要将nodes.conf文件清理掉! 删除7001,7003,7004,7005节点并清理对应的nodes.conf文件后重启.
redis-trib.rb del-node  localhost:7000  32607595f0e718ee97692eb762e9152d38ffbb5a 
8. 添加一个节点作为指定节点的Slave,需要使用ip地址而不能使用主机名...
src/redis-trib.rb  add-node --slave --master-id 9d6ebdac22053d5923f193437aa1c8ed806d9f1d  111.111.111.224:7004 111.111.111.224:7000

9. 重复上述步骤,知道每个Master都有对应的Salve且所有Hash Solt被分配出去

Redis笔记(二、Redis单实例到集群)_第10张图片

重新切分集群
查看当前节点信息
redis-cli  -p 7000 cluster nodes
添加一个主节点到集群
src/redis-trib.rb  add-node --master-id e47fe240eb6aefc8fa0099d6908b6c2cbf0612a2  111.111.111.224:7005 111.111.111.224:7000
自动副本迁移
默认情况下对于一个每个Redis的每个主节点都应该有至少一个副本,当主节点异常后提升副本为主节点,如果发生副本在次异常的场景将导致集群不可用,或者使用了更多的副本,但是需要更多的资源,Redis 集群可以实现自动的副本迁移,在集群内部自动的将副本数多的节点的副本转移给副本少的节点作为副本,寻求一个平衡,遵循以下规则.
集群尝试从副本最多的主节点中迁移副本
为从中获益,只需要向集群中的几个主节点多添加几个副本即可
使用cluster-migration-barrier进行配置,主节点的备份大于该值其从节点才可以迁移为其它节点[孤立的主节点]的从节点

你可能感兴趣的:(Redis)