34-redis缓存服务(二)

三: redis 高可用与集群

  • 虽然 Redis 可以实现单机的数据持久化, 但无论是 RDB 也好或者 AOF 也好, 都解决不了单点宕机问题,即一旦 redis 服务器本身出现系统故障、硬件故障等问题后, 就会直接造成数据的丢失, 因此需要使用另外的技术来解决单点问题。
3.1:配置 reids 主从
  • 主备模式, 可以实现 Redis 数据的跨主机备份。
    程序端连接到高可用负载的 VIP, 然后连接到负载服务器设置的 Redis 后端 real server, 此模式不需要在程序里面配置 Redis 服务器的真实 IP 地址, 当后期 Redis 服务器 IP 地址发生变更只需要更改 redis相应的后端 real server 即可, 可避免更改程序中的 IP 地址设置。

3.1.1: Slave 主要配置:

  • Redis Slave 也要开启持久化并设置和 master 同样的连接密码, 因为后期 slave 会有提升为 master 的可能,Slave 端切换 master 同步后会丢失之前的所有数据。
  • 一旦某个 Slave 成为一个 master 的 slave, Redis Slave 服务会清空当前 redis 服务器上的所有数据并将master 的数据导入到自己的内存,但是断开同步关系后不会删除当前已经同步过的数据。

3.1.1.1:命令行配置:

  • 当前状态为 master,需要转换为 slave 角色并指向 master 服务器的 IP+PORT+Password

    192.168.7.104:6379> REPLICAOF 192.168.7.103 6379
    OK
    192.168.7.104:6379> CONFIG SET masterauth 123456
    OK

3.1.1.2: 同步日志

image.png

3.1.1.3: 当前 slave 状态

image.png

3.1.1.4: 保存配置到 redis.conf
286 replicaof 192.168.7.103 6379
293 masterauth 123456 #master 如果密码需要设置

3.1.1.5: 重启 slave 验证

info replication

image.png

3.1.1.6: 验证 slave 数据

127.0.0.1:6379> KEYS *

  1. "num"
  2. "hset1"
  3. "key1"
  4. "name1"
  5. "zset2"
  6. "key2"
  7. "zset1"
  8. "set2"

3.1.1.7: slave 状态只读无法写入数据

image.png

3.1.1.8: Master 日志

image.png

小笔记:redis主从

#master
vim /apps/redis/etc/redis.conf
    bind 127.0.0.1 192.168.37.7
    requirepass 123456
    
#slave1
vim /apps/redis/etc/redis.conf
    bind 127.0.0.1 192.168.37.17
redis-server /apps/redis/etc/redis.conf
#手动设置为从服务器
redis-cli
auth 123456
slaveof 192.168.37.7 6379
config set masterauth 123456

#slave切换master(手动)
info Replication
SLAVEOF no one
set key1 value1
vim /apps/redis/etc/redis.conf
    bind 127.0.0.1 192.168.37.17
    #slaveof 192.168.37.7 6379
    #masterauth 123456

#slave2
vim /apps/redis/etc/redis.conf
    bind 127.0.0.1 192.168.37.27
    slaveof 192.168.37.7 6379
    masterauth 123456
redis-server /apps/redis/etc/redis.conf

#slave节点再有slave
vim /apps/redis/etc/redis.conf
    bind 127.0.0.1 192.168.37.37
    slaveof 192.168.37.27 6379      #指向slave
    masterauth 123456

3.1.1.9:主从复制过程

  • Redis 支持主从复制分为全量同步和增量同步, 首次同步是全量同步,主从同步可以让从服务器从主服务器备份数据,而且从服务器还可与有从服务器,即另外一台 redis 服务器可以从一台从服务器进行数据同步, redis 的主从同步是非阻塞的,其收到从服务器的 sync(2.8 版本之前是 PSYNC)命令会fork 一个子进程在后台执行 bgsave 命令,并将新写入的数据写入到一个缓冲区里面, bgsave 执行完成之后并生成的将 RDB 文件发送给客户端,客户端将收到后的 RDB 文件载入自己的内存,然后主 redis将缓冲区的内容在全部发送给从 redis,之后的同步从服务器会发送一个 offset 的位置(等同于 MySQL的 binlog 的位置)给主服务器,主服务器检查后位置没有错误将此位置之后的数据包括写在缓冲区的积压数据发送给 redis 从服务器,从服务器将主服务器发送的挤压数据写入内存,这样一次完整的数据同步,再之后再同步的时候从服务器只要发送当前的 offset 位 置给主服务器,然后主服务器根据响应的位置将之后的数据发送给从服务器保存到其内存即可。

  • Redis 全量复制一般发生在 Slave 初始化阶段,这时 Slave 需要将 Master 上的所有数据都复制一份。具
    体步骤如下:

    1)从服务器连接主服务器,发送 SYNC 命令;
    2)主服务器接收到 SYNC 命名后,开始执行 BGSAVE 命令生成 RDB 快照文件并使用缓冲区记录此后执行的所有写命令;
    3)主服务器 BGSAVE 执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令;
    4)从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
    5)主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;
    6)从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;
    7) 后期同步会先发送自己 slave_repl_offset 位置, 只同步新增加的数据, 不再全量同步。

    image.png

3.1.1.10: 主从同步优化

  • Redis 在 2.8 版本之前没有提供增量部分复制的功能, 当网络闪断或者 slave Redis 重启之后会导致主
    从之间的全量同步,即从 2.8 版本开始增加了部分复制的功能。

    repl-diskless-sync yes#yes 为支持 disk, master 将 RDB 文件先保存到磁盘在发送给 slave, no 为 master直接将 RDB 文件发送给 slave,默认即为使用 no, Master RDB 文件不需要与磁盘交互。
    repl-diskless-sync-delay 5 #Master 准备好 RDB 文件后等等待传输时间
    repl-ping-slave-period 10 #slave 端向 server 端发送 ping 的时间区间设置,默认为 10 秒
    repl-timeout 60 #设置超时时间
    repl-disable-tcp-nodelay no #是否启用 TCP_NODELAY, 如设置成 yes,则 redis 会合并小的 TCP 包从而节省带宽,但会增加同步延迟(40ms),造成 master 与 slave 数据不一致,假如设置成 no,则 redis master会立即发送同步数据,没有延迟,前者关注性能,后者关注一致性
    repl-backlog-size 1mb #master 的写入数据缓冲区, 用于记录自上一次同步后到下一次同步过程中间的写入命令,计算公式: b repl-backlog-size = 允许从节点最大中断时长 * 主实例 offset 每秒写入量, 比如 master 每秒最大写入 64mb, 最大允许 60 秒,那么就要设置为 64mb*60 秒=3840mb(3.8G)
    repl-backlog-ttl 3600 #如果一段时间后没有 slave 连接到 master,则 backlog size 的内存将会被释放。如果值为 0 则表示永远不释放这部份内存。
    slave-priority 100 #slave 端的优先级设置,值是一个整数,数字越小表示优先级越高。当 master 故障时将会按照优先级来选择 slave 端进行恢复,如果值设置为 0,则表示该 slave 永远不会被选择。
    #min-slaves-to-write 1 #设置一个master端的可用slave少于多少个
    #min-slaves-max-lag 20 #设置所有slave延迟时间都大于多少秒时,master不接收写操作(拒绝写入)
    

3.1.1.11: Slave 同步过程日志

image.png

3.1.1.12: master 同步日志

image.png

3.1.1.13: slave 切换 master

  • Master 的重启会导致 master_replid 发生变化, slave 之前的 master_replid 就和 master 不一致从而会引发所有 slave 的全量同步。
#当前状态:
192.168.7.101:6379> info Replication
# Replication
role:slave
master_host:192.168.7.103
master_port:6379
master_link_status:up
master_last_io_seconds_ago:8
master_sync_in_progress:0

#停止 slave 同步并查看当前状态:
192.168.7.101:6379> SLAVEOF no one
OK
192.168.7.101:6379> info Replication
# Replication
role:master
connected_slaves:0
master_replid:ac3475e5e4fae8c5f47711a643e465b9520c4182
master_replid2:8ee6bc1ac452fd4d2ccbaa660a219f78d218399a
master_repl_offset:8840
second_repl_offset:8841
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:8547
repl_backlog_histlen:294

#测试能否写入数据:
192.168.7.101:6379> set key1 value1
OK

3.1.1.14: Slave 节点再有 Slave

#在有 slave 的”master”查看状态:
# Replication
role:slave
master_host:192.168.7.102
master_port:6379
master_link_status:up
master_last_io_seconds_ago:9 #最近一次与 master 通信已经过去多少秒。
master_sync_in_progress:0 #是否正在与 master 通信。
slave_repl_offset:5334 #当前同步的偏移量。
slave_priority:100 #slave 优先级, master 故障后值越小越优先同步。
slave_read_only:1
connected_slaves:1
slave0:ip=192.168.7.104,port=6379,state=online,offset=5334,lag=1
master_replid:0f0318c25a022add7fd51d4438c470cf608631f9
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:5334
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:5334

3.1.2: 常见问题汇总

3.1.2.1: master 密码不对
即配置的 master 密码不对,导致验证不通过而无法建立主从同步关系。

3.1.2.2: Redis 版本不一致
不同的 redis 版本之间存在兼容性问题, 因此各 master 和 slave 之间必须保持版本一致。

3.1.2.3:无法远程连接
在开启了安全模式情况下,没有设置 bind 地址和密码

