为什么需要集群
在实际的项目中,从结构上和容量上两点需要集群:
1 结构上,redis单台服务器会发生单点故障,请求负载过大需要多个副本来将请求分配到不同的服务器上。
2 容量上,服务器内存存在存储平静,所以需要对数据进行分片存储到不同的服务器上。
集群管理
拥有集群之后,需要解决集群的管理问题,如何去管理集群,其中包括增肌爱节点,故障恢复,如何将请求分配到不同的服务器上等。设计到复制,哨兵,和集群的使用。
复制
虽然redis提供了持久化的功能,但是单点故障带来的问题还是无法解决。通常做法就是复制多个副本部署在不同的服务器上,出现单点故障的时候还可以利用其它副本进行服务。
配置
复制中,一般分主数据库和从数据库,主数据库用于进行读写操作,读数据库一般用来只读和接收主数据同步过来的数据。一个主数据库可以有多个从数据库。
redis中使用复制的步骤如下:
1 在从数据库中配置文件中增加:slaveof IP POR
################################# REPLICATION #################################
# Master-Slave replication. Use slaveof to make a Redis instance a copy of
# another Redis server. A few things to understand ASAP about Redis replication.
#
# 1) Redis replication is asynchronous, but you can configure a master to
# stop accepting writes if it appears to be not connected with at least
# a given number of slaves.
# 2) Redis slaves are able to perform a partial resynchronization with the
# master if the replication link is lost for a relatively small amount of
# time. You may want to configure the replication backlog size (see the next
# sections of this file) with a sensible value depending on your needs.
# 3) Replication is automatic and does not need user intervention. After a
# network partition slaves automatically try to reconnect to masters
# and resynchronize with them.
#
slaveof 127.0.0.1 6379
2 启动主数据库:
root@ubuntu:/etc/redis#
root@ubuntu:/etc/redis# redis-server redis.conf
root@ubuntu:/etc/redis#
root@ubuntu:/etc/redis#
root@ubuntu:/etc/redis# ps -ef | grep redis
redis 1343 1 0 02:11 ? 00:00:00 /usr/bin/redis-server 127.0.0.1:6379
root 3488 3438 0 02:21 pts/2 00:00:00 grep --color=auto redis
root@ubuntu:/etc/redis#
root@ubuntu:/etc/redis#
3 启动从数据:
root@ubuntu:/etc/redis#
root@ubuntu:/etc/redis# redis-server redis_6380.conf --slaveof 127.0.0.1 6379
root@ubuntu:/etc/redis#
root@ubuntu:/etc/redis#
root@ubuntu:/etc/redis# ps -ef | grep redis
redis 1343 1 0 02:11 ? 00:00:00 /usr/bin/redis-server 127.0.0.1:6379
root 3532 2447 0 02:23 ? 00:00:00 redis-server 127.0.0.1:6380
root 3537 3438 0 02:23 pts/2 00:00:00 grep --color=auto redis
root@ubuntu:/etc/redis#
用客户端连接主从两个redis数据库实例并查看相关信息:
root@ubuntu:/etc/redis# redis-cli -p 6379
127.0.0.1:6379>
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=267,lag=1
master_repl_offset:267
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:266
127.0.0.1:6379>
root@ubuntu:~#
root@ubuntu:~# redis-cli -p 6380
127.0.0.1:6380>
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:337
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6380>
验证下是否能够完成赋值的功能:
在主数据库上设置一个键
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379> set lable redis
OK
127.0.0.1:6379>
127.0.0.1:6379>
在从客户端上读取刚刚设置的键:
127.0.0.1:6380>
127.0.0.1:6380> get lable
"redis"
127.0.0.1:6380>
slaveof IP POR在客户端中执行,可以停止和原来数据库同步并和新的数据库同步:
1 另外启动一个主数据库 2 在6380这个客户端数据库中执行:
root@ubuntu:/etc/redis#
root@ubuntu:/etc/redis# redis-server redis_6381.conf
root@ubuntu:/etc/redis#
root@ubuntu:/etc/redis#
root@ubuntu:/etc/redis#
root@ubuntu:/etc/redis# ps -ef | grep redis
redis 1343 1 0 02:11 ? 00:00:02 /usr/bin/redis-server 127.0.0.1:6379
root 3532 2447 0 02:23 ? 00:00:01 redis-server 127.0.0.1:6380
root 3608 3593 0 02:27 pts/17 00:00:00 redis-cli -p 6380
root 3686 2447 0 02:35 ? 00:00:00 redis-server 127.0.0.1:6381
root 3692 3667 0 02:35 pts/18 00:00:00 grep --color=auto redis
root@ubuntu:/etc/redis#
root@ubuntu:/etc/redis#
127.0.0.1:6380>
127.0.0.1:6380> slaveof 127.0.0.1 6381
OK
127.0.0.1:6380>
127.0.0.1:6380>
127.0.0.1:6380>
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6381
master_link_status:up
master_last_io_seconds_ago:2
master_sync_in_progress:0
slave_repl_offset:29
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6380>
127.0.0.1:6380>
验证方式同上设置个键,再取获取即可
使用slaveof no one命令可以停止接收其它数据库的同步数据并转换为主数据库
127.0.0.1:6380>
127.0.0.1:6380> slaveof no one
OK
127.0.0.1:6380>
127.0.0.1:6380>
127.0.0.1:6380>
127.0.0.1:6380>
127.0.0.1:6380>
127.0.0.1:6380>
127.0.0.1:6380> info replication
# Replication
role:master
connected_slaves:0
master_repl_offset:509
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6380>
127.0.0.1:6380>
原理:
1 全量复制:从数据库启动之后,向主数据库发送一个同步消息。主数据收到之后会在开台开启快照并保存快照期间收到的命令缓存起来。当快照完成,会将快照和缓存的命令都发给从数据库。从数据库收到之后加载快照文件并执行收到缓存的命令。这个过程称为复制初始化。复制初始化之后,主数据库没收到请求都会命令同步给从数据库,从而保证主从数据库数据的一致。
2 增量复制:
增量复制需要的基础:
2.1 每个redis数据库实例运行时都有个运行唯一的ID。
2.2 在复制同步阶段,主数据库每将一个命令同步给从数据库,都会同时把该命令放进一个积压队列中,并记录下当前积压队列存放的命令的偏移范围。
2.3 从数据库接收到朱数据库传过来的命令,也会记录下该命令的偏移量。
过程:从数据库会给主数据库发送增量命令,格式为psync 主数据库运行的ID 断开前的命令偏移量。主数据库收到之后会判断何自己的运行ID是否一致,一致然后判断命令的偏移量是否在积压队列中。满足则增量同步,但是不满足的话则需要全量的同步。
零星配置补充:
redis采用的复制属于乐观复制,认为最终主从数据会一致,容忍有存在主从数据不一致的时间窗口。但是可通过配置来指定数量和允许从数据库最长的断连时间。
redis增量复制的积压队列的大小是可以设置的。
#
# This option does not GUARANTEE that N replicas will accept the write, but
# will limit the window of exposure for lost writes in case not enough slaves
# are available, to the specified number of seconds.
#
# For example to require at least 3 slaves with a lag <= 10 seconds use:
#
min-slaves-to-write 3
min-slaves-max-lag 10
#
# Set the replication backlog size. The backlog is a buffer that accumulates
# slave data when slaves are disconnected for some time, so that when a slave
# wants to reconnect again, often a full resync is not needed, but a partial
# resync is enough, just passing the portion of data the slave missed while
# disconnected.
#
# The bigger the replication backlog, the longer the time the slave can be
# disconnected and later be able to perform a partial resynchronization.
#
# The backlog is only allocated once there is at least a slave connected.
#
repl-backlog-size 1mb