0%

Redis学习汇总

Redis 学习汇总

  • 近期看书看博客看视频,相对较为系统的学习了一下Redis,不过版本还是比较老,主要还是3.X系列的。虽然目前最新的已经是4.X,不过老版本的基本都还兼容。

Redis 编译安装

  • Redis安装有很多种方式,Centos可以快捷的使用yum安装,Ubuntu也可以找到apt源进行安装,我这为了尝鲜,用的的是编译安装,其实蛮简单的,我这里直接在mac下进行编译安装,步骤如下:
  • 首先下载redis源码包 :wget http://download.redis.io/releases/redis-4.0.11.tar.gz
  • 解压 tar -zxvf redis-4.0.11.tar.gz
  • 进入redis-4.0.11目录 cd redis-4.0.11
  • 执行make命令编译(好像需要command tools,之前安装过,没太注意)
  • 然后执行make install 进行安装
  • 然后就可以运行了(mac下直接发送到bin目录下面了,不需要额外配置= =!),执行redis-server 就可以看到熟悉的姐妹了

Redis 简易配置

  • 开始还是单机运行吧,创建一个conf文件,我这里叫做 redis-6379.conf ,内容如下:
1
2
3
4
5
6
7
8
bind 127.0.0.1 #绑定Ip
port 6379 #暴露端口
daemonize yes #后台启动
pidfile /Users/eviltuzki/Public/redis/redis_6379.pid
logfile "/Users/eviltuzki/Public/redis/6379.log"
databases 16
dbfilename dump.rdb
dir /Users/eviltuzki/Public/redis #工作目录
  • 配置都比较简单,就不过多解释了,主要就是一些工作目录之类的内容
  • 配置完成后通过 redis-server redis-6379.conf 启动redis,可以通过redis-cli检查是否启动成功

Redis 基本数据类型

  • 新版本增加了若干新的数据类型,我暂时没有使用需求,没做过多研究,主要还是针对常用的5中数据结构

Strings

  • 这应该是Redis中使用最多最多的数据结构了,使用起来也很简单,直接set key value 进行赋值,get key进行取值
  • 常用的应用场景(好吧,我只是说一下我经常用的场景吧,在使用Token进行登录验证的时候,token存储于Redis中,使用的就是这种结构,设置好过期时间,定期刷新,可以理解为模拟Session吧)
  • 列举一些常用API
API 解释 使用示例
set 设置指定 key 的值 set key value
mset 同时设置一个或多个 key-value 对 mset key value [key1 value1 …]
get 获取指定 key 的值 get key
mget 获取所有(一个或多个)给定 key 的值 mget key1 [key2 …]
strlen 返回 key 所储存的字符串值的长度 strlen key
incr 将 key 中储存的数字值增一。 incr key
incrby 将 key 所储存的值加上给定的增量值(increment) incrby key increment
decr 将 key 中储存的数字值减一 decr key
decrby key 所储存的值减去给定的减量值(decrement) decrby key increment
append 如果 key 已经存在并且是一个字符串, APPEND 命令将指定的 value 追加到该 key 原来值(value)的末尾 append key value
getset 将给定 key 的值设为 value ,并返回 key 的旧值(old value) getset key value
expire 设置指定key的过期时间(time) expire key time

Hash

  • Hash结构可以认为是一个微型Redis(如果把Redis简单认为是Strings类型),换成Java语言来说,Hash结构就是 Map<String,Map<String,String>>
  • 应用场景。。。。Hmm。。项目中没有用到,不过觉得如果加入用户角色权限等信息。。。。是不是session可以用这个来处理呢?或者是application。。。。Hmm。。。暂时没有想法
  • 还是列举一些常用API
