Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets)与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRUeviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。
(1)从物理机上获取redis安装包
(2)安装gcc,解压redis包,进入解压后的目录,开始编译安装(有Makefile文件时,可以直接make编译)
(3)cd redis-5.0.3/utils/,进入到此目录下,执行./install_server.sh命令安装redis
(4)更改配置,重启redis
vim /etc/redis/6379.conf ##设置打开所有接口的6379端口
/etc/init.d/redis_6379 restart ##重启redis
redis的复制功能是支持多个数据库之间的数据同步
一类是主数据库(master),一类是从数据库(slave)
主数据库可以进行读写操作,当发生写操作的时候自动将数据同步到从数据库,而从数据库一般是只读的,并接收主数据库同步过来的数据,一个主数据库可以有多个从数据库,而一个从数据库只能有一个主数据库
从数据库的数据是以自己的主数据库为标准的
实验环境:
server1:172.25.254.1,作redis主服务器
server2:172.25.254.2,作redis从服务器
(1)将server1上解压后的redis安装目录(已make)直接传给server2
(2)在server2(从服务器)上进行编译,./install_server.sh命令安装redis
(3)在server2中配置主从复制,打开所有接口的6379端口,重启redis
vim /etc/redis/6379.conf
使server2是server1的一个从节点
测试:
server1中
redis-cli 进入redis命令行,写入数据并查看
在server2上可以查看到server1写入的数据,实现了基本的主从复制,server2只能读,不能写
redis数据存储位置:/var/lib/redis/6379/dump.rdb
1.sentinel哨兵模式介绍
Sentinel(哨兵)是Redis的高可用性解决方案:由一个或多个Sentinel实例组成的Sentinel系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器。
sentinel可让redis实现主从复制,当一个集群中的master失效之后,sentinel可以选举出一个新的master用于自动接替master的工作,集群中的其他redis服务器自动指向新的master同步数据。一般建议sentinel采取奇数台,防止某一台sentinel无法连接到master导致误切换。
2.Redis 的 Sentinel 系统管理
Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务:
监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。
Redis Sentinel 是一个分布式系统, 你可以在一个架构中运行多个 Sentinel 进程, 这些进程使用流言协议(gossip protocols)来接收关于主服务器是否下线的信息, 并使用投票协议(agreement protocols)来决定是否执行自动故障迁移, 以及选择哪个从服务器作为新的主服务器。
虽然 Redis Sentinel 释出为一个单独的可执行文件 redis-sentinel , 但实际上它只是一个运行在特殊模式下的 Redis 服务器, 你可以在启动一个普通 Redis 服务器时通过给定 –sentinel 选项来启动 Redis Sentinel 。
3.主观下线和客观下线
主观下线(Subjectively Down, 简称 SDOWN)指的是单个 Sentinel 实例对服务器做出的下线判断。
客观下线(Objectively Down, 简称 ODOWN)指的是多个 Sentinel 实例在对同一个服务器做出 SDOWN 判断, 并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服务器下线判断。 (一个 Sentinel 可以通过向另一个 Sentinel 发送 SENTINEL is-master-down-by-addr 命令来询问对方是否认为给定的服务器已下线。)
如果一个服务器没有在 master-down-after-milliseconds 选项所指定的时间内, 对向它发送 PING 命令的 Sentinel 返回一个有效回复(valid reply), 那么 Sentinel 就会将这个服务器标记为主观下线
客观下线条件只适用于主服务器: 对于任何其他类型的 Redis 实例, Sentinel 在将它们判断为下线前不需要进行协商, 所以从服务器或者其他 Sentinel 永远不会达到客观下线条件
只要一个 Sentinel 发现某个主服务器进入了客观下线状态, 这个 Sentinel 就可能会被其他 Sentinel 推选出, 并对失效的主服务器执行自动故障迁移操作。
4.哨兵模式的实现
实验环境:
server1:172.25.254.1,作redis主服务器
server2:172.25.254.2,作redis从服务器
server3:172.25.254.3,作redis从服务器
实验:
上面实验已经实现了server1(master)和server2(slave)之间的主从复制
现在将server3也设置为server1的slave节点,并打开redis
以上就实现了一主(server1)二从(server2、server3)的主从复制
哨兵模式的实现:master宕机时,从master的所有slave中选举出一个新的master出来
(1)在server1/2/3上配置
编辑哨兵模式的配置文件sentinel.conf
server1上开启sentinel进程
redis-server /etc/redis/sentinel.conf --sentinel ##启动运行在 Sentinel 模式下的 Redis 服务器
关闭保护模式
Sentinel监听的master地址,第一个参数是给master起的名字,第二个参数为master IP,第三个为master端口,第四个为当该master挂了的时候,若想将该master判为失效,在Sentine集群中必须至少2个Sentine同意才行,只要该数量不达标,则就不会发生故障迁移
也就是说只要有2个sentinel认为master下线,就认为该master客观下线,启动failover并选举产生新的master
认为多长时间连不上主机判定为主机离线,单位是ms(这里设置10秒)
server2上开启sentinel进程
redis-server /etc/redis/sentinel.conf --sentinel ##启动运行在 Sentinel 模式下的 Redis 服务器
redis-server /etc/redis/sentinel.conf --sentinel ##启动运行在 Sentinel 模式下的 Redis 服务器
可以看到,此时master节点是正常的,三个节点都在正常工作
(2)模拟哨兵模式
重新打开一个server1的shell窗口
使用命令查看此时的master节点和slave节点的信息
[root@server1 ~]# redis-cli
127.0.0.1:6379> info
server1是master节点,server2和server3是slave节点
server1的redis服务被down掉
进程查看,server1的redis-server进程已经关闭
但是server1的redis-sentinel进程依然正常运行,可以参加选举
在server3上发现master由server1切换为server3
在server1上使用远程登陆redis集群中的server2的命令,redis-cli -h 172.25.254.2
可以看到server2是slave,server3是master
重启server1上的redis服务
可以看到server3是master节点,server1是slave节点
注意:
重启server1上的redis服务之前,编辑redis的配置文件,设置server1作为slave节点,master节点是server3
手动去把server1变为slave,而不是选举完之后直接将master置为slave的原因是?
因为server1原来是master,上面会有重要的数据,而且它的slave节点server2和server3上的数据有可能不完全和server1同步,如果此时直接将server1置为slave的话,它会以新的master节点作为参考,丢弃原来的所有数据,这时就可能会造成严重的数据丢失
故障转移分为三个步骤:
1)从下线的主服务的所有从服务里面挑选一个从服务,将其转成主服务
sentinel状态数据结构中保存了主服务的所有从服务信息,领头sentinel按照如下的规则从从服务列表中挑选出新的主服务;
删除列表中处于下线状态的从服务;删除最近5秒没有回复过领头sentinel info信息的从服务;
删除与已下线的主服务断开连接时间超过 down-after-milliseconds*10毫秒的从服务,
这样就能保留从的数据比较新(没有过早的与主断开连接);
领头sentinel从剩下的从列表中选择优先级高的,如果优先级一样,选择偏移量最大的(偏移量大说明复制的数据比较新),
如果偏移量一样,选择运行id最小的从服务。
2)已下线主服务的所有从服务改为复制新的主服务
挑选出新的主服务之后,领头sentinel 向原主服务的从服务发送 slaveof 新主服务 的命令,复制新master。
3)将已下线的主服务设置成新的主服务的从服务,当其回复正常时,复制新的主服务,变成新的主服务的从服务
同理,当已下线的服务重新上线时,sentinel会向其发送slaveof命令,让其成为新主的从。
1.Redis集群介绍
redis从3.0版本开始引入了redis-cluster(集群)
(1)Redis-Cluster采用无中心结构
每个节点都和其它节点通过互ping保持连接,每个节点保存整个集群的状态信息,可以通过连接任意节点读取或者写入数据(甚至是没有数据的空节点)。
(2)只有当集群中的大多数节点同时fail整个集群才fail 一般情况下是集群当中超过一半以上的节点fail的时候,集群才会fail
(3)整个集群有16384个slot,当需要在 Redis 集群中放置一个key-value 时,根据 CRC16(key) mod16384的值,决定将一个key放到哪个桶中。 读取一个key时也是相同的算法。
(4)当主节点fail时从节点会升为主节点,fail的主节点online之后自动变成了从节点
集群:是一个提供多个Redis(分布式)节点间共享数据的程序集
集群部署:Redis 集群的键空间被分割为 16384 hash个槽(slot), 集群的最大节点数量也是 16384 个
关系:cluster>node>slot>key
集群特点:
自动分割数据到不同的节点上
客户端与redis节点直连、不需要中间proxy层
整个集群的部分节点失败或者不可达的情况下能够继续处理命令
所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽
2.redis cluster集群的实现
(1)在server1上创建 6个Redis 节点
mkdir /usr/local/rediscluster/ ##建立新目录
mkdir /usr/local/rediscluster/700{1..6} ##创建子目录作redis节点
vim /usr/local/rediscluster/7001/redis.conf对每个目录中运行一个 Redis 实例
port 7001 ##端口7001,7002,7003,7004,7005,7006
cluster-enabled yes ##开启集群
cluster-config-file nodes.conf ##集群的配置,配置文件首次启动自动生成 7001,7002,7003,7004,7005,7006
cluster-node-timeout 5000 ##请求超时 默认5秒,可自行设置
appendonly yes ##aof日志开启 有需要就开启,它会每次写操作都记录一条日志
pidfile "/usr/local/rediscluster/7001/redis.pid"
logfile "/usr/local/rediscluster/7001/redis.log"
daemonize yes ##redis后台运行
dir "/usr/local/rediscluster/7001"
同理配置其他5个节点,并且开启服务
redis-server /usr/local/rediscluster/700*/redis.conf运行实例
查看7001,7002,7003,7004,7005,7006的运行情况,6个节点全部开启
确保集群处于正常工作状态,查看信息
cluster_enabled:1
(2)在server1上创建redis-cluster集群
指定一主一从:
redis-cli --cluster create --cluster-replicas 1 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006
集群创建好后
集群中有三个master,三个slave,数据完全同步
三个master分别为:7001、7002、7003
7001的slave是7004
7002的slave是7005
7003的slave是7006
(3)测试
redis-cli -c -p 7001
写入数据,之后不管在哪个节点查看都会定向到7002节点去获取数据
数据存储位置:7002/appendonly.aof
down掉节点7002
获取数据时定向到7005节点(7002的从节点),此时7005由slave升级为master
不管在哪个节点查看都会定向到7005节点去获取数据
down掉节点7005(已升级为master)
down掉存放数据的主节点和从节点后,查看不到数据
重新启动7005节点后,可以查看到数据
3.集群重新分片
实验环境:在上面实验基础上进行操作
Redis 集群的数据分片
Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责一部分hash槽,如当前集群有3个节点,那么:
节点 A 包含 0 到 5500号哈希槽.
节点 B 包含5501 到 11000 号哈希槽.
节点 C 包含11001 到 16384号哈希槽.
这种结构很容易添加或者删除节点.
比如如果我想新添加个节点D, 我需要从节点 A, B, C中得部分槽到D上. 如果我想移除节点A,需要将A中的槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可.
由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态
实验:
(1)建立新的节点7007,7008
(2)在集群中添加节点
redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7001 ##将7007加入集群
redis-cli --cluster add-node 127.0.0.1:7008 127.0.0.1:7007 --cluster-slave --cluster-master-id 28c7de62c53ad1c573882a57f2cfa996581508f3 ##将7008加入集群中作为7007的slave
新加的节点哈希槽为0,没有slave
7008是7007的slave节点
(3)分配hash槽
当前7007节点没有哈希槽
指定数量来分配hash槽
redis-cli --cluster reshard 127.0.0.1:7001
输入500,从集群中有哈希槽的节点获取
redis-cli --cluster check 127.0.0.1:7001
平均分配hash槽
将集群中所有节点的哈希槽进行重新整合,均分哈希槽
redis-cli --cluster rebalance --cluster-threshold 1 --cluster-use-empty-masters 127.0.0.1:7001