[root@redis-s1 ~]# redis-cli -h 192.168.7.104
192.168.7.104:6379> KEYS *
(error) DENIED Redis is running in protected mode because protected mode is enabled, no
bind address was specified, no authentication password
is requested to clients. In this mode connections are only accepted from the loopback
interface. If you want to connect from external computers to Redis you may adopt one of
the following solutions:
1) Just disable protected mode sending the command 'CONFIG SET protected-mode no'
from the loopback interface by connecting to Redis from the same host the server is
running, however MAKE SURE Redis is not publicly accessible from internet if you do so. Use
CONFIG REWRITE to make this change permanent.
2) Alternatively you can just disable the protected mode by editing the Redis configuration
file, and setting the protected mode option to 'no', and then restarting the server.
3) If you started the server manually just for testing, restart it with the '--protected-mode n
option.
4) Setup a bind address or an authentication password. NOTE: You only need to do one of
the above things in order for the server to start accepting connections from the outside.
3.2: redis 集群
  • 上一个步骤的主从架构无法实现 master 和 slave 角色的自动切换,即当 master 出现 redis 服务异常、 主机断电、磁盘损坏等问题导致 master 无法使用,而 redis 高可用无法实现自故障转移(将 slave 提升 为 master),需要手动改环境配置才能切换到 slave redis 服务器,另外也无法横向扩展 Redis 服务的并行写入性能, 当单台 Redis 服务器性能无法满足业务写入需求的时候就必须需要一种方式解决以上的两个核心问题, 即:
    1.master 和 slave 角色的无缝切换,让业务无感知从而不影响业务使用
    2.可以横向动态扩展 Redis 服务器,从而实现多台服务器并行写入以实现更高并发的目的。
  • Redis 集群实现方式: 客户端分片 代理分片 Redis Cluster
3.2.1: Sentinel(哨兵)
  • Sentinel 进程是用于监控 redis 集群中 Master 主服务器工作的状态,在 Master 主服务器发生故障的时候,可以实现 Master 和 Slave 服务器的切换,保证系统的高可用,其已经被集成在 redis2.6+的版本中, Redis 的哨兵模式到了 2.8 版本之后就稳定了下来。一般在生产环境也建议使用 Redis 的 2.8 版本的以后版本。哨兵(Sentinel) 是一个分布式系统,你可以在一个架构中运行多个哨兵(sentinel) 进程,这些进程使用流言协议(gossipprotocols)来接收关于 Master 主服务器是否下线的信息,并使用投票协议(Agreement Protocols)来决定是否执行自动故障迁移,以及选择哪个 Slave 作为新的 Master。每个哨兵(Sentinel)进程会向其它哨兵(Sentinel)、 Master、 Slave 定时发送消息,以确认对方是否”活”着,如果发现对方在指定配置时间(可配置的)内未得到回应,则暂时认为对方已掉线,也就是所谓的”主观认
    为宕机” ,英文名称: Subjective Down,简称 SDOWN。有主观宕机,肯定就有客观宕机。当“哨兵群”中的多数 Sentinel 进程在对 Master 主服务器做出 SDOWN 的判断,并且通过 SENTINEL is-masterdown-by-addr 命令互相交流之后,得出的 Master Server 下线判断,这种方式就是“客观宕机”,英文名称是: Objectively Down, 简称 ODOWN。通过一定的 vote 算法,从剩下的 slave 从服务器节点中,选一台提升为 Master 服务器节点,然后自动修改相关配置,并开启故障转移(failover)。
  • Sentinel 机制可以解决 master 和 slave 角色的切换问题。

3.2.1.1:手动配置 master:

  • 需要手动先指定某一台 Redis 服务器为 master,然后将其他 slave 服务器使用命令配置为 master 服务器的 slave

3.2.1.1.1: 服务器 A 配置 slave

192.168.7.102:6379> REPLICAOF 192.168.7.101 6379
OK
192.168.7.102:6379> CONFIG SET masterauth "123456"
OK
192.168.7.103:6379> REPLICAOF 192.168.7.101 6379
OK
192.168.7.103:6379> CONFIG SET masterauth "123456"
OK

image.png

3.2.1.1.2: 服务器 B 配置 slave

192.168.7.103:6379> REPLICAOF 192.168.7.101 6379
OK
192.168.7.103:6379> CONFIG SET masterauth "123456"
OK

image.png

3.2.1.1.2: 当前 master 状态

image.png

3.2.1.1.3:应用程序如何连接 redis?

  • java 客户端连接 redis 是通过 jedis 来实现的, java 代码用的时候只要创建 jedis 对象就可以建多个 jedis 连接池来连接 redis, 应用程序再直接调用连接池即可连接 Redis。
  • 而 Redis 为了保障高可用,服务一般都是 Sentinel 部署方式, 当 Redis 服务中的主服务挂掉之后,会仲裁出另外一台 Slaves 服务充当 Master。这个时候,我们的应用即使使用了 Jedis 连接池,Master服务挂了,我们的应用奖还是无法连接新的 Master 服务, 为了解决这个问题,Jedis 也提供了相应的Sentinel 实现,能够在 Redis Sentinel 主从切换时候,通知我们的应用,把我们的应用连接到新的Master 服务。
  • Jedis Sentinel 的使用也是十分简单的,只是在 JedisPool 中添加了 Sentinel 和 MasterName 参数, Jedis Sentinel 底层基于 Redis 订阅实现 Redis 主从服务的切换通知, 当 Reids 发生主从切换时, Sentinel 会发送通知主动通知 Jedis 进行连接的切换, JedisSentinelPool 在每次从连接池中获取链接对象的时候,都要对连接对象进行检测,如果此链接和 Sentinel 的 Master 服务连接参数不一致,则会关闭此连接,重新获取新的 Jedis 连接对象。

3.2.1.1.4: python 连接 redis
yum install python-pip
pip install redis

[root@redis-s3 ~]# cat test.py
#!/bin/env python
#Author: ZhangJie
import redis
pool = redis.ConnectionPool(host="192.168.7.101", port=6379,password="123456")
r = redis.Redis(connection_pool=pool)
for i in range(100):
r.set("k%d" % i,"v%d" % i)
data=r.get("k%d" % i)
print(data)

3.2.1.1.5: 各 Redis 服务器验证数据

image.png

3.2.1.1:编辑配置文件 sentinel.conf

3.2.1.1.1: Server1 配置
哨兵可以不和 Redis 服务器部署在一起

[root@redis-s1 etc]# grep "^[a-Z]" /usr/local/redis/etc/sentinel.conf
bind 0.0.0.0
port 26379
daemonize yes
pidfile "/usr/local/redis/redis-sentinel.pid"
logfile "/usr/local/redis/sentinel_26379.log"
dir "/usr/local/redis"
sentinel monitor mymaster 192.168.7.101 6379 2
sentinel auth-pass mymaster 123456
sentinel down-after-milliseconds mymaster 30000 #(SDOWN)主观下线的时间
sentinel parallel-syncs mymaster 1 #发生故障转移时候同时向新 master 同步数据的 slave 数量, 数字越
小总同步时间越长
sentinel failover-timeout mymaster 180000 #所有 slaves 指向新的 master 所需的超时时间
sentinel deny-scripts-reconfig yes

3.2.1.1.2: Server2 配置

bind 192.168.7.102
port 26379
daemonize yes
pidfile "/usr/local/redis/redis-sentinel.pid"
logfile "/usr/local/redis/sentinel_26379.log"
dir "/usr/local/redis"
sentinel deny-scripts-reconfig yes
sentinel monitor mymaster 192.168.7.101 6379 2
sentinel auth-pass mymaster 123456

3.2.1.1.3: Server3 配置

bind 192.168.7.103
port 26379
daemonize yes
pidfile "/usr/local/redis/redis-sentinel.pid"
logfile "/usr/local/redis/sentinel_26379.log"
dir "/usr/local/redis"
sentinel deny-scripts-reconfig yes
sentinel monitor mymaster 192.168.7.101 6379 2
sentinel auth-pass mymaster 123456

3.2.1.2: 启动哨兵
三台哨兵都要启动
#/usr/local/redis/bin/redis-sentinel /usr/local/redis/etc/sentinel.conf
#/usr/local/redis/bin/redis-sentinel /usr/local/redis/etc/sentinel.conf
#/usr/local/redis/bin/redis-sentinel /usr/local/redis/etc/sentinel.conf

3.2.1.3:验证端口

image.png

3.2.1.4: 哨兵日志

image.png

3.2.1.5: 当前 redis 状态

192.168.7.101:6379> info Replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.7.103,port=6379,state=online,offset=2316,lag=1slave1:ip=192.168.7.102,port=6379,state=online,offset=2175,lag=1
master_replid:f62f849f8ff4b9ee6d0095b802e9189a3e84aaf3
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:2316
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:2316

3.2.1.6: 当前 sentinel 状态

尤其是最后一行, 涉及到 master IP 是多少,有几个 slave,有几个 sentinels, 必须是符合全部服务器
数量的。

[root@redis-s1 etc]# redis-cli -h 192.168.7.101 -p 26379
192.168.7.101:26379> info Sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0

3.2.1.6: 停止 Redis Master 测试故障转移

[root@redis-s1 ~]# systemctl stop redis
#查看集群信息:
[root@redis-s1 ~]# redis-cli -h 192.168.7.101 -p 6379
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.7.103,port=6379,state=online,offset=51206,lag=0
slave1:ip=192.168.7.102,port=6379,state=online,offset=51065,lag=1
master_replid:416707fb0a8197595e16d6af8a8241c41cd8e992
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:51347
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:51347
#查看哨兵信息:[root@redis-s1 ~]# redis-cli -h 192.168.7.101 -p 26379
# 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.7.101:6379,slaves=2,sentinels=3