API 解释 使用示例
hget 获取存储在哈希表中指定字段的值。 HGET key field
hset 将哈希表 key 中的字段 field 的值设为 value 。 HSET key field value
hmget 获取所有给定字段的值 HMGET key field1 [field2]
hmset 同时将多个 field-value (域-值)对设置到哈希表 key 中。 HMSET key field1 value1 [field2 value2 ]
hgetall 获取在哈希表中指定 key 的所有字段和值 HGETALL key
hscan 迭代哈希表中的键值对。 HSCAN key cursor [MATCH pattern] [COUNT count] ``
hexist 查看哈希表 key 中,指定的字段是否存在。 HEXISTS key field
hdel 删除一个或多个哈希表字段 HDEL key field1 [field2]
hincrby 为哈希表 key 中的指定字段的整数值加上增量 increment 。 HINCRBY key field increment
hkeys 获取所有哈希表中的字段 HKEYS key
hlen 获取哈希表中字段的数量 HLEN key
hvals 获取哈希表中所有值 HVALS key

List

  • 列表虽然最近项目中没有使用,不过之前的项目中大规模使用,场景是。。。把list当做消息队列了。。
  • 应用场景。。。除了消息队列。。Hmm。。我也想不到什么了。。。如果有其他场景,烦请告诉我,谢谢。。
  • 老规矩,列举一些常用API
API 解释 使用示例
blpop 移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 BLPOP key1 [key2] timeout
brpop 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 BRPOP key1 [key2] timeout
brpoplpush 从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 BRPOPLPUSH source destination timeout
lindex 通过索引获取列表中的元素 LINDEX key index
linsert 在列表的元素前或者后插入元素 LINSERT key BEFORE\AFTER pivot value
llen 获取列表长度 LLEN key
lpop 移出并获取列表的第一个元素 LPOP key
lpush 将一个或多个值插入到列表头部 LPUSH key value1 [value2]
lpushx 将一个值插入到已存在的列表头部 LPUSHX key value
lrange 获取列表指定范围内的元素 LRANGE key start stop
lrem 移除列表元素 LREM key count value
lset 通过索引设置列表元素的值 LSET key index value
ltrim 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。 LTRIM key start stop
rpop 移除并获取列表最后一个元素 RPOP key
rpoplpush 移除列表的最后一个元素,并将该元素添加到另一个列表并返回 RPOPLPUSH source destination
rpush 在列表中添加一个或多个值 RPUSH key value1 [value2]
rpushx 为已存在的列表添加值 RPUSHX key value

Set

  • Set集合,就知道这个是一个集合,无序,不可以重复(Hmm和java中的Set很相似)
  • 应用场景。。。没想到。。。Hmm。。待补充
  • 常用API
API 解释 使用示例
sadd 向集合添加一个或多个成员 SADD key member1 [member2]
scard 获取集合的成员数 SCARD key
sdiff 返回给定所有集合的差集 SDIFF key1 [key2]
sdiffstore 返回给定所有集合的差集并存储在 destination 中 SDIFFSTORE destination key1 [key2]
sinter 返回给定所有集合的交集 SINTER key1 [key2]
sinterstore 返回给定所有集合的交集并存储在 destination 中 SINTERSTORE destination key1 [key2]
sismember 判断 member 元素是否是集合 key 的成员 SISMEMBER key member
smembers 返回集合中的所有成员 SMEMBERS key
smove 将 member 元素从 source 集合移动到 destination 集合 SMOVE source destination member
spop 移除并返回集合中的一个随机元素 SPOP key
srandmember 返回集合中一个或多个随机数 SRANDMEMBER key [count]
srem 移除集合中一个或多个成员 SREM key member1 [member2]
sunion 返回所有给定集合的并集 SUNION key1 [key2]
sunionstore 所有给定集合的并集存储在 destination 集合中 SUNIONSTORE destination key1 [key2]
sscan 迭代集合中的元素 SSCAN key cursor [MATCH pattern] [COUNT count]

Zset

  • Hmm Zset 也叫做Sorted Set 就是一个排序的集合,简单的说就是Set的有序版本(不过这个和Java的SortedSet不太一样。。),区别是什么呢,区别就是每个元素都有一个Score,排序的依据呢就是这个Score了。。
  • 应用场景,项目中倒是用到了,不过感觉用到并不是太对。。。所以不说了。老项目使用这个实现了一个排行榜,Hmm还是可以的,定期刷入到MySQL中持久化,也不怕数据丢失什么的。。。挺好
  • 说一下常用API吧
