单机/单点
单点故障/瓶颈:多个节点负载:面向数据:
一变多(一致性<弱一致,最终一致性>)à 可用性
最终一致性:一部分角色确认 à 网络分区(脑裂)à 过半机制
镜像:数据容量不变
切片:横向扩展
集群分类
主从复制 Replication:镜像:增删改(主<退化到单节点>)查询负载到从节点
高可用 Sentinel
分布式 twemproxy:切片
集群 Cluster
主从复制 Replication
一个Redis服务可以有多个该服务的复制品,这个Redis服务称为Master,其他复制品称为Slaves,只要网络连接正常,Master会一直将自己的数据更新同步给Slaves,保持主从同步
只有Master可以执行写命令,Slaves只能执行读命令
主从复制 Replication
- 从服务器执行客户端发送的读命令,比如GET、LRANGE、SMEMMBERS、HGET、ZRANGE等等
- 客户端可以连接Slaves执行读请求,来降低Master的读压力
主从复制创建
redis-server --slaveof <master-ip> <master-port>,配置当前服务称为某Redis服务的Slave
# redis-server --port 6380 --slaveof 127.0.0.1 6379
SLAVEOF host port命令,将当前服务器状态从Master修改为别的服务器的Slave
redis > SLAVEOF 192.168.1.1 6379,将服务器转换为Slave
redis > SLAVEOF NO ONE ,将服务器重新恢复到Master,不会丢弃已同步数据
配置方式:启动时,服务器读取配置文件,并自动成为指定服务器的从服务器
slaveof <masterip> <masterport>
slaveof 127.0.0.1 6379
主从复制问题
- 一个Master可以有多个Slaves
- Slave下线,只是读请求的处理性能下降
- Master下线,写请求无法执行
- 其中一台Slave使用SLAVEOF no one命令成为Master,其它Slaves执行SLAVEOF命令指向这个新的Master,从它这里同步数据
以上过程是手动的,能够实现自动,这就需要Sentinel哨兵,实现故障转移Failover操作
高可用 Sentinel哨兵
官方提供的高可用方案,可以用它管理多个Redis服务实例
编译后产生redis-sentinel程序文件
Redis Sentinel是一个分布式系统,可以在一个架构中运行多个Sentinel进程
启动 Sentinel
将src目录下产生redis-sentinel程序文件复制到$REDIS_HOME/bin
启动一个运行在Sentinel模式下的Redis服务实例
redis-sentinel
redis-server /path/to/sentinel.conf --sentinel
Redis Sentinel是一个分布式系统,可以在一个架构中运行多个Sentinel进程
监控 Monitoring
Sentinel会不断检查Master和Slaves是否正常
每一个Sentinel可以监控任意多个Master和该Master下的Slaves
Sentinel网络
监控同一个Master的Sentinel会自动连接,组成一个分布式的Sentinel网络,互相通信并交换彼此关于被监视服务器的信息
右图中3个Sentinel监控着S1和它的2个Slave
服务器下线
- 当一个sentinel认为被监视的服务器已经下线时,它会向网络中的其他Sentinel进行确认,判断该服务器是否真的已经下线
- 如果下线的服务器为主服务器,那么sentinel网络将对下线主服务器进行自动故障转移,通过将下线主服务器的某个从服务器提升为新的主服务器,并让其从服务器转为复制新的主服务器,以此来让系统重新回到上线的状态
Sentinel 配置举例
执行以下两条命令,将创建两个监视主服务器s1的sentinel实例:
$redis-sentinel sentinel1.conf
$redis-sentinel sentinel2.conf
其中sentinel1.conf的内容为:
port 26379
sentinel monitor s1 127.0.0.1 6380 2
sentinel2.conf的内容为:
port 26380
sentinel monitor s1 127.0.0.1 6380 2
Sentinel 总结
-
- 主从复制,解决了读请求的分担,从节点下线,会使得读请求能力有所下降
- Master只有一个,有写请求单点问题
- Sentinel会在Master下线后自动执行Failover操作,提升一台Slave为Master,并让其他Slaves重新成为新Master的Slaves
- 主从复制+哨兵Sentinel只解决了读性能和高可用问题,但是没有解决写性能问题
Redis集群
3.0支持 redis集群
由多个Redis服务器组成的分布式网络服务集群
每一个Redis服务器称为节点Node,节点之间会互相通信。两两相连
Redis集群无中心节点 无主模型
Redis集群节点复制
- Redis集群的每个节点都有两种角色可选:主节点master node、从节点slave node。其中主节点用于存储数据,而从节点则是某个主节点的复制品
- 当用户需要处理更多读请求的时候,添加从节点可以扩展系统的读性能,因为Redis集群重用了单机Redis复制特性的代码,所以集群的复制行为和我们之前介绍的单机复制特性的行为是完全一样的
Redis集群故障转移
- Redis集群的主节点内置了类似Redis Sentinel的节点故障检测和自动故障转移功能,当集群中的某个主节点下线时,集群中的其他在线主节点会注意到这一点,并对已下线的主节点进行故障转移
- 集群进行故障转移的方法和Redis Sentinel进行故障转移的方法基本一样,不同的是,在集群里面,故障转移是由集群中其他在线的主节点负责进行的,所以集群不必另外使用Redis Sentinel
Redis集群分片
- 集群将整个数据库分为16384个槽位slot,key的槽位计算公式为slot_number=crc16(key)%16384,其中crc16为16位的循环冗余校验和函数
- 集群中的每个主节点都可以处理0个至16383个槽,当16384个槽都有某个节点在负责处理时,集群进入上线状态,并开始处理客户端发送的数据命令请求
解决了3.0版本以前对写压力的分担
解决思路就是,使用多个节点分担,将写请求分散到不同节点处理
分片Sharding:多节点分担的思路就是关系型数据库处理大表的水平切分思路
举例
三个主节点7000、7001、7002平均分片16384个slot槽位
节点7000指派的槽位为0到5460
节点7001指派的槽位为5461到10922
节点7002指派的槽位为10923到16383
何时集群不能对外提供服务
- 过半的主节点挂掉,不能对外提供服务
- 其中任意一个节点主从都挂掉,不能对外提供服务
主节点过半机制判定一个主节点是否挂掉
Redis集群Redirect转向
- 由于Redis集群无中心节点,请求会发给任意主节点
- 主节点只会处理自己负责槽位的命令请求,其它槽位的命令请求,该主节点会返回客户端一个转向错误
- 客户端根据错误中包含的地址和端口重新向正确的负责的主节点发起命令请求
Redis集群搭建
创建多个主节点
为每一个节点指派slot,将多个节点连接起来,组成一个集群
槽位分片完成后,集群进入上线状态
6个节点:3个主节点,每一个主节点有一个从节点
1、下载redis3.0以及以上的tar包
2、解压
3、安装gcc tcl
yum install gcc tcl -y
4、编译
make
5、安装
make install PREFIX=/opt/redis3
6、将配置文件拷贝到安装目录处
cp ~/redis-3.0.0/redis.conf /opt/redis3/bin/
7、复制安装的目录6份
mv bin redis1
cp -r redis1/ redis2
…
8、编辑6份的配置信息:
port
daemonize yes
cluster-enabled yes 注释放开就行了
9、启动6台服务器
10、将redis-trib.rb拷贝到指定目录/opt/redis3/
cp ~/redis-3.0.0/src/redis-trib.rb .
11、下载和安装ruby以及rubygems
yum install ruby rubygems -y
12、下载并安装redis.gem
https://rubygems.org/downloads/redis-3.0.0.gem
https://rubygems.org/gems/redis/versions/3.0.0
gem install redis-3.0.0.gem
13、运行命令:
redis-trib.rb create --replicas 1 192.168.100.101:7001 192.168.100.101:7002 192.168.100.101:7003 192.168.100.101:7004 192.168.100.101:7005 192.168.100.101:7006
14、连接
[root@node1 redis3]# redis1/redis-cli -p 7001 -c
-c表示集群连接,否则单机连接
Redis集群总结
- Redis集群是一个由多个节点组成的分布式服务集群,它具有复制、高可用和分片特性
- Redis的集群没有中心节点,并且带有复制和故障转移特性,这可用避免单个节点成为性能瓶颈,或者因为某个节点下线而导致整个集群下线
- 集群中的主节点负责处理槽(储存数据),而从节点则是主节点的复制品
- Redis集群将整个数据库分为16384个槽,数据库中的每个键都属于16384个槽中的其中一个
- 集群中的每个主节点都可以负责0个至16384个槽,当16384个槽都有节点在负责时,集群进入上线状态,可以执行客户端发送的数据命令
- 主节点只会执行和自己负责的槽有关的命令,当节点接收到不属于自己处理的槽的命令时,它将会处理指定槽的节点的地址返回给客户端,而客户端会向正确的节点重新发送
添加和删除节点
该命令查看redis-trib.rb的使用信息:
ruby /opt/redis3/redis-trib.rb
Usage: redis-trib <command> <options> <arguments ...>
import host:port
--from <arg>
help (show this help)
del-node host:port node_id
create host1:port1 ... hostN:portN
--replicas <arg>
set-timeout host:port milliseconds
fix host:port
call host:port command arg arg .. arg
add-node new_host:new_port existing_host:existing_port
--master-id <arg>
--slave
reshard host:port
--yes
--to <arg>
--from <arg>
--slots <arg>
check host:port
添加7007到集群中
./redis-trib.rb add-node 127.0.0.1:7007 127.0.0.1:7001
在客户端使用该命令CLUSTER NODES 查看节点信息
给7007分配hash slots 1000个
./redis-trib.rb reshard --from all --to 8ba4a99a6f4ee94b0db053eb2a1ec5577a80dd40 --slots 1000 --yes 127.0.0.1:7001
启动node8,作为node7的从节点加入集群:
./redis-trib.rb add-node --slave 127.0.0.1:7008 127.0.0.1:7007
移除:
从节点
./redis-trib.rb del-node 127.0.0.1:7001 8ba4a99a6f4ee94b0db053eb2a1ec5577a80dd40
删除主节点:
迁移hash slots
./redis-trib.rb reshard --from a7b2151e53b99456064614bedd341acc1dbc28d4 --to c7ed704c5289f8935b707bd26a52b5c8f52f1467 --slots 333 127.0.0.1:7001
./redis-trib.rb reshard --from a7b2151e53b99456064614bedd341acc1dbc28d4 --to 6b2225b705224870b498305ba3024024fea797e2 --slots 334 127.0.0.1:7001
./redis-trib.rb reshard --from a7b2151e53b99456064614bedd341acc1dbc28d4 --to 056a42e8b7489cb7e579cc1e0af936885d24ccaa --slots 333 127.0.0.1:7001
移除空的主节点
./redis-trib.rb del-node 127.0.0.1:7001 a7b2151e53b99456064614bedd341acc1dbc28d4