故障转移时 sentinel 的信息

image.png

3.2.1.7:故障转移后的 redis 配置文件

  • 故障转移后 redis.conf 中的 replicaof 行的 master IP 会被修改, sentinel.conf 中的 sentinel monitor IP 会被修改

    [图片上传失败...(image-51e2c9-1591525426362)]

3.2.1.8: 当前 reids 状态

[图片上传失败...(image-f0b6cd-1591525426362)]

小笔记:配置哨兵监控redis

#master
vim /apps/redis/etc/redis.conf
    bind 127.0.0.1 192.168.37.7
    requirepass 123456
    
cp /usr/local/src/redis/sentinel.conf /apps/redis/etc/sentinel.conf
vim /apps/redis/etc/sentinel.conf
    bind 0.0.0.0
    port 26379
    daemonize yes                   #守护进程
    pidfile "redis-sentinel.pid"
    logfile "sentinel.log"
    dir "/apps/redis/logs"
    sentinel monitor master1 192.168.37.7 6379 2        #最后2是指redis-server的总数量
    sentinel auth-pass master1 123456
    sentinel down-after-milliseconds master1 30000      #(SDOWN)主观下线的时间,单位毫秒
    sentinel parallel-syncs master1 1       #发生故障转移时候同时向新 master 同步数据的 slave 数量, 数字越小总同步时间越长
    sentinel failover-timeout master1 180000 #所有 slaves 指向新的 master 所需的超时时间,单位毫秒
    sentinel deny-scripts-reconfig yes      #禁止修改脚本
    
scp /apps/redis/etc/sentinel.conf root@192.168.37.17:/apps/redis/etc
scp /apps/redis/etc/sentinel.conf root@192.168.37.27:/apps/redis/etc
redis-server /apps/redis/etc/redis.conf
redis-sentinel /apps/redis/etc/sentinel.conf

#slave1
vim /apps/redis/etc/redis.conf
    bind 127.0.0.1 192.168.37.17
    slaveof 192.168.37.7 6379
    masterauth 123456
redis-server /apps/redis/etc/redis.conf
redis-sentinel /apps/redis/etc/sentinel.conf

#slave2
vim /apps/redis/etc/redis.conf
    bind 127.0.0.1 192.168.37.27
    slaveof 192.168.37.7 6379
    masterauth 123456
redis-server /apps/redis/etc/redis.conf
redis-sentinel /apps/redis/etc/sentinel.conf

#查看日志观察down变化
tail /apps/redis/logs/sentinel.log
3.2.2: Redis Cluster
  • Redis 分布式部署方案

    1. 客户端分区: 由客户端程序决定 key 写分配和写入的 redis node, 但是需要客户端自己处理写入分配、高可用管理和故障转移等
      2)代理方案: 基于三方软件实现 redis proxy,客户端先连接之代理层,由代理层实现 key 的写入分配,对客户端来说是有比较简单,但是对于集群管节点增减相对比较麻烦,而且代理本身也是单点和性能瓶颈。

    在哨兵 sentinel 机制中,可以解决 redis 高可用的问题, 即当 master 故障后可以自动将 slave 提升为master 从而可以保证 redis 服务的正常使用,但是无法解决 redis 单机写入的瓶颈问题, 即单机的 redis写入性能受限于单机的内存大小、 并发数量、 网卡速率等因素,因此 redis 官方在 redis 3.0 版本之后推出了无中心架构的 redis cluster 机制, 在无中心的 redis 集群汇中,其每个节点保存当前节点数据和整个集群状态,每个节点都和其他所有节点连接, 特点如下:

    1: 所有 Redis 节点使用(PING 机制)互联
    2:集群中某个节点的失效, 是整个集群中超过半数的节点监测都失效才算真正的失效
    3: 客户端不需要 proxy 即可直接连接 redis, 应用程序需要写全部的 redis 服务器 IP
    4: redis cluster 把所有的 redis node 映射到 0-16383 个槽位(slot)上, 读写需要到指定的 redis node 上进行操作,因此有多少个 reids node 相当于 redis 并发扩展了多少倍
    5: Redis cluster 预先分配 16384 个(slot)槽位,当需要在 redis 集群中写入一个 key -value 的时候,会使用 CRC16(key) mod 16384 之后的值,决定将 key 写入值哪一个槽位从而决定写入哪一个 Redis 节点上, 从而有效解决单机瓶颈

3.2.2.1: Redis cluster 架构

3.2.2.1.1: Redis cluster 基本架构:

  • 假如三个主节点分别是:A, B, C 三个节点,采用哈希槽 (hash slot)的方式来分配 16384 个 slot 的话,
    它们三个节点分别承担的 slot 区间是:
    节点 A 覆盖 0-5460
    节点 B 覆盖 5461-10922
    节点 C 覆盖 10923-16383

3.2.2.1.2: Redis cluster 主从架构:

  • Redis cluster 的架构虽然解决了并发的问题, 但是又引入了一个新的问题,每个 Redis master 的高可用

3.2.2.2: 部署 redis 集群

  • 环境准备:
    环境 A: 三台服务器, 每台服务器启动 6379 和 6380 两个 redis 服务。
    192.168.7.101:6379/6380 192.168.7.102:6379/6380 192.168.7.103:6379/6380
    另外预留一台服务器做集群添加节点测试。
    192.168.7.104:6379/6380

    环境 B: 生产环境建议直接 6 台服务器。

    172.18.200.101 172.18.200.102 172.18.200.103
    172.18.200.104 172.18.200.105 172.18.200.106
    预留服务器 172.18.200.107

3.2.2.2.1: 创建 redis cluster 集群的前提

  • 1.每个 redis node 节点采用相同的硬件配置、相同的密码
    2.每个节点必须开启的参数
    cluster-enabled yes #必须开启集群状态, 开启后 redis 进程会有 cluster 显示
    cluster-config-file nodes-6380.conf #此文件有 redis cluster 集群自动创建和维护,不需要任何手动操作
    3.所有 redis 服务器必须没有任何数据
    4.先启动为单机 redis 且没有任何 key value

    image.png