API 解释 使用示例
zadd 向有序集合添加一个或多个成员,或者更新已存在成员的分数 ZADD key score1 member1 [score2 member2]
zcard 获取有序集合的成员数 ZCARD key
zcount 计算在有序集合中指定区间分数的成员数 ZCOUNT key min max
zincrby 有序集合中对指定成员的分数加上增量 increment ZINCRBY key increment member
zinterstore 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中 ZINTERSTORE destination numkeys key [key …]
zlexcount 在有序集合中计算指定字典区间内成员数量 ZLEXCOUNT key min max
zrange 通过索引区间返回有序集合成指定区间内的成员 ZRANGE key start stop [WITHSCORES]
zrangebylex 通过字典区间返回有序集合的成员 ZRANGEBYLEX key min max [LIMIT offset count]
zrangebyscore 通过分数返回有序集合指定区间内的成员 ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT]
zrank 返回有序集合中指定成员的索引 ZRANK key member
zrem 移除有序集合中的一个或多个成员 ZREM key member [member …]
zremrangebylex 移除有序集合中给定的字典区间的所有成员 ZREMRANGEBYLEX key min max
zremrangebyrank 移除有序集合中给定的排名区间的所有成员 ZREMRANGEBYRANK key start stop
zremrangebyscore 移除有序集合中给定的分数区间的所有成员 ZREMRANGEBYSCORE key min max
zrevrange 返回有序集中指定区间内的成员,通过索引,分数从高到底 ZREVRANGE key start stop [WITHSCORES]
zrevrangebyscore 返回有序集中指定分数区间内的成员,分数从高到低排序 ZREVRANGEBYSCORE key max min [WITHSCORES]
zrevrank 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序 ZREVRANK key member
zscore 返回有序集中,成员的分数值 ZSCORE key member
zunionstore 计算给定的一个或多个有序集的并集,并存储在新的 key 中 ZUNIONSTORE destination numkeys key [key …]
zscan 迭代有序集合中的元素(包括元素成员和元素分值) ZSCAN key cursor [MATCH pattern] [COUNT count]

Redis 读写分离结构

  • 读写分离其实不是太复杂,简单来说就是多个Redis组成小”集群”,注意我这里的集群是带有引号的哈,这并不是一个真正意义上的集群,而是主从结构(Master&Slave),可以是一主多从,也可以是一主一从,甚至可以使只有一个Master(这个就退化成了。。。单机模式了。。)
  • 说一下怎么配置吧
    • 先参考 Redis 简易配置,并启动6379节点

    • 拷贝一份配置文件,将所有的6379替换为6380 (Hmm,我比较懒。。就单机先这么搞了。。)

    • 启动6380这个实例 redis-server redis-6380.conf

    • 查看是否都启动成功了,执行 ps -ef |grep redis-server|grep -v ‘grep’ 我这里显示如下,表示两个实例已经启动成功

      1
      2
      501 42485     1   0 12:29下午 ??         0:07.18 redis-server 127.0.0.1:6379
      501 43688 1 0 10:20下午 ?? 0:00.33 redis-server 127.0.0.1:6380
    • 执行 redis-cli -p 6380 info replication 看到6380实例目前是以Master角色运行

