Redis的主从复制
主从复制引言
实际生产环境下,单机的redis服务器是无法满足实际的生产需求的。
第一,单机的redis服务器很容易发生单点故障,即使redis提供了各种持久化的方法来避免数据的丢失,但是物理上的故障(硬盘损毁等)还是无法完全避免的。
第二,如果对单台机器的性能进行纵向拓展,无论是CPU,内存还是磁盘容量都很容易达到瓶颈,无法满足实际需求。
针对这些问题,redis提供了复制(replication)的功能,通过"主从(一主多从)"和"集群(多主多从)"的方式对redis的服务进行水平扩展,用多台redis服务器共同构建一个高可用的redis服务系统。
搭建步骤
在Redis的主从模型下,主服务器既可以读也可以写,而从服务器原则上只允许读操作。接下来我们讲解一下主从复制的搭建。
-
克隆2台Redis机器,并编辑redis.conf
另外2台机器都要编辑绑定ip地址 bind 0.0.0.0 # 可以被外部访问
-
主机正常启动,并关闭防火墙
systemctl stop firewalld redis-server /etc/redis/redis.conf
-
配置从机,编辑redis.conf
在 port 6379 后添加如下配置 slaveof 主机ip redis端口号,示例如下: slaveof 192.168.146.21 6379
-
启动从机
redis-server /etc/redis/redis.conf
-
查看主从信息
#登录主库 info replication
Redis的哨兵模式
哨兵模式引言
主从复制解决了数据备份的问题,但是如果主节点宕机,仍需要运维手动进行主从切换。要在主从复制下实现故障恢复的自动化,就需要使用Redis的哨兵(Sentinel)模式。
哨兵是一个独立于数据服务器的进程,用于监控redis数据服务器的状态,当主从模式下最关键的主服务器出现故障时,能够被哨兵自动的察觉。同时哨兵会在剩余的从服务器中"选举"出新的主服务器,达到自动化恢复系统服务的目的。
哨兵本身也要考虑单点故障的问题,所以Redis Sentinel一般由3~5个节点组成,这样即使挂了个别哨兵节点,哨兵整体还可以正常工作。
客户端来连接集群时,会首先连接 sentinel,通过 sentinel 来查询主节点的地址,然后再去连接主节点进行数据交互。当主节点发生故障时,客户端会重新向 sentinel 要地址,sentinel 会将最新的主节点地址告诉客户端。如此应用程序将无需重启即可自动完成节点切换。
通过如下2图,演示故障切换的过程:
从上图可以看到主节点挂掉了,原先的主从复制也断开了,客户端和损坏的主节点也断开了。从节点被提升为新的主节点,其它从节点开始和新的主节点建立复制关系。客户端通过新的主节点继续进行交互。
Sentinel 会持续监控已经挂掉了主节点。待它恢复后,原先挂掉的主节点现在变成了从节点,从新的主节点那里建立复制关系。
哨兵模式搭建
配置3个Redis(1主2从),3个哨兵
-
配置主从复制
主机配置redis.conf:
bind 127.0.0.1 修改为: bind 机器ip
从机1配置redis.conf:
bind 127.0.0.1 修改为:bind 0.0.0.0 并添加配置:slaveof 主节点ip 端口号 示例:slaveof 192.168.146.23 6379
从机2配置redis.conf:
bind 127.0.0.1 修改为:bind 0.0.0.0 并添加配置:slaveof 主节点ip 端口号 示例:slaveof 192.168.146.23 6379
重复执行redis-server /etc/redis/redis.conf 启动3个redis实例。
-
配置哨兵
哨兵1配置sentinel.conf:
添加bind 当前机器ip 将 sentinel monitor mymaster 127.0.0.1 6379 2 修改为 sentinel monitor mymaster 192.168.146.23 6379 2
哨兵2配置sentinel.conf:
添加bind 当前机器ip 将 sentinel monitor mymaster 127.0.0.1 6379 2 修改为 sentinel monitor mymaster 192.168.146.23 6379 2
哨兵3配置sentinel.conf:
添加bind 当前机器ip 将 sentinel monitor mymaster 127.0.0.1 6379 2 修改为 sentinel monitor mymaster 192.168.146.23 6379 2
重复执行redis-sentinel /etc/redis/sentinel.conf 启动3个哨兵。
-
连接哨兵,查看redis主从信息
redis-cli -h 哨兵ip -p 26379 比如: redis-cli -h 192.168.146.26 -p 26379 执行info命令 # Server redis_version:5.0.10 redis_git_sha1:00000000 redis_git_dirty:0 redis_build_id:87154668b9be1de7 redis_mode:sentinel os:Linux 3.10.0-862.el7.x86_64 x86_64 arch_bits:64 multiplexing_api:epoll atomicvar_api:atomic-builtin gcc_version:4.8.5 process_id:5489 run_id:ffec09007fa40ab368227ca757fea7c1deeab585 tcp_port:26379 uptime_in_seconds:349 uptime_in_days:0 hz:11 configured_hz:10 lru_clock:8401446 executable:/root/redis-sentinel config_file:/etc/redis/sentinel.conf # Clients connected_clients:3 client_recent_max_input_buffer:2 client_recent_max_output_buffer:0 blocked_clients:0 # CPU used_cpu_sys:3.608731 used_cpu_user:0.556983 used_cpu_sys_children:0.000000 used_cpu_user_children:0.000000 # Stats total_connections_received:4 total_commands_processed:933 instantaneous_ops_per_sec:2 total_net_input_bytes:53617 total_net_output_bytes:7440 instantaneous_input_kbps:0.03 instantaneous_output_kbps:0.01 rejected_connections:0 sync_full:0 sync_partial_ok:0 sync_partial_err:0 expired_keys:0 expired_stale_perc:0.00 expired_time_cap_reached_count:0 evicted_keys:0 keyspace_hits:0 keyspace_misses:0 pubsub_channels:0 pubsub_patterns:0 latest_fork_usec:0 migrate_cached_sockets:0 slave_expires_tracked_keys:0 active_defrag_hits:0 active_defrag_misses:0 active_defrag_key_hits:0 active_defrag_key_misses:0 # Sentinel 这里可以看到主节点信息 sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=192.168.146.23:6379,slaves=2,sentinels=3
关掉主节点,然后过几秒刷新info,可以看到选举后的新的主节点信息。
Redis的集群
集群引言
Redis 的哨兵模式基本已经可以实现高可用,读写分离 ,但是在这种模式下仍存在如下的问题:
-
单个redis主节点的写并发有限
-
单个redis接收所有的数据,最终回导致内存太大,内存太大回导致rdb文件过大,从很大的rdb文件中同步恢复数据会很慢
为此,Redis提供了Redis Cluster(集群)来解决这些问题。集群实现了 Redis 的分布式存储,也就是说每台 Redis 节点上存储不同的内容,Redis中多个节点共同担起存储数据的任务。
Redis Cluster 中整个数据库被划分为 16384 个slots(槽),数据库中每一个键都属于这16384中的一个,集群中的每个节点负责其中一部分槽位。
当 Redis Cluster 的客户端来连接集群时,它也会得到一份集群的槽位配置信息。这样当客户端要查找某个 key 时,可以直接定位到目标节点。
可以认为Redis 集群是一个提供在多个Redis间节点间共享数据的程序集。
搭建步骤
为了配置一个redis cluster,官方建议我们我们需要准备至少6台redis.其中至少3个主节点:既然有3个主节点,而一个主节点搭配至少一个从节点,因此至少得6台redis
方法一:
-
克隆6台机器,并关闭防火墙和selinux
-
配置6个节点:都是编辑redis.conf
主节点1:192.168.146.31 bind 当前机器ip cluster-enabled yes 主节点2:192.168.146.32 bind 当前机器ip cluster-enabled yes 主节点3:192.168.146.33 bind 当前机器ip cluster-enabled yes 从节点1:192.168.146.34 bind 当前机器ip cluster-enabled yes 从节点2:192.168.146.35 bind 当前机器ip cluster-enabled yes 从节点3:192.168.146.36 bind 当前机器ip cluster-enabled yes
-
启动6台Redis,并在每个节点上执行flushall命令(目的是清空redis中原有的数据)
-
执行以下命令,创建Redis集群
# --cluster-replicas 1 表示从节点的个数,每个主节点配置1个从节点 [root@localhost opt]#redis-cli --cluster create 192.168.183.131:6379 192.168.183.132:6379 192.168.183.133:6379 192.168.183.134:6379 192.168.183.135:6379 192.168.183.136:6379 --cluster-replicas 1 # 六个虚拟机集群 redis-cli --cluster create 192.168.183.131:6379 192.168.183.132:6379 192.168.183.133:6379 192.168.183.134:6379 192.168.183.135:6379 192.168.183.136:6379 --cluster-replicas 1 如果出现以下错误 >>> Creating cluster [ERR] Node 192.168.146.31:6379 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0. 解决方案: 在每台机器上执行 flushall 命令 另外可以通过:cluster reset命令重置集群 >>> Creating cluster >>> Performing hash slots allocation on 6 nodes... Using 3 masters: 192.168.146.31:6379 192.168.146.32:6379 192.168.146.33:6379 Adding replica 192.168.146.34:6379 to 192.168.146.31:6379 Adding replica 192.168.146.35:6379 to 192.168.146.32:6379 Adding replica 192.168.146.36:6379 to 192.168.146.33:6379 M: 3c8b6b84a16516c6fcccdcc2025fa656420d5c6c 192.168.146.31:6379 slots:0-5460,5798,6257,11921 (5464 slots) master M: e98a7244dac95763902b11ad5a2689cfd0231350 192.168.146.32:6379 slots:741,5461-10922,11921 (5464 slots) master M: f9efde9fbe682281602331c523d670e0a2d4c659 192.168.146.33:6379 slots:741,5798,6257,10923-16383 (5464 slots) master S: d02eb5f1f321520104197eb3b4cc7ffa74a843af 192.168.146.34:6379 replicates 3c8b6b84a16516c6fcccdcc2025fa656420d5c6c S: e9d037bdddfe4a9f0f29d7d28727f09d6d07c550 192.168.146.35:6379 replicates e98a7244dac95763902b11ad5a2689cfd0231350 S: 1bc1c56b3260469b8c3ddb13eb5f6e25f88abb7c 192.168.146.36:6379 replicates f9efde9fbe682281602331c523d670e0a2d4c659 Can I set the above configuration? (type 'yes' to accept): 输入yes 最终看到如下输出: [OK] All nodes agree about slots configuration. >>> Check for open slots... [OK] All 16384 slots covered.
方法二:
一台机器,启动六个redis服务
- 将redis下的redis.conf复制六份到etc/redis下,分别为redis.conf1、redis.conf2、redis.conf3、redis.conf4、redis.conf5、redis.conf6。
- 配置以上的六个redis.conf文件,修改端口号,分别为6379、6380、6381、3682、3683、6384
-
配置6个节点:都是编辑redis.conf
主节点1:192.168.146.31 bind 当前机器ip cluster-enabled yes 主节点2:192.168.146.31 bind 当前机器ip cluster-enabled yes 主节点3:192.168.146.31 bind 当前机器ip cluster-enabled yes 从节点1:192.168.146.31 bind 当前机器ip cluster-enabled yes 从节点2:192.168.146.31 bind 当前机器ip cluster-enabled yes 从节点3:192.168.146.31 bind 当前机器ip cluster-enabled yes
-
启动6台Redis,并在每个节点上执行flushall命令(目的是清空redis中原有的数据)
-
执行以下命令,创建Redis集群
# --cluster-replicas 1 表示从节点的个数,每个主节点配置1个从节点 [root@localhost opt]# redis-cli --cluster create 192.168.183.130:6379 192.168.183.130:6380 192.168.183.130:6381 192.168.183.130:6382 192.168.183.130:6383 192.168.183.130:6384 --cluster-replicas 1 如果出现以下错误 >>> Creating cluster [ERR] Node 192.168.146.31:6379 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0. 解决方案: 在每台机器上执行 flushall 命令 另外可以通过:cluster reset命令重置集群 >>> Creating cluster >>> Performing hash slots allocation on 6 nodes... Using 3 masters: 192.168.146.31:6379 192.168.146.31:6380 192.168.146.31:6381 Adding replica 192.168.146.34:6379 to 192.168.146.31:6379 Adding replica 192.168.146.35:6379 to 192.168.146.31:6380 Adding replica 192.168.146.36:6379 to 192.168.146.31:6381 M: 3c8b6b84a16516c6fcccdcc2025fa656420d5c6c 192.168.146.31:6379 slots:0-5460,5798,6257,11921 (5464 slots) master M: e98a7244dac95763902b11ad5a2689cfd0231350 192.168.146.31:6380 slots:741,5461-10922,11921 (5464 slots) master M: f9efde9fbe682281602331c523d670e0a2d4c659 192.168.146.31:6381 slots:741,5798,6257,10923-16383 (5464 slots) master S: d02eb5f1f321520104197eb3b4cc7ffa74a843af 192.168.146.31:6382 replicates 3c8b6b84a16516c6fcccdcc2025fa656420d5c6c S: e9d037bdddfe4a9f0f29d7d28727f09d6d07c550 192.168.146.31:6383 replicates e98a7244dac95763902b11ad5a2689cfd0231350 S: 1bc1c56b3260469b8c3ddb13eb5f6e25f88abb7c 192.168.146.31:6384 replicates f9efde9fbe682281602331c523d670e0a2d4c659 Can I set the above configuration? (type 'yes' to accept): 输入yes 最终看到如下输出: [OK] All nodes agree about slots configuration. >>> Check for open slots... [OK] All 16384 slots covered.