3.2.2.2.2: 创建集群:

  • Redis 3 和 4 版本:
    需要使用到集群管理工具 redis-trib.rb, 这个工具是 redis 官方推出的管理 redis 集群的工具,集成在redis 的源码 src 目录下,是基于 redis 提供的集群命令封装成简单、便捷、实用的操作工具, redis-trib.rb是 redis 作者用 ruby 开发完成的, centos 系统 yum 安装的 ruby 存在版本较低问题,如下:

    [root@s1 ~]# yum install ruby rubygems -y
    [root@s1 ~]# find / -name redis-trib.rb
    /usr/local/src/redis-4.0.14/src/redis-trib.rb
    [root@s1 ~]# cp /usr/local/src/redis-4.0.14/src/redis-trib.rb /usr/bin/
    [root@s1 src]# gem install redis
    Fetching: redis-4.1.2.gem (100%)
    ERROR: Error installing redis:
    redis requires Ruby version >= 2.3.0.  
    
    #解决 ruby 版本较低问题:
    [root@s1 src]# yum remove ruby rubygems -y
    [root@s1 src]# wget https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.5.tar.gz
    [root@s1 src]# tar xf ruby-2.5.5.tar.gz[root@s1 src]# cd ruby-2.5.5
    [root@s1 ruby-2.5.5]# ./configure
    [root@s1 ruby-2.5.5]# make -j 2
    [root@s1 ruby-2.5.5]# make install
    [root@s1 ruby-2.5.5]# gem install redis #https://rubygems.org/gems/redis, # gem install -l redis-3.3.0.gem
    
    #验证 redis-trib.rb 命令是否可执行
    [root@s1 ruby-2.5.4]# redis-trib.rb
    Usage: redis-trib <command> <options> <arguments ...>
    create host1:port1 ... hostN:portN #创建集群
          --replicas <arg> #指定 master 的副本数量
    check host:port #检查集群信息
    info host:port #查看集群主机信息
    fix host:port #修复集群
      --timeout <arg>
    reshard host:port #在线热迁移集群指定主机的 slots 数据
      --from <arg>
      --to <arg>
      --slots <arg>
      --yes
      --timeout <arg>
      --pipeline <arg>
    rebalance host:port #平衡集群中各主机的 slot 数量
      --weight <arg>
      --auto-weights
      --use-empty-masters
      --timeout <arg>
      --simulate
      --pipeline <arg>
      --threshold <arg>
    add-node new_host:new_port existing_host:existing_port #添加主机到集群
      --slave
      --master-id <arg>
    del-node host:port node_id #删除主机
    set-timeout host:port milliseconds #设置节点的超时时间
    call host:port command arg arg .. arg #在集群上的所有节点上执行命令
    import host:port #导入外部 redis 服务器的数据到当前集群
      --from <arg>--copy
      --replace
    help (show this help)
    [root@s1 ruby-2.5.4]# vim /usr/local/lib/ruby/gems/2.5.0/gems/redis-4.1.0/lib/redis/client.rb #修改密码为redis 登录密码
    
    #创建 redis cluster 集群
    #Redis 3/4 版本
    [root@s1 ~]# redis-trib.rb create --replicas 1 172.18.200.101:6379 172.18.200.102:6379 172.18.200.103:6379 172.18.200.104:6379 172.18.200.105:6379 172.18.200.106:6379
    
    #如果有之前的操作导致 Redis 集群创建报错,则执行清空数据和集群命令:
    127.0.0.1:6379> FLUSHALL
    OK
    127.0.0.1:6379> cluster reset
    OK
    
    #Redis 5 版本
    [root@redis-s1 ~]# redis-cli -a 123456 --cluster create 192.168.7.101:6379 192.168.7.101:6380 192.168.7.102:6379 192.168.7.102:6380 192.168.7.103:6379 192.168.7.103:6380 --cluster-replicas 1
    Warning: Using a password with '-a' or '-u' option on the command line interface may not be
    safe.
    >>> Performing hash slots allocation on 6 nodes...
    Master[0] -> Slots 0 - 5460
    Master[1] -> Slots 5461 - 10922
    Master[2] -> Slots 10923 - 16383
    Adding replica 192.168.7.102:6380 to 192.168.7.101:6379
    Adding replica 192.168.7.101:6380 to 192.168.7.102:6379
    Adding replica 192.168.7.103:6380 to 192.168.7.103:6379
    >>> Trying to optimize slaves allocation for anti-affinity
    [OK] Perfect anti-affinity obtained!
    M: f4cfc5cf821c0d855016488d6fbfb62c03a14fda 192.168.7.101:6379 #带 M 的为 master
    slots:[0-5460] (5461 slots) master #当前 master 的槽位起始和结束位
    S: 2b6e5d9c3944d79a5b64a19e54e52f83d48438d6 192.168.7.101:6380 #带 S 的 slave
    replicates 70de3821dde4701c647bd6c23b9dd3c5c9f24a62
    M: 116c4c6de036fdbac5aaad25eb1a61ea262b64af 192.168.7.102:6379
    slots:[5461-10922] (5462 slots) master #当前 master 的槽位起始和结束位
    S: 7186c6d03dd9a5e3be658f2d08e800bc55b04a09 192.168.7.102:6380
    replicates f4cfc5cf821c0d855016488d6fbfb62c03a14fda
    M: 70de3821dde4701c647bd6c23b9dd3c5c9f24a62 192.168.7.103:6379
    slots:[10923-16383] (5461 slots) master #当前 master 的槽位起始和结束位
    S: 7eda0bcf0c01bb7343313b81267c42dd1b26c8a6 192.168.7.103:6380
    replicates 116c4c6de036fdbac5aaad25eb1a61ea262b64af
    Can I set the above configuration? (type 'yes' to accept): yes #输入 yes 自动创建集群
    >>> Nodes configuration updated
    >>> Assign a different config epoch to each node
    >>> Sending CLUSTER MEET messages to join the cluster
    Waiting for the cluster to join
    .....
    >>> Performing Cluster Check (using node 192.168.7.101:6379)
    M: f4cfc5cf821c0d855016488d6fbfb62c03a14fda 192.168.7.101:6379 #master 的 ID 及端口
    slots:[0-5460] (5461 slots) master #已经分配的槽位
    1 additional replica(s) #分配了一个 slave
    S: 7186c6d03dd9a5e3be658f2d08e800bc55b04a09 192.168.7.102:6380
    slots: (0 slots) slave #slave 没有分配槽位
    replicates f4cfc5cf821c0d855016488d6fbfb62c03a14fda
    M: 70de3821dde4701c647bd6c23b9dd3c5c9f24a62 192.168.7.103:6379
    slots:[10923-16383] (5461 slots) master
    1 additional replica(s)
    M: 116c4c6de036fdbac5aaad25eb1a61ea262b64af 192.168.7.102:6379slots:[5461-10922] (5462 slots) master
    1 additional replica(s)
    S: 2b6e5d9c3944d79a5b64a19e54e52f83d48438d6 192.168.7.101:6380
    slots: (0 slots) slave
    replicates 70de3821dde4701c647bd6c23b9dd3c5c9f24a62
    S: 7eda0bcf0c01bb7343313b81267c42dd1b26c8a6 192.168.7.103:6380
    slots: (0 slots) slave
    replicates 116c4c6de036fdbac5aaad25eb1a61ea262b64af
    [OK] All nodes agree about slots configuration. #所有节点槽位分配完成
    >>> Check for open slots... #检查打开的槽位
    >>> Check slots coverage... #检查插槽覆盖范围
    [OK] All 16384 slots covered. #所有槽位(16384 个)分配完成
    

3.2.2.2.3:检查状态

由于未设置 masterauth 认证密码, 所以主从未建立起来, 但是集群已经运行,所以需要在每个 slave控制台使用 config set 设置 masterauth 密码,或者写在每个 redis 配置文件中,最好是在控制点设置密码之后再写入配置文件当中

image.png

3.2.2.2.4: 分别设置 masterauth 密码

[root@redis-s1 ~]# redis-cli -h 192.168.7.101 -p 6380 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.7.101:6380> CONFIG SET masterauth 123456
OK
[root@redis-s1 ~]# redis-cli -h 192.168.7.102 -p 6380 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.7.102:6380> CONFIG SET masterauth 123456
OK
[root@redis-s1 ~]# redis-cli -h 192.168.7.103 -p 6380 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.192.168.7.103:6380> CONFIG SET masterauth 123456
OK

3.2.2.2.5: 确认 slave 状态为 up

image.png

3.2.2.2.6: 验证 master 状态

[root@redis-s1 ~]# redis-cli -h 192.168.7.101 -p 6379 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be
safe.
192.168.7.101:6379> INFO Replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.7.102,port=6380,state=online,offset=840,lag=0
master_replid:0aa3281030eb29bf268f3317d4afe401f661a917
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:840
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:4026531840
repl_backlog_first_byte_offset:1
repl_backlog_histlen:840

192.168.7.101:6379> CLUSTER INFO
cluster_state:okcluster_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:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:1474
cluster_stats_messages_pong_sent:1507
cluster_stats_messages_sent:2981
cluster_stats_messages_ping_received:1502
cluster_stats_messages_pong_received:1474
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:2981

3.2.2.2.8: 查看集群 node 对应关系

192.168.7.103:6380> cluster nodes
7186c6d03dd9a5e3be658f2d08e800bc55b04a09 192.168.7.102:6380@16380 slave
f4cfc5cf821c0d855016488d6fbfb62c03a14fda 0 1545659135000 4 connected
7eda0bcf0c01bb7343313b81267c42dd1b26c8a6 192.168.7.103:6380@16380 myself,slave
116c4c6de036fdbac5aaad25eb1a61ea262b64af 0 1545659135000 6 conne
ctedf4cfc5cf821c0d855016488d6fbfb62c03a14fda 192.168.7.101:6379@16379 master - 0
1545659135000 1 connected 0-5460
116c4c6de036fdbac5aaad25eb1a61ea262b64af 192.168.7.102:6379@16379 master - 0
1545659136000 3 connected 5461-10922
70de3821dde4701c647bd6c23b9dd3c5c9f24a62 192.168.7.103:6379@16379 master - 0
1545659134000 5 connected 10923-16383
2b6e5d9c3944d79a5b64a19e54e52f83d48438d6 192.168.7.101:6380@16380 slave
70de3821dde4701c647bd6c23b9dd3c5c9f24a62 0 1545659135946 5 connected

3.2.2.2.9: 验证集群写入 key

192.168.7.101:6379> SET key1 value1 #经过算法计算,当前 key 的槽位需要写入指定的 node
(error) MOVED 9189 192.168.7.102:6379 #槽位不在当前 node 所以无法写入
192.168.7.103:6379> SET key1 value1
(error) MOVED 9189 192.168.7.102:6379
192.168.7.102:6379> SET key1 value1 #指定的 node 就可以写入
OK
192.168.7.102:6379> KEYS *
1) "key1
192.168.7.101:6379> KEYS *
(empty list or set)
192.168.7.103:6379> KEYS *
(empty list or set)

3.2.2.2.10: 集群状态监控