1
2
3
4
5
6
7
8
9
10
11
# Replication
role:master
connected_slaves:0
master_replid:13f6fcea2807ec7a78d52ecf76c382c0ba7d9c55
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
- 给6380分配角色slave,跟从Master 执行 redis-cli -p 6380  slaveof 127.0.0.1 6379
- 执行 redis-cli -p 6380 info replication 看到6380实例目前是以Slave角色运行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:8
master_sync_in_progress:0
slave_repl_offset:154
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:7a2c11e996810f76bdc72765130dcf47b5af4ab8
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:154
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:71
repl_backlog_histlen:84
- 这种是通过Redis Client来分配角色,还可以在配置文件中进行配置,修改redis-6380.conf如下,并重启:
1
2
3
4
5
6
7
8
9
bind 127.0.0.1
port 6380
daemonize yes
pidfile /Users/eviltuzki/Public/redis/redis_6380.pid
logfile "/Users/eviltuzki/Public/redis/6380.log"
databases 16
dbfilename dump.rdb
dir /Users/eviltuzki/Public/redis
slaveof 127.0.0.1 6379
  • 实际生产环境通常使用配置文件的方式配置主从结构
  • 完成了配置简单尝试一下:
    • 在Master set value -> redis-cli -p 6379 set hello world -> OK
    • 在Slave get value -> redis-cli -p 6380 get hello -> “world”
    • 在Slave set value -> redis-cli -p 6380 set test test -> (error) READONLY You can’t write against a read only slave.
  • 基本测试完成,主节点可读可写,从节点同步主节点,只能读取,不能写入,Hmm。。。如果要多加入几个Slave节点。。Copy一下配置文件就好了。。。

Redis HA 之 sentinel

说一下背景

  • Hmm 上文说道了集群,其实主从结构并不是一个可靠的集群,比如某天一大波僵尸来袭。。。跑题了,一大波流量来袭。。。Master挂了。。。然后。。。Hmm。。。没有节点可以写入了,咋办呢?
  • 解决方法也不是太复杂,举个场景:3台机器,1Master 2Slave,然后某天。。。Master突然挂了。。剩下2个Slave,这个时候咋办?切换一下,让其中一个Slave变成Master,另外一个跟随这个新的Master,这样就1主1从1挂机(鄙视挂机党。。。)。好赖可以正常提供服务了,等挂机服务器启动起来了,将它设置为新Master的Slave节点,这样就完成了Master Slave的转换了,然后就可以正常提供服务了。
  • 听起来上面的方案还不错,其实服务端执行起来也不太复杂。如下:
    • Master挂了,剩下2个Slave,记为Slave1 Slave2
    • 对Slave 1 执行 slaveof no one,将Slave 1 升级为新Master
    • 对Slave 2 执行 slaveof Slave1,将Slave 2设置跟从新的Master
    • 等原Master启动,执行slaveof Slave1,将原Master设置为Slave并且跟从新的Master
  • 为啥说服务端简单呢?Client连接服务器也得跟着切换啊。。Client写入只能写入到Master节点,服务端经过这么一折腾,Client也要跟着切换IP,才能正常访问。
  • 所以呢,官方提供了sentinel 一种HA方案,服务端的切换可以自动执行,sentinel 节点负责监控Master Slave状态,如果切换了,同时通知Client进行切换,达到可服务状态。

