Redis作为一款开源的、高性能的键值对存储。支持主从复制,并通过哨兵模式(sentinel)提高了高可用性,以及集群(Redis Cluster)模式保证了高并发性。
一、redis主从
Redis提供了一主(master)多从(slave)数据库的方式来进行数据的备份。一个主数据库可以有多个从数据库,一个从数据库只能有一个主数据库。一般情况下,主数据是可读写的,从数据只能读,并且从数据库同步主数据库新增的数据。
Redis主从是一种备份关系,主数据库写入数据,同步到从数据库。如果主数据损坏了,从数据库可以作为主数据库继续提供服务。
下面就来搭建一个一主二从的主从复制环境。演示环境是在一台centos 7服务器上模拟的,真实环境需要把主从服务器放置在不同的服务器上。
1.创建3个redis服务,对应的端口分别是6001,6002,6003,其中6001作为主库,6002,6003作为6001的从库(备份库)
在当前目录新增3个目录,名称以端口命名:
mkdir 6001 6002 6003
2.配置主从关系
配置主从关系有两种方式,一种是通过修改redis.conf配置文件,另一种是通过命令修改相应配置项。把redis.conf文件分别复制到对应的目录下
-
修改redis.conf
主库配置:
cd ./6001 vim redis.conf //redis.conf 主库主要配置项 bind 192.168.80.129//本机IP地址 port 6001 requirepass 123456 //设置密码 masterauth 123456 //链接主库密码
从库配置(以6002端口为例,6003修改相应端口即可):
cd ./6002 vim redis.conf bind 192.168.80.129 port 6002 requirepass 123456 masterauth 123456 //连接主库的密码 对应主库中 requirepass slaveof 192.168.80.129 6001//主库 ip 端口
-
命令方式更改主从配置
//分别修改3个redis服务的端口和ip 6001: bind 192.168.80.129 port 6001 6002: bind 192.168.80.129 port 6002 6003: bind 192.168.80.129 port 6003 //开启redis服务 ./redis-server ./6001/redis.conf ./redis-server ./6002/redis.conf ./redis-server ./6003/redis.conf //使用redis-cli连接6002 ./redis-cli -h 192.168.80.129 -p 6002 -a 123456 192.168.80.129:6002> slaveof 192.168.80.129 6001 OK 192.168.80.129:6002> config set masterauth 123456 OK 192.168.80.129:6002> info replication # Replication role:slave master_host:192.168.80.129 master_port:6001 master_link_status:up master_last_io_seconds_ago:1 master_sync_in_progress:0 slave_repl_offset:28 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:131038188755eea59eb4a84de0e2702c977a438b master_replid2:0000000000000000000000000000000000000000 master_repl_offset:28 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:28 //查看6001 192.168.80.129:6001> info replication # Replication role:master connected_slaves:1 slave0:ip=192.168.80.129,port=6002,state=online,offset=42,lag=1 master_replid:131038188755eea59eb4a84de0e2702c977a438b master_replid2:0000000000000000000000000000000000000000 master_repl_offset:42 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:42
可以看到6002已经是6001的从服务了,按照6002配置6003为6001的从服务器,查询6001的状态:
192.168.80.129:6001> info replication # Replication role:master connected_slaves:2 slave0:ip=192.168.80.129,port=6002,state=online,offset=1022,lag=1 slave1:ip=192.168.80.129,port=6003,state=online,offset=1022,lag=0 master_replid:131038188755eea59eb4a84de0e2702c977a438b master_replid2:0000000000000000000000000000000000000000 master_repl_offset:1022 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:1022
有2个从服务器6002,6003
>>>测试
通过第二步已经成功创建了一主二从的主从复制环境,主服务是可读写的,从服务是只读的。
在6002上是禁止写入的:
192.168.80.129:6003> set name 123 (error) READONLY You can't write against a read only slave.
在6001上写入数据:
192.168.80.129:6001> set name test OK
在6002上查看数据已经同步到6002从数据库上:
192.168.80.129:6002> get name "test"
到这里,一个主从复制、读写分离的环境就完成了,主服务器负责写入,从服务器服务读取。然而如果主服务器由于某种原因down掉的话,整个服务就没有办法写入,需要运维人员手动恢复主数据库后才能正常提供服务。下面哨兵模式的登场就有效的解决了主服务down掉人工介入的问题。
二、Redis哨兵(sentinel)
设置Redis主从后,如果主数据断开后,需要人工手动设置一个从数据库提升为主数据库继续提供服务,然而这种人工介入的方式,需要耗费一定的时间。为了实现此过程的自动化,Redis提供了哨兵模式(sentinel)。哨兵负责监控主从数据的运行状态,如果检测到主数据库出现异常,就自动选择一个从数据库升级为主数据库。
哨兵保证Redis的高可用性(HA),保证特殊故障后能够自动切换,如果主库异常,自动推选出一个从库作为新的主库继续提供服务。
下面让我们在主从模式的基础上,添加哨兵机制,主库down掉后,推选出一个从库作为新的主库,继续提供服务。
1.将sentinel.conf配置文件复制到目录下,修改相应配置:
vim sentinel.conf //修改如下配置项 port 16001 sentinel monitor mymaster 192.168.80.129 6001 1 sentinel auth-pass mymaster 123456
2.开启哨兵
./redis-sentinel ./sentinel.conf //显示如下信息,启动成功,自动检测到6001下的从服务器 120502:X 18 Apr 11:26:35.565 # Sentinel ID is 0676c2efd784d10801da4e51f17a35ddb2018e54 120502:X 18 Apr 11:26:35.565 # +monitor master mymaster 192.168.80.129 6001 quorum 1 120502:X 18 Apr 11:26:35.566 * +slave slave 192.168.80.129:6002 192.168.80.129 6002 @ mymaster 192.168.80.129 6001 120502:X 18 Apr 11:26:35.567 * +slave slave 192.168.80.129:6003 192.168.80.129 6003 @ mymaster 192.168.80.129 6001
哨兵启动成功后,模拟6001down掉,查看服务状态:
./redis-cli -h 192.168.80.129 -p 6001 -a 6001 shutdown //或是直接kill id //查看哨兵服务日志,如下:成功将6003提升为主库 120502:X 18 Apr 11:30:20.478 # +switch-master mymaster 192.168.80.129 6001 192.168.80.129 6003 120502:X 18 Apr 11:30:20.478 * +slave slave 192.168.80.129:6002 192.168.80.129 6002 @ mymaster 192.168.80.129 6003 120502:X 18 Apr 11:30:20.478 * +slave slave 192.168.80.129:6001 192.168.80.129 6001 @ mymaster 192.168.80.129 6003 //使用redis-cli连接6003,查看信息如下:6003做为新的主库,6002为其从库 192.168.80.129:6003> info replication # Replication role:master connected_slaves:1 slave0:ip=192.168.80.129,port=6002,state=online,offset=26318,lag=0 master_replid:2902c22b9c0c34000c9b3af52dbd812242774a90 master_replid2:695a9c210b17f18e6fc39503b28af3ee341bae2c master_repl_offset:26461 second_repl_offset:15804 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:26461
重新开启6001服务,6001会成为6003主库的从库:
./redis-server ./6001/redis.conf //哨兵输入如下信息,6001成功成为6003的从库 120502:X 18 Apr 11:44:16.161 # +sdown slave 192.168.80.129:6001 192.168.80.129 6001 @ mymaster 192.168.80.129 6003 120502:X 18 Apr 11:46:46.411 * +reboot slave 192.168.80.129:6001 192.168.80.129 6001 @ mymaster 192.168.80.129 6003 120502:X 18 Apr 11:46:46.467 # -sdown slave 192.168.80.129:6001 192.168.80.129 6001 @ mymaster 192.168.80.129 6003 //查看6003的信息,拥有6001,6002两个从服务: 192.168.80.129:6003> info replication # Replication role:master connected_slaves:2 slave0:ip=192.168.80.129,port=6002,state=online,offset=89380,lag=1 slave1:ip=192.168.80.129,port=6001,state=online,offset=89380,lag=1 master_replid:2902c22b9c0c34000c9b3af52dbd812242774a90 master_replid2:695a9c210b17f18e6fc39503b28af3ee341bae2c master_repl_offset:89380 second_repl_offset:15804 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:89380
三、Redis集群(cluster)
虽然Redis提供了主从备份、哨兵模式自动切换主从数据库。但是每个Redis实例是全量存储的,存储的都是完整的数据。这就造成了单个Redis并发有限,并且导致内存占用太大,rdb文件文件过大,从很大的rdb文件中同步恢复数据会很慢。Redis集群模式出现就解决了这个问题,采用分布式存储,最大化的使用内存。Redis集群共有16384个哈希槽(slot),每个Redis节点都会分配一部分slot,通过CRC(16)校验后16384取模,得到给定key的哈希槽,就把对应的可以存储在相应的节点上。
Redis集群保证了高并发性,同时集群导致了数据的分散,不同的key存放到不同的槽中。
下面使用Redis自带的redis-trib.rb工具来逐步搭建Redis Cluster。实战环境需要把redis部署在不同的服务器上,我们演示是在一台centos 7服务器上,用不同的端口来进行部署。由于Redis集群中至少需要3个主节点,每个主节点至少一个从节点(备份),所以需要创建6个节点:
创建6个文件夹,分别命名为:7001,7002,7003,7004,7005,7006
mkdir 7001 7002 7003 7004 7005 7006
1、添加配置信息
把redis.conf配置文件复制到对应的6个文件夹中,并按如下内容配置:
以7001为例,其它文件内参考如下项修改相应的端口:
bind 192.168.80.129 //配置本机ip port 7001 //配置端口 daemonize yes //以守护进程方式启动 pidfile /var/run/redis_7001.pid dbfilename dump7001.rdb masterauth 123456 //访问主机密码 requirepass 123456 //访问本实例密码 appendonly yes //开启aof appendfilename "appendonly7001.aof" cluster-enabled yes //开启集群模式 cluster-config-file nodes-7001.conf
2、编写启动、停止服务脚本:
启动脚本,命名:start-server.sh
./redis-server ./7001/redis.conf ./redis-server ./7002/redis.conf ./redis-server ./7003/redis.conf ./redis-server ./7004/redis.conf ./redis-server ./7005/redis.conf ./redis-server ./7006/redis.conf
停止脚本,命名:stop-server.sh
./redis-cli -c -h 192.168.80.129 -c 7001 -a 123456 shutdown ./redis-cli -c -h 192.168.80.129 -c 7002 -a 123456 shutdown ./redis-cli -c -h 192.168.80.129 -c 7003 -a 123456 shutdown ./redis-cli -c -h 192.168.80.129 -c 7004 -a 123456 shutdown ./redis-cli -c -h 192.168.80.129 -c 7005 -a 123456 shutdown ./redis-cli -c -h 192.168.80.129 -c 7006 -a 123456 shutdown
保存之后,需要设置可执行权限:
chmod +x start-server.sh chmod +x stop-server.sh
3、安装redis-trib.rb工具所需环境
由于redis-trib.rb是使用ruby语言编写的,在使用工具创建集群前,需要安装对应的依赖环境。
yum install ruby yum install rubygems gem install redis
创建集群
./start-server.sh //开启redis实例 ps -ef|grep redis //查看redis的状态 root 120202 1 0 09:35 ? 00:00:26 ./redis-server 192.168.80.129:7005 [cluster] root 122327 1 0 09:06 ? 00:00:29 ./redis-server 192.168.80.129:7002 [cluster] root 122332 1 0 09:06 ? 00:00:29 ./redis-server 192.168.80.129:7003 [cluster] root 122337 1 0 09:06 ? 00:00:28 ./redis-server 192.168.80.129:7004 [cluster] root 122350 1 0 09:06 ? 00:00:29 ./redis-server 192.168.80.129:7006 [cluster] ./redis-trib.rb create --replicas 1 192.168.80.129:7001 192.168.80.129:7002 192.168.80.129:7003 192.168.80.129:7004 192.168.80.129:7005 192.168.80.129:7006
使用create命令创建集群,--replicas 1参数表示为每个主服务器分配1个从服务器。
在redis.conf配置文件中我们设置了requirepass,需要修改/usr/local/rvm/gems/ruby-2.5.3/gems/redis-4.1.0/lib/redis/client.rb文件中password
DEFAULTS = { :url => lambda { ENV["REDIS_URL"] }, :scheme => "redis", :host => "127.0.0.1", :port => 6379, :path => nil, :timeout => 5.0, :password => 123456, :db => 0, :driver => nil, :id => nil, :tcp_keepalive => 0, :reconnect_attempts => 1, :reconnect_delay => 0, :reconnect_delay_max => 0.5, :inherit_socket => false }
创建成功后,随便连接一个redis实例,查看集群所有节点信息:
./redis-cli -c -h 192.168.80.129 -p 7001 -a 123456 cluster nodes 4b25a13040b72063c124194afdd2498d9bdf9ad5 192.168.80.129:7006@17006 slave 01eb67ca03f468254ae44774ee8923da318a4bce 0 1555485726804 6 connected b9fc41ff7cf22b3b7b066883f4f0dae6c0552114 192.168.80.129:7003@17003 master - 0 1555485726000 3 connected 10923-16383 53af35146e22456897920e02c696323b8fe29c55 192.168.80.129:7004@17004 slave b9fc41ff7cf22b3b7b066883f4f0dae6c0552114 0 1555485725000 4 connected 7f7041c5ef11f5165c7d913596243ca142826907 192.168.80.129:7001@17001 myself,master - 0 1555485726000 8 connected 0-5460 01eb67ca03f468254ae44774ee8923da318a4bce 192.168.80.129:7002@17002 master - 0 1555485725000 2 connected 5461-10922 bcd17fb8c3ae4e20ce2b1edc82c8e235475dcf0f 192.168.80.129:7005@17005 slave 7f7041c5ef11f5165c7d913596243ca1428
从上面信息可以看出,三个主库(7001,7002,7003),三个从库(7004,7005,7006)。三个主库分配的slot分别是:
7001:0-5460 7002:5461-10922 7003:10923-16383
结束7001主库,查看集群所有节点状态:
92.168.80.129:7002> cluster nodes b9fc41ff7cf22b3b7b066883f4f0dae6c0552114 192.168.80.129:7003@17003 master - 0 1555488472000 3 connected 10923-16383 bcd17fb8c3ae4e20ce2b1edc82c8e235475dcf0f 192.168.80.129:7005@17005 master - 0 1555488474017 9 connected 0-5460 53af35146e22456897920e02c696323b8fe29c55 192.168.80.129:7004@17004 slave b9fc41ff7cf22b3b7b066883f4f0dae6c0552114 0 1555488473000 4 connected 01eb67ca03f468254ae44774ee8923da318a4bce 192.168.80.129:7002@17002 myself,master - 0 1555488470000 2 connected 5461-10922 4b25a13040b72063c124194afdd2498d9bdf9ad5 192.168.80.129:7006@17006 slave 01eb67ca03f468254ae44774ee8923da318a4bce 0 1555488473006 6 connected 7f7041c5ef11f5165c7d913596243ca142826907 192.168.80.129:7001@17001 master,fail - 1555488452052 1555488450000 8 disconnected
其中7001的状态已经是fail,7005已升级为主库继续提供服务。显然redis cluster本身就集成了主从备份和哨兵模式,主数据库down掉后,从服务器自动被推选为新的主服务器,查看集群状态如下:
192.168.80.129:7002> cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:8 cluster_my_epoch:2 cluster_stats_messages_ping_sent:33577 cluster_stats_messages_pong_sent:25592 cluster_stats_messages_meet_sent:4 cluster_stats_messages_fail_sent:8 cluster_stats_messages_auth-ack_sent:2 cluster_stats_messages_sent:59183 cluster_stats_messages_ping_received:25590 cluster_stats_messages_pong_received:24893 cluster_stats_messages_meet_received:2 cluster_stats_messages_fail_received:2 cluster_stats_messages_publish_received:278 cluster_stats_messages_auth-req_received:2 cluster_stats_messages_received:50767
再次启动7001,7001已成为7005的从库
[root@localhost cluster]# ./redis-server ./7001/redis.conf 60511:C 17 Apr 16:10:44.760 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 60511:C 17 Apr 16:10:44.760 # Redis version=4.0.10, bits=64, commit=00000000, modified=0, pid=60511, just started 60511:C 17 Apr 16:10:44.760 # Configuration loaded [root@localhost cluster]# ./redis-cli -c -h 192.168.80.129 -p 7001 -a 123456 Warning: Using a password with '-a' option on the command line interface may not be safe. 192.168.80.129:7001> cluster nodes 7f7041c5ef11f5165c7d913596243ca142826907 192.168.80.129:7001@17001 myself,slave bcd17fb8c3ae4e20ce2b1edc82c8e235475dcf0f 0 1555488653000 8 connected bcd17fb8c3ae4e20ce2b1edc82c8e235475dcf0f 192.168.80.129:7005@17005 master - 0 1555488657756 9 connected 0-5460 53af35146e22456897920e02c696323b8fe29c55 192.168.80.129:7004@17004 slave b9fc41ff7cf22b3b7b066883f4f0dae6c0552114 0 1555488653732 4 connected b9fc41ff7cf22b3b7b066883f4f0dae6c0552114 192.168.80.129:7003@17003 master - 0 1555488656752 3 connected 10923-16383 4b25a13040b72063c124194afdd2498d9bdf9ad5 192.168.80.129:7006@17006 slave 01eb67ca03f468254ae44774ee8923da318a4bce 0 1555488655743 6 connected 01eb67ca03f468254ae44774ee8923da318a4bce 192.168.80.129:7002@17002 master - 0 1555488656000 2 connected 5461-10922
PS:如果有一个主数据库异常后,没有从数据库可以恢复,整个集群就会down掉。
本小节主要简单的介绍下redis集群的搭建,以及模拟一个主机down掉之后从机自动切换成主机的过程,更多有关redis集群内容会单独的章节进行分析总结。