#Redis 4
[root@s1 ~]# redis-trib.rb check 172.18.200.105:6379
>>> Performing Cluster Check (using node 172.18.200.105:6379)
S: dfa53d634b3bd798e256ef9861579d5e637fc4b0 172.18.200.105:6379
slots: (0 slots) slave
replicates 99e09216d4ca5739788791da81a816bd2322802d
M: 3ed26459bcdf4bbd3004c9a7506ba1f6e87dd55a 172.18.200.102:6379
slots:5461-10922 (5462 slots) master
1 additional replica(s)
M: 99e09216d4ca5739788791da81a816bd2322802d 172.18.200.101:6379
slots:0-5460 (5461 slots) master
1 additional replica(s)
S: 45e28f36573eb5123c27b359ae870e55a7d73017 172.18.200.104:6379
slots: (0 slots) slave
replicates 4d6357633a82f4ab48910d9c26dec8a2ef5b757c
S: adc943d76aa9ef1b123319f0772e4322756f34a2 172.18.200.106:6379
slots: (0 slots) slave
replicates 3ed26459bcdf4bbd3004c9a7506ba1f6e87dd55a
M: 4d6357633a82f4ab48910d9c26dec8a2ef5b757c 172.18.200.103:6379
slots:10923-16383 (5461 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
[root@s1 ~]# redis-trib.rb info 172.18.200.105:6379
172.18.200.102:6379 (3ed26459...) -> 1 keys | 5462 slots | 1 slaves.
172.18.200.101:6379 (99e09216...) -> 0 keys | 5461 slots | 1 slaves.
172.18.200.103:6379 (4d635763...) -> 0 keys | 5461 slots | 1 slaves.
[OK] 1 keys in 3 masters.
0.00 keys per slot on average.

#Redis 5
redis-cli -a 123456 --cluster check 192.168.7.101:6379

小笔记:配置集群

#6台机器
#A:192.168.37.7 B:192.168.37.17 C:192.168.37.27 D:192.168.37.37 E:192.168.37.47 F:192.168.37.57

#先把哨兵取消
mv /apps/redis/etc/sentinel.conf /apps/redis/etc/sentinel.conf.bak
killall redis-sentinel
redis-cli -a 123456
flushall                    #清空数据
rm -rf /apps/redis/data/*
rm -rf /apps/redis/logs/*

#集群
#A到F
vim /apps/redis/etc/redis.conf
    bind 0.0.0.0
    requirepass 123456
    cluster-enabled yes         #开启集群
    cluster-config-file nodes-6379.conf
    #slaveof 192.168.37.7 6379
    masterauth 123456

#创建集群,所有机器都启动服务,并保证没有数据
#随便一台机器执行集群即可,以A为例,redis5.0以下需要redis-trib建立集群,5.0以上则用redis-cli即可
cp /usr/local/src/redis-4.1.2/src/redis-trib.rb /usr/sbin
wget https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.5.tar.gz
tar xf ruby-2.5.5.tar.gz
cd ruby-2.5.5
./configure
make -j 2
make install
gem install redis

vim /usr/local/lib/ruby/gems/2.5.0/gems/redis-4.1.2/lib/redis/client.rb
    :password ==> 123456;
redis-trib.rb create --replicas 192.168.37.7:6379 192.168.37.17:6379  192.168.37.27:6379  192.168.37.37:6379  192.168.37.47:6379  192.168.37.57:6379

#redis5
redis-cli -a 123456 --cluster create 192.168.7.101:6379 192.168.7.101:6380 192.168.7.102:6379 192.168.7.102:6380 192.168.7.103:6379 192.168.7.103:6380 --cluster-replicas 1

#查看集群状态信息
#redis 4
redis-trib.rb info 192.168.37.7:6379
redis-trib.rb check 192.168.37.7:6379
#redis 5
redis-cli -a 123456 --cluster check 192.168.37.7:6379

#创建集群后6台机器会变成3组主从集群
1:192.168.37.7:6379,192.168.37.37:6379
2:192.168.37.17:6379,192.168.37.47:6379
3:192.168.37.27:6379,192.168.37.57:6379
3.2.3: Redis cluster 集群节点维护
  • 集群运行时间长久之后,难免由于硬件故障、网络规划、 业务增长等原因对已有集群进行相应的调整,比如增加 Redis node 节点、 减少节点、 节点迁移、更换服务器等。

  • 增加节点和删除节点会涉及到已有的槽位重新分配及数据迁移

    3.2.3.1: 集群维护之动态添加节点

    • 增加 Redis node 节点,需要与之前的 Redis node 版本相同、配置一致,然后分别启动两台 Redis node,因为一主一从。

      案例:因公司业务发展迅猛, 现有的三主三从 redis cluster 架构可能无法满足现有业务的并发写入需求,因
      此公司紧急采购一台服务器 192.168.7.104,需要将其动态添加到集群当中其不能影响业务使用和数据
      丢失,则添加过程如下 :

    #同步之前 Redis node 的配置文件到 192.168.7.104 Redis 编译安装目录, 注意配置文件的监听 IP。
    scp redis.conf 192.168.7.104:/usr/local/redis/etc/
    scp redis_6380.conf 192.168.7.104:/usr/local/redis/etc/
    #分别启动 redis 服务:
    systemctl daemon-reload
    systemctl restart redis
    /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis_6380.conf
    

    3.2.3.1.1: 添加节点到集群

    redis-trib.rb add-node new_host:new_port existing_host:existing_port
    #要添加的新 redis 节点 IP 和端口 添加到的集群中的 master IP:端口, 加到集群之后默认是 master 节点但是没有slots 数据,需要重新分配。
    #Redis 4 添加方式:
    [root@s1 ~]# redis-trib.rb add-node 172.18.200.106:6379 172.18.200.101:6379
    #Redis 5 添加方式:
    redis-cli -a 123456 --cluster add-node 192.168.7.104:6379 192.168.7.101:6379
    

    3.2.3.1.2:分配槽位:

    • 添加主机之后需要对添加至集群种的新主机重新分片否则其没有分片
#验证当前状态
#Redis 3/4:
[root@s1 ~]# redis-trib.rb reshard 172.18.200.107:6379
[root@s1 ~]# redis-trib.rb check 172.18.200.101:6379  
#Redis 5:
[root@s1 ~]# redis-cli -a 123456 --cluster check 192.168.7.103:6379
image.png
#使用命令对新加的主机重新分配槽位:
[root@redis-s1 ~]# redis-cli -a 123456 --cluster reshard 192.168.7.104:6379
[root@redis-s1 ~]# redis-cli -a 123456 --cluster reshard 192.168.7.104:6379
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Performing Cluster Check (using node 192.168.7.104:6379)
M: 886338acd50c3015be68a760502b239f4509881c 192.168.7.104:6379
slots: (0 slots) master
M: 116c4c6de036fdbac5aaad25eb1a61ea262b64af 192.168.7.102:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: 2b6e5d9c3944d79a5b64a19e54e52f83d48438d6 192.168.7.101:6380
slots: (0 slots) slave
replicates 70de3821dde4701c647bd6c23b9dd3c5c9f24a62
S: 7186c6d03dd9a5e3be658f2d08e800bc55b04a09 192.168.7.102:6380
slots: (0 slots) slave
replicates f4cfc5cf821c0d855016488d6fbfb62c03a14fda
M: 70de3821dde4701c647bd6c23b9dd3c5c9f24a62 192.168.7.103:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 7eda0bcf0c01bb7343313b81267c42dd1b26c8a6 192.168.7.103:6380
slots: (0 slots) slave
replicates 116c4c6de036fdbac5aaad25eb1a61ea262b64af
M: f4cfc5cf821c0d855016488d6fbfb62c03a14fda 192.168.7.101:6379
slots:[0-5460] (5461 slots) master1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
How many slots do you want to move (from 1 to 16384)? 4096 #分配多少个槽位 192.168.7.104:6379
What is the receiving node ID? 886338acd50c3015be68a760502b239f4509881c #接收 slot 的服务器 ID, 手动输入
192.168.7.104 的 node ID
Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes for the hash slots.
Type 'done' once you entered all the source nodes IDs.
Source node #1: all #将哪些源主机的槽位分配给 192.168.7.104:6379, all 是自动在所有的 redis node 选择划分,如果是从 redis cluster 删除主机可以使用此方式将主机上的槽位全部移动到别的 redis 主机
………………………………..
Moving slot 6823 from 116c4c6de036fdbac5aaad25eb1a61ea262b64af
Moving slot 6824 from 116c4c6de036fdbac5aaad25eb1a61ea262b64af
Moving slot 6825 from 116c4c6de036fdbac5aaad25eb1a61ea262b64af
Moving slot 6826 from 116c4c6de036fdbac5aaad25eb1a61ea262b64af
Moving slot 10923 from 70de3821dde4701c647bd6c23b9dd3c5c9f24a62
Moving slot 10924 from 70de3821dde4701c647bd6c23b9dd3c5c9f24a62
Moving slot 10925 from 70de3821dde4701c647bd6c23b9dd3c5c9f24a62
Moving slot 10926 from 70de3821dde4701c647bd6c23b9dd3c5c9f24a62
…………………………………..
Moving slot 1364 from f4cfc5cf821c0d855016488d6fbfb62c03a14fda
Do you want to proceed with the proposed reshard plan (yes/no)? yes #确认分配
image.png

3.2.3.1.3: 验证重新分配槽位之后的集群状态

  • 重新分配槽位是自动从每个 Redis node 上移动一些槽位到新的 master 上

    redis-cli -a 123456 --cluster check 192.168.7.103:6379

    image.png

3.2.3.1.4: 为新的 master 添加 slave 节点

  • 命令格式: redis-cli -a 123456 --cluster add-node 192.168.7.104:6380 192.168.7.104:6379

    [图片上传失败...(image-c370f6-1591525426362)]

3.2.3.1.5:更改新节点更改状态为 slave

  • 需要手动将其指定为某个 master 的 slave, 否则其默认角色为 master

    [root@redis-s1 ~]# redis-cli -h 192.168.7.104 -p 6380 -a 123456 #登录到新添加节点
    Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
    192.168.7.104:6380> CLUSTER NODES #查看当前集群节点,找到目标 master 的 ID
    7eda0bcf0c01bb7343313b81267c42dd1b26c8a6 192.168.7.103:6380@16380 slave 116c4c6de036fdbac5aaad25eb1a61ea262b64af 0 1545700464964 3 connected
    116c4c6de036fdbac5aaad25eb1a61ea262b64af 192.168.7.102:6379@16379 master - 0 1545700470516 3 connected 6827-10922
    2b6e5d9c3944d79a5b64a19e54e52f83d48438d6 192.168.7.101:6380@16380 slave 70de3821dde4701c647bd6c23b9dd3c5c9f24a62 0 1545700468498 5 connected
    b9a00d59fa3c2a322080a1c7d84f53a2c853b089 192.168.7.104:6380@16380 myself,master - 0 1545700464000 0 connected
    886338acd50c3015be68a760502b239f4509881c 192.168.7.104:6379@16379 master - 0 1545700465468 7 connected 0-1364 5461-6826 10923-12287
    70de3821dde4701c647bd6c23b9dd3c5c9f24a62 192.168.7.103:6379@16379 master - 0 1545700467489 5 connected 12288-16383
    f4cfc5cf821c0d855016488d6fbfb62c03a14fda 192.168.7.101:6379@16379 master - 0 1545700464461 1 connected 1365-5460
    7186c6d03dd9a5e3be658f2d08e800bc55b04a09 192.168.7.102:6380@16380 slave f4cfc5cf821c0d855016488d6fbfb62c03a14fda 0 1545700469508 1 connected
    192.168.7.104:6380> CLUSTER REPLICATE 886338acd50c3015be68a760502b239f4509881c #将其设置 slave,命令格式为 cluster replicate MASTERID
    OK
    192.168.7.104:6380> CLUSTER NODES #再次查看集群节点状态, 验证节点是否已经更改为指定 master 的 slave
    7eda0bcf0c01bb7343313b81267c42dd1b26c8a6 192.168.7.103:6380@16380 slave 116c4c6de036fdbac5aaad25eb1a61ea262b64af 0 1545700517970 3 connected
    116c4c6de036fdbac5aaad25eb1a61ea262b64af 192.168.7.102:6379@16379 master - 0 1545700514942 3 connected 6827-10922
    2b6e5d9c3944d79a5b64a19e54e52f83d48438d6 192.168.7.101:6380@16380 slave 70de3821dde4701c647bd6c23b9dd3c5c9f24a62 0 1545700518979 5 connected
    b9a00d59fa3c2a322080a1c7d84f53a2c853b089 192.168.7.104:6380@16380 myself,slave 886338acd50c3015be68a760502b239f4509881c 0 1545700509000 0 connected
    886338acd50c3015be68a760502b239f4509881c 192.168.7.104:6379@16379 master - 0 1545700516456 7 connected 0-1364 5461-6826 10923-12287
    70de3821dde4701c647bd6c23b9dd3c5c9f24a62 192.168.7.103:6379@16379 master - 0 1545700519988 5 connected 12288-16383
    f4cfc5cf821c0d855016488d6fbfb62c03a14fda 192.168.7.101:6379@16379 master - 0 1545700515953 1 connected 1365-5460
    7186c6d03dd9a5e3be658f2d08e800bc55b04a09 192.168.7.102:6380@16380 slave f4cfc5cf821c0d855016488d6fbfb62c03a14fda 0 1545700516962 1 connected
    

3.2.3.1.6:验证当前集群状态

  • redis-cli -a 123456 --cluster check 192.168.7.103:6379

    image.png

3.2.3.2:集群维护之动态删除节点

  • 添加节点的时候是先添加 node 节点到集群,然后分配槽位,删除节点的操作与添加节点的操作正好相反,是先将被删除的 Redis node 上的槽位迁移到集群中的其他 Redis node 节点上,然后再将其删除。

  • 如果一个 Redis node 节点上的槽位没有被完全迁移, 删除该 node 的时候会提示有数据且无法删除。

  • 案例:
    由于 192.168.7.101 服务器使用年限已经超过三年, 已经超过厂商质保期而且硬盘出现异常报警, 经运维部架构师提交方案并同开发同事开会商议,决定将现有 Redis 集群的 4 台服务器分别是: 192.168.7.101/192.168.7.102/192.168.7.103/192.168.7.104 中的 192.168.7.101 临时下线,三台服务器的并发写入性能足够支出未来 1-2 年的业务需求,则删除 Redis node 192.168.7.101 的操作如下:

    3.2.3.2.1:迁移 master 的槽位之其他 master

    #被迁移 Redis 服务器必须保证没有数据
    [root@s1 ~]# redis-trib.rb reshard 172.18.200.101:6379
    [root@s1 ~]# redis-trib.rb fix 172.18.200.101:6379 #迁移失败需要修复集群
    [root@redis-s1 ~]# redis-cli -a 123456 --cluster reshard 192.168.7.102:6379
    Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.>>> Performing Cluster Check (using node 192.168.7.102:6379)
    M: 116c4c6de036fdbac5aaad25eb1a61ea262b64af 192.168.7.102:6379
    slots:[6827-10922] (4096 slots) master
    1 additional replica(s)
    M: 70de3821dde4701c647bd6c23b9dd3c5c9f24a62 192.168.7.103:6379
    slots:[12288-16383] (4096 slots) master
    1 additional replica(s)
    M: 886338acd50c3015be68a760502b239f4509881c 192.168.7.104:6379
    slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master
    1 additional replica(s)
    S: 7eda0bcf0c01bb7343313b81267c42dd1b26c8a6 192.168.7.103:6380
    slots: (0 slots) slave
    replicates 116c4c6de036fdbac5aaad25eb1a61ea262b64af
    S: b9a00d59fa3c2a322080a1c7d84f53a2c853b089 192.168.7.104:6380
    slots: (0 slots) slave
    replicates 886338acd50c3015be68a760502b239f4509881c
    S: 7186c6d03dd9a5e3be658f2d08e800bc55b04a09 192.168.7.102:6380
    slots: (0 slots) slave
    replicates f4cfc5cf821c0d855016488d6fbfb62c03a14fda
    S: 2b6e5d9c3944d79a5b64a19e54e52f83d48438d6 192.168.7.101:6380
    slots: (0 slots) slave
    replicates 70de3821dde4701c647bd6c23b9dd3c5c9f24a62
    M: f4cfc5cf821c0d855016488d6fbfb62c03a14fda 192.168.7.101:6379
    slots:[1365-5460] (4096 slots) master
    1 additional replica(s)
    [OK] All nodes agree about slots configuration.
    >>> Check for open slots...
    >>> Check slots coverage...
    [OK] All 16384 slots covered.
    How many slots do you want to move (from 1 to 16384)? 4096 #迁移 master 上的多少个槽位
    What is the receiving node ID? 886338acd50c3015be68a760502b239f4509881c #接收槽位的服务器 ID
    Please enter all the source node IDs.
    Type 'all' to use all the nodes as source nodes for the hash slots.
    Type 'done' once you entered all the source nodes IDs.
    Source node #1: f4cfc5cf821c0d855016488d6fbfb62c03a14fda #从哪个服务器迁移 4096 个槽位
    Source node #2: done #写 done,表示没有其他 master 了
    Moving slot 5457 from f4cfc5cf821c0d855016488d6fbfb62c03a14fda
    Moving slot 5458 from f4cfc5cf821c0d855016488d6fbfb62c03a14fda
    Moving slot 5459 from f4cfc5cf821c0d855016488d6fbfb62c03a14fda
    Moving slot 5460 from f4cfc5cf821c0d855016488d6fbfb62c03a14fda
    Do you want to proceed with the proposed reshard plan (yes/no)? yes #是否继续
    
    image.png

    3.2.3.2.2: 验证槽位迁移完成

    image.png

    3.2.3.2.3: 从集群删除服务器

    #虽然槽位已经迁移完成,但是服务器 IP 信息还在集群当中,因此还需要将 IP 信息从集群删除命令格式: redis-cli -a 123456 --cluster del-node IP:Port ID#删除 master:
    #Redis 4:
    [root@s1 ~]# redis-trib.rb del-node 172.18.200.102:6379
    3ed26459bcdf4bbd3004c9a7506ba1f6e87dd55a
    >>> Removing node 3ed26459bcdf4bbd3004c9a7506ba1f6e87dd55a from cluster 172.18.200.102:6379
    >>> Sending CLUSTER FORGET messages to the cluster...
    >>> SHUTDOWN the node.
    #Redis 5:
    [root@redis-s1 ~]# redis-cli -a 123456 --cluster del-node 192.168.7.101:6379 f4cfc5cf821c0d855016488d6fbfb62c03a14fda
    Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
    >>> Removing node f4cfc5cf821c0d855016488d6fbfb62c03a14fda from cluster 192.168.7.101:6379
    >>> Sending CLUSTER FORGET messages to the cluster...
    >>> SHUTDOWN the node.
    

    3.2.3.2.4: 验证 node 是否删除

    • 发现 192.168.7.101 已经被删除,但是由于 192.168.7.101:6380 之前是 192.168.7.103:6379 的 slave, 所以删除后会导致相应的 master 缺少 slave, 需要重新为没有 slave 的 master 分配 slave。
    • 可以发现下图的 192.168.7.104 有两个 slave,分别是 192.168.7.102:6380 和 192.168.7.104:6380,因此需要将其中一个 slave 转移为 192.168.7.103 的 slave。
      image.png

    3.2.3.2.5: 重新分配 slave

    • 将 192.168.7.104:6380 转移为 192.168.7.103 的 slave

      #将 192.168.7.104:6380 转移为 192.168.7.103 的 slave
      [root@redis-s1 ~]# redis-cli -h 192.168.7.104 -p 6379 -a 123456
      Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
      192.168.7.104:6379> CLUSTER NODES
      116c4c6de036fdbac5aaad25eb1a61ea262b64af 192.168.7.102:6379@16379 master - 0 1545708439000 3 connected 6827-10922
      b9a00d59fa3c2a322080a1c7d84f53a2c853b089 192.168.7.104:6380@16380 slave 886338acd50c3015be68a760502b239f4509881c 0
      1545708440717 7 connected
      7186c6d03dd9a5e3be658f2d08e800bc55b04a09 192.168.7.102:6380@16380 slave 886338acd50c3015be68a760502b239f4509881c 0
      1545708437682 7 connected
      886338acd50c3015be68a760502b239f4509881c 192.168.7.104:6379@16379 myself,master - 0 1545708439000 7 connected 0-6826 10923-
      12287
      70de3821dde4701c647bd6c23b9dd3c5c9f24a62 192.168.7.103:6379@16379 master - 0 1545708440000 5 connected 12288-16383
      7eda0bcf0c01bb7343313b81267c42dd1b26c8a6 192.168.7.103:6380@16380 slave 116c4c6de036fdbac5aaad25eb1a61ea262b64af 0
      1545708438697 3 connected
      192.168.7.104:6380> CLUSTER REPLICATE 70de3821dde4701c647bd6c23b9dd3c5c9f24a62
      

    3.2.3.2.6:验证集群 Master 与 Slave 对应关系

    • Redis Slave 节点一定不能个 master 在一个服务器,必须为跨主机交叉备份模式,避免主机故障后主备全部挂掉, 如果出现 Redis Slave 与 Redis master 在同一台 Redis node 的情况, 则需要安装以上步骤重新进行 slave 分配,直到不相互交叉备份为止。

      image.png

3.2.3.3:集群维护之模拟 Master 宕机

  • 目前的架构为三主三从,互为跨主机 master slave 模式,测试 master 宕机之后是否会自动切换至 slave

    3.2.3.3.1:测试数据写入
    测试在 master 写入数据,并在其对应的 slave 验证数据

    192.168.7.102:6379> SET key1 value1
    OK
    192.168.7.102:6379> get key1
    "value1"
    

    3.2.3.3.2: slave 验证数据

    192.168.7.103:6380> KEYS *
    1) "key1"
    192.168.7.103:6380> get key1
    (error) MOVED 9189 192.168.7.102:6379 #slave 不提供读写,只提供数据备份即 master 选举
    

    3.2.3.3.3: 停止 master 并验证故障转移

    #Redis Master 服务停止之后,其对应的 slave 会被选举为 master 继续处理数据的读写操作。
    systemctl stop redis
    

    3.2.3.3.4:验证 slave 日志

    tail -f /usr/local/redis/redis_6380.log #需要相应的数秒故障转移时间 (约15秒)

    image.png

    3.2.3.3.5: 验证 slave 状态

    image.png

    3.2.3.3.6: 验证数据读写

    #确认 slave 192.168.7.103:6380 切换为 master 之后可以继续为业务提供读写业务且数据没有丢失。
    192.168.7.103:6380> KEYS *1) "key1"
    192.168.7.103:6380> SET aaa bbb
    OK
    192.168.7.103:6380> get key1
    "value1"
    192.168.7.103:6380> get aaa
    "bbb"
    192.168.7.103:6380>
    #注:服务恢复之后重新验证各 master 的 slave
    

3.2.3.4: 集群维护之导入现有 Redis 数据

  • 导入数据需要 redis cluster 不能与被导入的数据有重复的 key 名称, 否则导入不成功或中断。

  • 案例:公司将 redis cluster 部署完成之后,需要将之前的数据导入之 Redis cluster 集群, 但是由于 Redis cluster使用的分片保存 key 的机制,因此使用传统的 AOF 文件或 RDB 快照无法满足需求,因此需要使用集群数据导入命令完成。

    3.2.3.4.1: 基础环境准备

    • 导入数据之前需要关闭各 redis 服务器的密码, 包括集群中的各 node 和源 Redis server, 避免认证带来的环境不一致从而无法导入, 可以加参数--cluster-replace 强制替换 Redis cluster 已有的 key。
    [root@redis-s1 ~]# redis-cli -h 192.168.7.102 -p 6379 -a 123456
    Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
    192.168.7.102:6379> CONFIG SET requirepass ""
    OK
    192.168.7.104:6379> exit
    [root@redis-s1 ~]# redis-cli -h 192.168.7.102 -p 6380 -a 123456
    Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
    192.168.7.102:6380> CONFIG SET requirepass ""
    OK
    192.168.7.104:6379> exit
    [root@redis-s1 ~]# redis-cli -h 192.168.7.103 -p 6379 -a 123456
    Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
    192.168.7.103:6379> CONFIG SET requirepass ""
    OK
    192.168.7.103:6379> exit
    [root@redis-s1 ~]# redis-cli -h 192.168.7.103 -p 6380 -a 123456
    Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
    192.168.7.103:6380> CONFIG SET requirepass ""
    OK
    192.168.7.104:6379> exit
    [root@redis-s1 ~]# redis-cli -h 192.168.7.104 -p 6379 -a 123456
    Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
    192.168.7.104:6379> CONFIG SET requirepass ""
    OK
    192.168.7.104:6379> exit[root@redis-s1 ~]# redis-cli -h 192.168.7.104 -p 6380 -a 123456
    Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
    192.168.7.104:6380> CONFIG SET requirepass ""
    OK
    192.168.7.104:6379> exit
    

    3.2.3.4.2:执行数据导入

    • 将源 Redis server 的数据直接导入之 redis cluster。
      命令格式:
    #Redis 3/4:
    [root@s1 ~]# redis-trib.rb import --from 172.18.200.107:6382 --replace 172.18.200.107:6379
    #Redis 5:
    redis-cli --cluster import 集群服务器 IP:PORT --cluster-from 外部 Redis node-IP:PORT --cluster-copy --cluster-replace
    [root@redis-s2 redis]# redis-cli --cluster import 192.168.7.103:6379 --cluster-from 192.168.7.101:6379 --cluster-copy
    
    image.png

    3.2.3.4.3: Redis cluster 验证数据

    image.png

3.2.4: redis 扩展集群方案:

  • 除了 Redis 官方自带的 Redis cluster 集群之外,还有一些开源的集群解决方案可供参考使用

    3.2.4.1: codis:

    • Codis 是一个分布式 Redis 解决方案, 对于上层的应用来说, 连接到 Codis Proxy 和连接原生的Redis Server 没有显著区别 (令不支持的命列表), 上层应用可以像使用单机的 Redis 一样使用, Cod底层会处理请求的转发, 不停机的数据迁移等工作, 所有后边的一切事情, 对于前面的客户端来说是透明的, 可以简单的认为后边连接的是一个内存无限大的 Redis 服务。
    • codis-proxy 相当于 redis,即连接 codis-proxy 和连接 redis 是没有任何区别的, codis-proxy 无状态,不负责记录是否在哪保存,数据在 zookeeper 记录,即 codis proxy 向 zookeeper 查询 key 的记录位置,proxy 将请求转发到一个组进行处理,一个组里面有一个 master 和一个或者多个 slave 组成,默认有1024 个槽位, redis cluster 默认有 16384 个槽位,其把不同的槽位的内容放在不同的 group。
      Github 地址: https://github.com/CodisLabs/codis/blob/release3.2/doc/tutorial_zh.md
    • 1

    3.2.4.2: twemproxy

小笔记:集群管理

#添加新机器
1、添加新机器192.168.37.67
vim /apps/redis/etc/redis.conf
    bind 0.0.0.0
    requirepass 123456
    cluster-enabled yes         #开启集群
    cluster-config-file nodes-6379.conf
    #slaveof 192.168.37.7 6379
    masterauth 123456
systemctl start redis

2、新节点添加到集群
#redis 4
redis-trib.rb add-node 192.168.37.67:6379 192.168.37.57:6379
#redis 5
redis-cli -a 123456 --cluster add-node 192.168.37.67:6379 192.168.37.57:6379
#新机器再添加一个6380节点
cp -a /apps/redis /apps/redis-6380
vim /apps/redis-6380/etc/redis.conf
    pidfile /apps/redis/run/redis-6380.pid
    logfile "/apps/redis/logs/redis-6380.log"
    port 6380
    cluster-config-file nodes-6380.conf
redis-server /apps/redis-6380/etc/redis.conf

3、分配槽位
#集群管理机器上操作(这里是A机器)
redis-cli -a 123456 cluster nodes       #找到107:6379的id号
redis-cli -h 192.168.37.67 -p 6380
    AUTH 123456
    CLUSTER REPLICATE node-id
    CLUSTER nodes
    
redis-trib.rb reshard 192.168.37.57:6379    #分配槽位
#redis-cli -a 123456 --cluster reshard 192.168.37.57:6379   #redis 5
    How many slots do you want to move (from 1 to 16384)? 4096  #分配多少个槽位 192.168.37.57:6379
    What is the receiving node ID? node-id      #接收slot的服务器 ID,手动输入192.168.37.57 的 node ID
    Source node #1: all     #将哪些源主机的槽位分配给 192.168.7.104:6379,all是自动在所有的 redis node 选择划分,如果是从 redis cluster 删除主机可以使用此方式将主机上的槽位全部移动到别的 redis 主机
    Do you want to proceed with the proposed reshard plan (yes/no)? yes #确认分配

#!!!注意:节点上有数据会导致分配槽位失败,需要清空对应的redis数据
redis-trib.rb fix 192.168.37.57:6379        #修复
redis-cli -a 123456 cluster nodes           #找到107:6379的id号和已分配的slot
redis-trib.rb reshard 192.168.37.57:6379    #分配槽位
    How many slots do you want to move (from 1 to 16384)? 4096-已分配slot  
    What is the receiving node ID? node-id      
    Source node #1: all
    Do you want to proceed with the proposed reshard plan (yes/no)? yes 

#---------------分割线-----------------#

#下线节点,被迁移 Redis 服务器必须保证没有数据 
redis-trib.rb reshard 192.168.37.67:6379
#redis-cli -a 123456 --cluster reshard 192.168.37.67:6379       #redis 5
    How many slots do you want to move (from 1 to 16384)? 4096  #迁移 master 上的多少个槽位
    What is the receiving node ID? 迁移到的机器node-id        #接收槽位的服务器 ID
    Source node #1: 67-node-id                          #从哪个服务器迁移 4096 个槽位
    Source node #2: done                                #写done,表示没有其他 master 了
    Do you want to proceed with the proposed reshard plan (yes/no)? yes #是否继续
#迁移失败的话执行以下修复
redis-trib.rb fix 192.168.37.67:6379
#删除节点
redis-trib.rb del-node 192.168.37.67:6379 node-id
#redis-cli -a 123456 --cluster 192.168.37.67:6379 node-id       #redis5

四: memcached

Memcache 官网: http://memcached.org/

  • memcache 本身没有像 redis 所具备的数据持久化功能,比如 RDB 和 AOF 都没有,但是可以通过做集群同步的方式,让各 memcache 服务器的数据进行同步,从而实现数据的一致性,即保证各 memcache的数据是一样的,即使有任何一台 memcache 发生故障,只要集群种有一台 memcache 可用就不会出现数据丢失,当其他 memcache 重新加入到集群的时候可以自动从有数据的 memcache 当中自动获取数据并提供服务。

  • Memcache 借助了操作系统的 libevent 工具做高效的读写。 libevent 是个程序库,它将 Linux 的 epoll、BSD 类操作系统的 kqueue 等事件处理功能封装成统一的接口。即使对服务器的连接数增加,也能发挥高性能。 memcached 使用这个 libevent 库,因此能在 Linux、 BSD、 Solaris 等操作系统上发挥其高性能。

  • Memcache 支持最大的内存存储对象为 1M, 超过 1M 的数据可以使用客户端压缩或拆分报包放到多个key 中,比较大的数据在进行读取的时候需要消耗的时间比较长, memcache 最适合保存用户的 session实现 session 共享, Memcached 存储数据时, Memcached 会去申请 1MB 的内存, 把该块内存称为一个slab, 也称为一个 page。

  • memcached 具有多种语言的客户端开发包,包括: Perl/PHP/JAVA/C/Python/Ruby/C#/

4.1: 单机部署:

4.1.1: yum 安装与启动

  • 通过 yum 安装是相对简单的安装方式

    yum install memcached -y
    vim /etc/sysconfig/memcached
    PORT="11211" #监听端口
    USER="memcached" #启动用户
    MAXCONN="1024" #最大连接数
    CACHESIZE="1024" #最大使用内存
    OPTIONS="" #其他选项
    

4.1.2: python 操作 memcache

#!/usr/bin/env python
#coding:utf-8
#Author:Zhang ShiJie
import memcache
m = memcache.Client(['172.18.200.106:11211'], debug=True)
for i in range(100):
    m.set("key%d" % i,"v%d" % i)
    ret = m.get('key%d' % i)
    print ret

4.1.2: 编译安装:

yum install libevent libevent-devel –y
pwd
/usr/local/src
tar xvf memcached-1.5.12.tar.gz
./configure --prefix=/usr/local/memcache
make && make install 

启动 memcached
# /usr/local/memcache/bin/memcached -u memcached -p 11211 -m 2048 -c 65536 &
4.2: memcached 集群部署架构:
  • 4.2.1: 基于 magent 的部署架构

  • 该部署方式依赖于 magent 实现高可用, 应用端通过负载服务器连接到 magent,然后再由 magent代理用户应用请求到 memcached 处理,底层的 memcached 为双主结构会自动同步数据, 本部署方式存在 magent 单点问题因此需要两个 magent 做高可用。

    image.png

    4.2.2: Repcached 实现原理

    • 在 master 上可以通过 -X 指定 replication port,在 slave 上通过 -x/-X 找到 master 并 connect 上去,事实上,如果同时指定了 -x/-X, repcached 一定会尝试连接,但如果连接失败,它就会用 -X 参数来自己 listen(成为 master);如果 master 坏掉, slave 侦测到连接断了,它会自动 listen 而成为 master;而如果 slave 坏掉, master 也会侦测到连接断,它就会重新 listen 等待新的 slave 加入。

    • 从这方案的技术实现来看,其实它是一个单 master 单 slave 的方案,但它的 master/slave 都是可读写
      的,而且可以相互同步,所以从功能上看,也可以认为它是双机 master-master 方案。

    4.2.3: 简化后的部署架构

    • magent 已经有很长时间没有更新,因此可以不再使用 magent,直接通过负载均衡连接之 memcached 任然有两台 memcached 做高可用,memcached 会自动同步数据保持数据一致性,即使一台 memcached 故障也不影响业务正常运行, 故障的 memcached 修复上线后再自动从另外一台同步数据即可保持数据一致性。

      image.png

    4.2.4: 部署 repcached

    http://repcached.sourceforge.net/

    [root@s6 src]# yum install libevent libevent-devel
    [root@s6 src]# wget https://sourceforge.net/projects/repcached/files/repcached/2.2.1-1.2.8/memcached-1.2.8-repcached-2.2.1.tar.gz
    [root@s6 src]# tar xvf memcached-1.2.8-repcached-2.2.1.tar.gz
    [root@s6 src]# cd memcached-1.2.8-repcached-2.2.1
    [root@s6 memcached-1.2.8-repcached-2.2.1]# ./configure --prefix=/usr/local/repcached --enable-replication
    [root@s6 memcached-1.2.8-repcached-2.2.1]# make #报错如下
    
    image.png
      #解决办法
      [root@s6 memcached-1.2.8-repcached-2.2.1]# vim memcached.c
      56 #ifndef IOV_MAX
      57 #if defined(__FreeBSD__) || defined(__APPLE__)
      58 # define IOV_MAX 1024
      59 #endif
      60 #endif
      
      #应用程序改为如下内容
      55 /* FreeBSD 4.x doesn't have IOV_MAX exposed. */
      56 #ifndef IOV_MAX
      57 # define IOV_MAX 1024
      58 #endif
      
      #再次编译安装
      [root@s6 memcached-1.2.8-repcached-2.2.1]# make && make install
    
4.3: 启动 memcache:
  • 通过 repcached 安装的 memcached 命令启动 memcache 服务并实现 memcache 主备结构,其中-x 为对方即主 memcache 的 IP, -X 为本地启动的用数据同步的端口

    4.3.1: server 1 相关操作

    [root@s5 ~]# /usr/local/repcached/bin/memcached -d -m 2048 -p 11211 -u root -c 2048 -x 172.18.200.106 -X 16000
    

    4.3.2: server 2 相关操作:

    [root@s6 src]# /usr/local/repcached/bin/memcached -d -m 2048 -p 11211 -u root -c 2048 -x 172.18.200.105 -X 16000  
    

    4.3.3: 连接到 memcache 验证数据

    • 4.3.3.1: shell 命令

      [root@s6 src]# telnet 172.18.200.106 11211
      Trying 172.18.200.106...
      Connected to 172.18.200.106.
      Escape character is '^]'.
      set name 0 0 4
      jack
      STORED
      get name
      VALUE name 0 4
      jack
      END
      quit
      Connection closed by foreign host.
      [root@s6 src]# telnet 172.18.200.105 11211
      Trying 172.18.200.105...
      Connected to 172.18.200.105.
      Escape character is '^]'.
      get name
      VALUE name 0 4
      jack
      END
      quit
      Connection closed by foreign host.
      [root@s6 src]
      
    • 4.3.3.2: python 脚本

      #!/usr/bin/env python
      #coding:utf-8
      #Author:Zhang ShiJie
      import memcache
      m = memcache.Client(['172.18.200.106:11211'], debug=True)
      for i in range(100):
          m.set("key%d" % i,"v%d" % i)
          ret = m.get('key%d' % i)
          print ret
      

小笔记:高可用memcache(很少用了)

#2台机器

1、安装
#memcache-1和memcache-2
yum install libevent libevent-devel
wget https://sourceforge.net/projects/repcached/files/repcached/2.2.1-1.2.8/memcached-1.2.8-repcached-2.2.1.tar.gz
tar xvf memcached-1.2.8-repcached-2.2.1.tar.gz
cd memcached-1.2.8-repcached-2.2.1
vim memcached.c
#删除57、60行,删除后如下
56 #ifndef IOV_MAX
57 # define IOV_MAX 1024
58 #endif
./configure --prefix=/usr/local/repcached --enable-replication
make && make install

2、启动memcache
#memcache-1
# -d:后台 -m:内存 -p:端口 -u:运行用户 -c:并发数 -x:mencache对方IP -X:本地监听端口
/usr/local/repcached/bin/memcached -d -m 2048 -p 11211 -u root -c 2048 -x 192.168.37.17 -X 16000
#memcache-2
/usr/local/repcached/bin/memcached -d -m 2048 -p 11211 -u root -c 2048 -x 192.168.37.7 -X 16000

3、验证数据
[root@ha1 src]# telnet 192.168.37.7 11211
Trying 192.168.37.7...
Connected to 192.168.37.7.
Escape character is '^]'.
set name2 0 0 4     
mage
STORED
get name2
VALUE name2 0 4
mage
END
quit
Connection closed by foreign host.
[root@ha1 src]# telnet 192.168.37.17 11211
Trying 192.168.37.17...
Connected to 192.168.37.17.
Escape character is '^]'.
get name2
VALUE name2 0 4
mage
END
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342