怎么配置?

  • 首先要额外准备机器作为sentinel节点,我这里偷懒,继续单机运行。。。(Hmm,穷人。。没有太多机器。。也不想搞虚拟机)

  • 先启动一个Maste 6379,2个Slave 6380 8381,执行ps -ef |grep redis|grep -v grep 如下:

    1
    2
    3
    501 42485     1   0 12:29下午 ??         0:10.87 redis-server 127.0.0.1:6379
    501 43910 1 0 10:47下午 ?? 0:02.45 redis-server 127.0.0.1:6380
    501 44117 1 0 11:17下午 ?? 0:00.53 redis-server 127.0.0.1:6381
  • 查看Master状态 redis-cli -p 6379 info replication

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # Replication
    role:master
    connected_slaves:2
    slave0:ip=127.0.0.1,port=6380,state=online,offset=3796,lag=0
    slave1:ip=127.0.0.1,port=6381,state=online,offset=3796,lag=0
    master_replid:7a2c11e996810f76bdc72765130dcf47b5af4ab8
    master_replid2:0000000000000000000000000000000000000000
    master_repl_offset:3796
    second_repl_offset:-1
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:1
    repl_backlog_histlen:3796
  • 全部启动成功,然后开始配置sentinel节点

  • 从Redis解压文件中可以看到一个sentinel.conf文件,Hmm。。。懒人。。直接Copy这个开始改造,sentinel-26379.conf 如下:

    1
    2
    3
    4
    5
    6
    7
    8
    port 26379
    dir /Users/eviltuzki/Public/redis/
    sentinel monitor mymaster 127.0.0.1 6379 2 # 监控mymaster集群,Master地址为127.0.0.1 6379,当2个sentinel认为Master有问题,则进行Master转换
    sentinel down-after-milliseconds mymaster 30000 #下线Master时间30s
    sentinel parallel-syncs mymaster 1
    sentinel failover-timeout mymaster 180000
    sentinel deny-scripts-reconfig yes
    daemonize yes #守护进程方式启动
  • 生成对应的3份,分别是sentinel-26379.conf、sentinel-26380.conf、sentinel-26381.conf,然后通过redis-sentinel sentinel-263xx.conf启动sentinel节点

  • 查看进程,是否启动成功:ps -ef |grep sent|grep -v grep

    1
    2
    3
    501 44288     1   0 11:36下午 ??         0:00.64 redis-sentinel *:26379 [sentinel]
    501 44291 1 0 11:36下午 ?? 0:00.61 redis-sentinel *:26380 [sentinel]
    501 44293 1 0 11:36下午 ?? 0:00.63 redis-sentinel *:26381 [sentinel]
  • 查看redis-sentinel状态:redis-cli -p 26379 info sentinel

    1
    2
    3
    4
    5
    6
    7
    # 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=127.0.0.1:6379,slaves=2,sentinels=3
  • 可以看到master0状态OK,2个Slave,3个sentinels,一切正常。接下来就可以使用对应的Client进行连接了。

  • Hmm 这块内容有点太多了。。。后面单开Java Client连接。。

  • 接下来模拟一下事故吧:

    • 查看一下刚刚配置的sentinel-26379.conf文件,多了一些内容:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      port 26379
      dir "/Users/zhaojian/Public/redis"
      sentinel myid bca8111060bbda4a42ec3744391d1f40ca1fda00
      sentinel deny-scripts-reconfig yes
      sentinel monitor mymaster 127.0.0.1 6379 2
      sentinel config-epoch mymaster 0
      sentinel leader-epoch mymaster 0
      # Generated by CONFIG REWRITE
      sentinel known-slave mymaster 127.0.0.1 6381
      sentinel known-slave mymaster 127.0.0.1 6380
      sentinel known-sentinel mymaster 127.0.0.1 26380 ba913a9c10e46fd4df76bf0289721136031926ef
      daemonize yes
      sentinel known-sentinel mymaster 127.0.0.1 26381 7c387d9b2e95ac2338655fb8f5011f277635dade
      sentinel current-epoch 0
    • 主节点和从节点信息都能看到,现在我准备下线Master节点,看看会有什么反应(Hmm怎么下线呢?直接kill掉吧)

    • 等待一小会儿,Hmm,大概30S左右吧,再次查看sentinel-26379.conf文件,发现有些变化了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
port 26379
dir "/Users/zhaojian/Public/redis"
sentinel myid bca8111060bbda4a42ec3744391d1f40ca1fda00
sentinel deny-scripts-reconfig yes
sentinel monitor mymaster 127.0.0.1 6380 2
sentinel config-epoch mymaster 1
sentinel leader-epoch mymaster 1
# Generated by CONFIG REWRITE
sentinel known-slave mymaster 127.0.0.1 6379
sentinel known-slave mymaster 127.0.0.1 6381
sentinel known-sentinel mymaster 127.0.0.1 26380 ba913a9c10e46fd4df76bf0289721136031926ef
daemonize yes
sentinel known-sentinel mymaster 127.0.0.1 26381 7c387d9b2e95ac2338655fb8f5011f277635dade
sentinel current-epoch 1
- Hmm,首先Master已经切换了,不再是6379了,而是6380,而6379变成了known-slave,也就是Slave节点,无妨。。。反正现在也不工作。。。
- 那我现在恢复一下6379节点(重新执行redis-server redis-6379.conf),注意,这里的配置6379可是Master哦~
- 执行 redis-cli -p 6379 info replication ,信息如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:162525
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:a6939796e0faba3555a74719ec18498e7b247756
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:162525
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:155146
repl_backlog_histlen:7380
- Hmm,说明sentinel还是蛮智能的,尽管6379之前是Master,但是选举出新的Master之后,旧的Master会被 降级到Slave节点,避免出现多个Master。
- 附带看一下6381和6380的日志:
- 首先是6380的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
43910:S 06 Oct 23:45:51.903 * MASTER <-> SLAVE sync started
43910:S 06 Oct 23:45:51.904 # Error condition on socket for SYNC: Connection refused
43910:S 06 Oct 23:45:52.914 * Connecting to MASTER 127.0.0.1:6379

...
43910:S 06 Oct 23:46:21.205 * MASTER <-> SLAVE sync started
43910:S 06 Oct 23:46:21.206 # Error condition on socket for SYNC: Connection refused
43910:M 06 Oct 23:46:21.960 # Setting secondary replication ID to 7a2c11e996810f76bdc72765130dcf47b5af4ab8, valid up to offset: 111989. New replication ID is a6939796e0faba3555a74719ec18498e7b247756
43910:M 06 Oct 23:46:21.960 * Discarding previously cached master state.
43910:M 06 Oct 23:46:21.962 * MASTER MODE enabled (user request from 'id=13 addr=127.0.0.1:51348 fd=12 name=sentinel-7c387d9b-cmd age=568 idle=0 flags=x db=0 sub=0 psub=0 multi=3 qbuf=0 qbuf-free=32768 obl=36 oll=0 omem=0 events=r cmd=exec')
43910:M 06 Oct 23:46:21.963 # CONFIG REWRITE executed with success.
43910:M 06 Oct 23:46:23.354 * Slave 127.0.0.1:6381 asks for synchronization
43910:M 06 Oct 23:46:23.354 * Partial resynchronization request from 127.0.0.1:6381 accepted. Sending 422 bytes of backlog starting from offset 111989.
43910:M 06 Oct 23:49:59.772 * Slave 127.0.0.1:6379 asks for synchronization
43910:M 06 Oct 23:49:59.772 * Partial resynchronization not accepted: Replication ID mismatch (Slave asked for '4a931cc983685e6f1b029225185120eee25f03b4', my replication IDs are 'a6939796e0faba3555a74719ec18498e7b247756' and '7a2c11e996810f76bdc72765130dcf47b5af4ab8')
43910:M 06 Oct 23:49:59.773 * Starting BGSAVE for SYNC with target: disk
43910:M 06 Oct 23:49:59.773 * Background saving started by pid 44404
44404:C 06 Oct 23:49:59.775 * DB saved on disk
43910:M 06 Oct 23:49:59.855 * Background saving terminated with success
43910:M 06 Oct 23:49:59.856 * Synchronization with slave 127.0.0.1:6379 succeeded
- 然后看一下6381的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
44117:S 06 Oct 23:46:22.338 * Connecting to MASTER 127.0.0.1:6379
44117:S 06 Oct 23:46:22.339 * MASTER <-> SLAVE sync started
44117:S 06 Oct 23:46:22.340 # Error condition on socket for SYNC: Connection refused
44117:S 06 Oct 23:46:22.866 * SLAVE OF 127.0.0.1:6380 enabled (user request from 'id=11 addr=127.0.0.1:51346 fd=12 name=sentinel-7c387d9b-cmd age=569 idle=0 flags=x db=0 sub=0 psub=0 multi=3 qbuf=133 qbuf-free=32635 obl=36 oll=0 omem=0 events=r cmd=exec')
44117:S 06 Oct 23:46:22.867 # CONFIG REWRITE executed with success.
44117:S 06 Oct 23:46:23.351 * Connecting to MASTER 127.0.0.1:6380
44117:S 06 Oct 23:46:23.351 * MASTER <-> SLAVE sync started
44117:S 06 Oct 23:46:23.352 * Non blocking connect for SYNC fired the event.
44117:S 06 Oct 23:46:23.353 * Master replied to PING, replication can continue...
44117:S 06 Oct 23:46:23.353 * Trying a partial resynchronization (request 7a2c11e996810f76bdc72765130dcf47b5af4ab8:111989).
44117:S 06 Oct 23:46:23.354 * Successful partial resynchronization with master.
44117:S 06 Oct 23:46:23.355 # Master replication ID changed to a6939796e0faba3555a74719ec18498e7b247756
44117:S 06 Oct 23:46:23.355 * MASTER <-> SLAVE sync: Master accepted a Partial Resynchronization.
- 额,刚想起来6379重启后的日志也看一下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
42485:M 06 Oct 23:45:51.599 # User requested shutdown...
42485:M 06 Oct 23:45:51.600 * Saving the final RDB snapshot before exiting.
42485:M 06 Oct 23:45:51.601 * DB saved on disk
42485:M 06 Oct 23:45:51.601 * Removing the pid file.
42485:M 06 Oct 23:45:51.602 # Redis is now ready to exit, bye bye...
44398:C 06 Oct 23:49:48.652 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
44398:C 06 Oct 23:49:48.653 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=44398, just started
44398:C 06 Oct 23:49:48.654 # Configuration loaded
44399:M 06 Oct 23:49:48.656 * Increased maximum number of open files to 10032 (it was originally set to 4864).
44399:M 06 Oct 23:49:48.657 * Running mode=standalone, port=6379.
44399:M 06 Oct 23:49:48.657 # Server initialized
44399:M 06 Oct 23:49:48.657 * DB loaded from disk: 0.000 seconds
44399:M 06 Oct 23:49:48.658 * Ready to accept connections
44399:S 06 Oct 23:49:58.958 * Before turning into a slave, using my master parameters to synthesize a cached master: I may be able to synchronize with the new master with just a partial transfer.
44399:S 06 Oct 23:49:58.958 * SLAVE OF 127.0.0.1:6380 enabled (user request from 'id=3 addr=127.0.0.1:52967 fd=7 name=sentinel-ba913a9c-cmd age=10 idle=0 flags=x db=0 sub=0 psub=0 multi=3 qbuf=0 qbuf-free=32768 obl=36 oll=0 omem=0 events=r cmd=exec')
44399:S 06 Oct 23:49:58.960 # CONFIG REWRITE executed with success.
44399:S 06 Oct 23:49:59.769 * Connecting to MASTER 127.0.0.1:6380
44399:S 06 Oct 23:49:59.769 * MASTER <-> SLAVE sync started
44399:S 06 Oct 23:49:59.770 * Non blocking connect for SYNC fired the event.
44399:S 06 Oct 23:49:59.771 * Master replied to PING, replication can continue...
44399:S 06 Oct 23:49:59.771 * Trying a partial resynchronization (request 4a931cc983685e6f1b029225185120eee25f03b4:1).
44399:S 06 Oct 23:49:59.774 * Full resync from master: a6939796e0faba3555a74719ec18498e7b247756:155145
44399:S 06 Oct 23:49:59.774 * Discarding previously cached master state.
44399:S 06 Oct 23:49:59.856 * MASTER <-> SLAVE sync: receiving 202 bytes from master
44399:S 06 Oct 23:49:59.857 * MASTER <-> SLAVE sync: Flushing old data
44399:S 06 Oct 23:49:59.857 * MASTER <-> SLAVE sync: Loading DB in memory
44399:S 06 Oct 23:49:59.858 * MASTER <-> SLAVE sync: Finished with success
- 从日志中可以看到,6379下线以后,6380和6381经历了一段时间(约30s)的找不到Master,之后6380收到了sentinel-7c387d9b-cmd发送的请求,转换角色为Master。6381收到sentinel-7c387d9b-cmd发送的请求,变更为跟随6380而不是6379。等6379重新启动后收到了sentinel-ba913a9c-cmd的请求,降级为Slave并且跟随6380。
  • 补充说明一下sentinel一定要集群部署,不能单点!否则网络等因素会导致集群来回切换角色,另外sentinel本身单点也有风险!

Redis HA 之 Clusterv