一站式学习Redis 从入门到高可用分布式实践

1:redis 是用c语言来实现的,速度快 持久化 单线程 复杂的数据类型有bitmap和hyperloglog和geo地理信息
2:高可用、分布式
v2.8开始支持Redis-Sentinel(哨兵)高可用
v3.0开始支持Redis-Cluster 分布式
3:典型应用场景
缓存系统
计数器(如微博评论数,转发数以及点赞数)
消息队列
排行榜(sortset)
社交网络(set并集交集差集)
实时系统

4:可执行文件说明

redis-server Redis服务器
redis-cli Redis命令行客户端
redis-benchmark Redis性能测试
redis-check-aof AOF文件修复工具
redis-check-dump RDB文件修复工具
redis-sentinel Sentinel服务器(2.8以后)
5:三种启动方式
最简单启动 redis-server
判断是否启动成功
ps -ef|grep redis
netstat -antpl|grep redis
redis-cli -h ip -p port ping

动态参数启动
redis-server --port 6380 (默认6379)

配置文件启动
redis-server configPath

生产环境选择配置启动
单机多实例配置文件开源用端口号区分开
6:简单的客户端链接:
redis-cli -h 10.10.79.150 -p 6384
ping
set hello world
get hello
7:Redis Ping 命令使用客户端向 Redis 服务器发送一个 PING ,如果服务器运作正常的话,会返回一个 PONG 。
通常用于测试与服务器的连接是否仍然生效,或者用于测量延迟值。
# 客户端和服务器连接正常
redis 127.0.0.1:6379> PING
PONG
# 客户端和服务器连接不正常(网络不正常或服务器未能正常运行)
redis 127.0.0.1:6379> PING
Could not connect to Redis at 127.0.0.1:6379: Connection refused
8:Redis常用配置
deamonize 是否是守护进程默认no建议yes
prot redis对外端口号
logfile redis系统日志
dir redis工作目录
9:慢查询  找到系统中瓶颈的命令
客户端请求的生命周期


两点说明:
1.慢查询发生在第三阶段
2.客户端超时不一定慢查询,但慢查询是客户端超时的一个可能因素
10:edis的slowlog是redis用于记录记录慢查询执行时间的日志系统。由于slowlog只保存在内存中,
因此slowlog的效率很高,完全不用担心会影响到redis的性能。
Slowlog是Redis从2.2.12版本引入的一条命令。
在redis.conf中有关于slowlog的设置:
1slowlog-log-slower-than 10000
2slowlog-max-len 128
其中slowlog-log-slower-than表示slowlog的划定界限,只有query执行时间大于slowlog-log-slower-than的才会定义成慢查询,才会被slowlog进行记录。slowlog-log-slower-than设置的单位是微妙,默认是10000微妙,也就是10ms
slowlog-max-len表示慢查询最大的条数,当slowlog超过设定的最大值后,会将最早的slowlog删除,是个FIFO队列
10:慢查询命令
slowlog get [n] 获取慢查询队列
slowlog len 获取慢查询队列长度 队列里面有多少慢查询
slowlog reset 清空慢查询队列
11:
  • pipeline  提高客户端的效率

     流水线

 

          减少网络时间的消耗

与原生M(mget,mset等)操作对比

M操作是原子操作

pipeline命令是非原子的,Redis服务器会对其命令集进行拆分。

  • 发布订阅   redis的发布订阅功能

 角色:发布者 订阅者 频道  订阅者可以订阅多频道(右图)

 

 

消息队列 要抢      Redis不仅可作为缓存服务器,还可用作消息队列。它的列表类型天生支持用作消息队列

发布订阅  都有

  • Bitmap  减少内存的方案
  • bitmap位图的概念

  • 其实类型也是字符串
  •  

    首先来看一个例子,字符串big,

    字母b的ASCII码为98,转换成二进制为 01100010
    字母i的ASCII码为105,转换成二进制为 01101001
    字母g的ASCII码为103,转换成二进制为 01100111

    如果在Redis中,设置一个key,其值为big,此时可以get到big这个值,也可以获取到 big的ASCII码每一个位对应的值,也就是0或1

    例如:

    127.0.0.1:6379> set hello big
    OK
    127.0.0.1:6379> getbit hello 0      # b的二进制形式的第1位,即为0
    (integer) 0
    127.0.0.1:6379> getbit hello 1      # b的二进制形式的第2位,即为1
    (integer) 1

    big长度为3个字节,对应的长度为24位,使用getbit命令可以获取到big对应的位的对应的值

setbit   getbit  bitcount

  1. 若只有10万独立用户
数据类型每个userId占用空间需要存储的用户量内存使用总量
set 32位(假设userId用的是整型) 100,000 32位*100,000=4MB
Bitmap 1位 100,000,000 1位*100,000,000=12.5MB

Java连接远程的redis时,连接被拒绝。

Exception in thread "main" redis.clients.jedis.exceptions.JedisConnectionException: java.net.ConnectException: Connection refused: connect
at redis.clients.jedis.Connection.connect(Connection.java:154)
at redis.clients.jedis.BinaryClient.connect(BinaryClient.java:83)
at redis.clients.jedis.Connection.sendCommand(Connection.java:93)
at redis.clients.jedis.BinaryClient.set(BinaryClient.java:100)
at redis.clients.jedis.Client.set(Client.java:29)
at redis.clients.jedis.Jedis.set(Jedis.java:65)
at redis.Demo1.main(Demo1.java:10)
Caused by: java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at redis.clients.jedis.Connection.connect(Connection.java:148)
... 6 more

可能的原因:

redis服务器的redis.conf配置中bind 127.0.0.1

应该改为:bind 0.0.0.0

  • HyperLogLog  极端的减少内存的方案/数据结构(算法)

本质还是字符串

  • GEO 地理信息

            3.2版本添加的新特性 用来计算地理位置相关  其实zset类型实现

 

11:通用命令       

                mset /mget      批量设置  减少了网络时间   一般而言=网络时间+命令时间

                sadd myset a b c d e   将一个或多个成员元素加入到集合中

                keys *      生产不适用  热备从节点  scan

                dbsize      计算key的总数

                exists  key   检查key是否存在

                expire key seconds  key在seconds秒后过期

                ttl key  查看key剩余的过期时间

                persist  key  去掉key的过期时间

                 type  key     返回key的类型

时间复杂度都是o(1)
12:

13:

单线程架构

        单线程为什么这么块?

                 1.纯内存

                 2.非阻塞IO

                 3.避免现场切换和竟态消耗

14:字符串string操作

字符串类型

 incr  key                 #自增1

decr key                  #自减1

incrby key k             #自增k   

decrby key k            #自减k

set key value           #不管key是否存在,都设置

setnx key value        #key不存在,才设置

set key value xx       #key存在,才设置

getset  key newvalue  #set key newvalue并返回旧的value

append key value       #将value追加到旧的value

strlen  key                   #返回字符串的长度

incrbyfloat key 3.5       #增加key对应的值3.5

getrange key start  end  #获取字符串指定下标的所有值

setrange key index value #设置指定下标所对应的值

get key 获取key
set key 设置key
del key 删除key
以上命令时间复杂度都为o(1)
mget key1 key2 key3 时间复杂度o(n) 原子操作节约网络开销时间 pipline 不是原子操作
mset key1 value1 key2 value2 时间复杂度o(n)

15:hash 操作

以h开头:

hget key field 获取key中field
hset key field 设置key field
hdel key field 删除key field
hexist key field 判断是否存在field
hlen key 获取所有field 数量
HSETNX key field value
只有在字段 field 不存在时,设置哈希表字段的值。
HINCRBY key field increment
为哈希表 key 中的指定字段的整数值加上增量 increment 。
6 HINCRBYFLOAT key field increment
为哈希表 key 中的指定字段的浮点数值加上增量 increment 。


以上命令时间复杂度都为o(1)
hmget key field1 field2 时间复杂度o(n) 原子操作节约网络开销时间 pipline 不是原子操作
hmset key field1 value1 field2 value2 时间复杂度o(n)
hgetall key 返回hash中所有的filed和value时间复杂度o(n)
hvals key 返回所有hash中的value时间复杂度o(n)
hkeys key 返回所有hash中的key时间复杂度o(n)
不能设置field的过期时间
17:jredis 使用

18:直连

19:连接池

20:对比

 21:代码

public JedisPool JedisPoolFactory() {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxIdle(redisConfig.getPoolMaxIdle());
poolConfig.setMaxTotal(redisConfig.getPoolMaxTotal());
poolConfig.setMaxWaitMillis(redisConfig.getPoolMaxWait() * 1000);
JedisPool jp = new JedisPool(poolConfig, redisConfig.getHost(), redisConfig.getPort(),
redisConfig.getTimeout()*1000, redisConfig.getPassword(), 0);
return jp;
}

/**
* 获取当个对象
* */
public <T> T get(KeyPrefix prefix, String key, Class<T> clazz) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//生成真正的key
String realKey = prefix.getPrefix() + key;
String str = jedis.get(realKey);

T t = stringToBean(str, clazz);
return t;
}finally {
returnToPool(jedis);
}
}

private void returnToPool(Jedis jedis) {
if(jedis != null) {
jedis.close();
}
}

 22:持久化方式

快照RDM方案
触发方式有三种
save命令(会阻塞redis),会首先生成一个临时文件当生成以后替换老的文件 时间复杂度o(n)
bgsave命令
配置自动触发(通过bgsave实现)
日志AOF方案

 23:

24:redis 配置

redis配置文件中可以设置/opt/moudels/redis/config

save 900 1                  #900s内改变1次就生成RDB  实际生产环境去掉自动触发rdm机制

save 300 10

save 60 10000

dbfilename dump.rdb   #设置rdb的名称

dir ./                              #rdb文件的位置

stop-writes-on-bgsave-error  yes 默认配置 stop-writes-on-bgsave-error yes当bgsave出错时数据将不能修改

rdbcompression  yes

rdbchecksum      yes

 25

:

26:触发rdb机制---不容忽略方式

1.全量复制         主从复制

2.debug reload   debug机制

3.shutdown         

27:
修改redis.conf中daemonize为yes,确保守护进程开启,也就是在后台可以运行.
# 默认情况下 redis 不是作为守护进程运行的,如果你想让它在后台运行,你就把它改成 yes。
# 当redis作为守护进程运行的时候,它会写一个 pid 到 /var/run/redis.pid 文件里面。
daemonize no

# 当redis作为守护进程运行的时候,它会把 pid 默认写到 /var/run/redis.pid 文件里面,
# 但是你可以在这里自己制定它的文件位置。
pidfile /var/run/redis.pid

# 指定日志文件的位置
logfile ""

28:RDB方式缺点: 耗时耗性能,容易丢失数据,时间复杂度o(n) fork消耗内存,io磁盘性能

AOF:就是把执行的redis命令写到AOF文件中,然后恢复的时候直接在redis中执行AOF中的命令
AOF三种策略:always everysec no
 



29:
AOF重写是把原有的AOF文件进行重构合并命令是文件更小
作用:减少磁盘占用量
加速恢复速度

AOF重写实现两种方式
bgrwriteof命令
AOF重写配置

 

 30:RDB和AOF的决择

 31:AOF重写流程

32:Redis开发运维常见问题

fork操作

             1.同步操作

              2.与内存量息息相关:内存越大,耗时越长(与机器类型有关)

              3.info:latest_fork_usec

  • 进程外开销

33:redis的no-appendfsync-on-rewrite参数

同时在执行bgrewriteaof操作和主进程写aof文件的操作,两者都会操作磁盘,而bgrewriteaof往往会涉及大量磁盘操作,这样就会造成主进程在写aof文件的时候出现阻塞的情形,现在no-appendfsync-on-rewrite参数出场了。如果该参数设置为no,是最安全的方式,不会丢失数据,但是要忍受阻塞的问题。如果设置为yes呢?这就相当于将appendfsync设置为no,这说明并没有执行磁盘操作,只是写入了缓冲区,因此这样并不会造成阻塞(因为没有竞争磁盘),但是如果这个时候redis挂掉,就会丢失数据。丢失多少数据呢?在linux的操作系统的默认设置下,最多会丢失30s的数据。

因此,如果应用系统无法忍受延迟,而可以容忍少量的数据丢失,则设置为yes。如果应用系统无法忍受数据丢失,则设置为no。
34:AOF追加阻塞

这里写图片描述
配置appenedfsync everysec后 
当执行set命令的时候,先进入1步骤,然后检查后台是否有同步线程,如果没有则,主线程继续执行。如果有同步线程,那么判断上次同步时间和现在时间,如果大于2秒,表示上个同步线程还没有执行完,而且时间已经大于2秒,这个时侯主线程就阻塞,一直等待同步线程的完成。如果小于2秒,运行主线程继续执行,如果不发生阻塞的话就实现2s同步一次。 
所以虽然设置了everysec,可能丢失2秒数据。

查看阻塞情况 
这里写图片描述
其中aof_delayed_fsync 就是阻塞次数

35:主从复制的配置 两种实现方式

    slaveof命令    slaveof   127.0.0.1 6379  无需重启
如果想断掉的话使用命令 slaveof no one 断掉主从不会删掉数据,但是再找新的主时候会被清空
配置文件配置
slaveof 192.168.0.100 6379 (映射到主服务器上) 需要重新启动
Slave-read-only yes

可以通过 info replication来查看当前的角色  info server来查看runid 每次重启都会生成新的runid 都会进行一次全量复制
36:全量复制和部分复制

全量复制流程
如果从服务器以前没有复制过任何主服务器,或者之前执行过SLAVEOF no one命令,那么从服务器在开始一次新的复制时将向主服务器发送PSYNC ? -1命令,主动请求主服务器进行完整重同步(因为这时不可能执行部分重同步);
相反地,如果从服务器已经复制过某个主服务器,那么从服务器在开始一次新的复制时将向主服务器发送PSYNC <runid> <offset>命令:其中runid是上一次复制的主服务器的运行ID,而offset则是从服务器当前的复制偏移量,接收到这个命令的主服务器会通过这两个参数来判断应该对从服务器执行哪种同步操作,如何判断已经在介绍runid时进行详细说明。
根据情况,接收到PSYNC命令的主服务器会向从服务器返回以下三种回复的其中一种:

如果主服务器返回+FULLRESYNC <runid> <offset>回复(runid变化或者offset不在缓冲区队列范围之内),那么表示主服务器将与从服务器执行完整重同步操作:其中runid是这个主服务器的运行ID,从服务器会将这个ID保存起来,在下一次发送PSYNC命令时使用;而offset则是主服务器当前的复制偏移量,从服务器会将这个值作为自己的初始化偏移量;
如果主服务器返回+CONTINUE回复(runid没有变化且offset在缓冲区队列范围之内),那么表示主服务器将与从服务器执行部分同步操作,从服务器只要等着主服务器将自己缺少的那部分数据发送过来就可以了;
如果主服务器返回-ERR回复,那么表示主服务器的版本低于Redis 2.8,它识别不了PSYNC命令,从服务器将向主服务器发送SYNC命令,并与主服务器执行完整同步操作。
  
  由此可见psync也有不足之处,当从库重启以后runid发生变化,也就意味者从库还是会进行全量复制,而在实际的生产中进行从库的维护很多时候会进行重启,而正是有由于全量同步需要主库执行快照,以及数据传输会带不小的影响。因此在4.0版本,psync命令做了改进,以下说明。

全量复制开销~
  • bgsave时间
  • rdb文件传输时间
  • 从节点清空时间
  • 从节点加载rdb
  • 可能的AOF重写,加载rdb完成后,如果开启了aof重写,需要重写aof

36:run_id 和复制偏移量和复制积压缓冲区

run_id 是redis每次启动时生成的随机的ID,用于标识该节点,重启会生成新的run_id,可以在redis-cli中执行 info命令查看

偏移量 用于主从同步、从节点上报从节点偏移量、master_repl_offset
主库和从库分别各自维护一个复制偏移量(可以使用info replication查看)用于标识自己复制的情况,在主库中代表主节点向从节点传递的字节数,在从库中代表从库同步的字节数。每当主库向从节点发送N个字节数据时,主节点的offset增加N,从库每收到主节点传来的N个字节数据时,从库的offset增加N。因此offset总是不断增大,这也是判断主从数据是否同步的标志,若主从的offset相同则表示数据同步量,不通则表示数据不同步
replication backlog buffer(复制积压缓冲区):复制积压缓冲区是一个固定长度的FIFO队列,大小由配置参数repl-backlog-size指定,默认大小1MB。需要注意的是该缓冲区由master维护并且有且只有一个,所有slave共享此缓冲区,其作用在于备份最近主库发送给从库的数据。在主从命令传播阶段,主节点除了将写命令发送给从节点外,还会发送一份到复制积压缓冲区,作为写命令的备份。除了存储最近的写命令,复制积压缓冲区中还存储了每个字节相应的复制偏移量(如下图),由于复制积压缓冲区固定大小先进先出的队列,所以它总是保存的是最近redis执行的命令。
37:部分复制是2.8以后出现的

部分复制
  • 如果网络发生抖动,2.8之前会重新生产rdb文件,然后重新执行
  • 之后,提供部分复制功能、如果抖动,master会在复制缓冲区生成一个buffer(默认1M),如果offset在buffer范围内,则会将部分数据复制到slave,而不需要全量复制

38:

 2.主从配置不一致

            例如maxmemory不一致:丢失数据 

            例如数据结构优化参数(hash-max-ziplist-entries):内存不一致

 3.规避全量复制

           3.1   第一次全量复制,不可避免     小主节点 、低峰

           3.2    节点运行ID不匹配  主节点重启(运行ID变化)

                   故障转移,例如哨兵或集群(sentinals和Redis Cluster)

           3.3   复制积压缓冲区不足

                  网络中断,部分复制无法满足

                  增大复制缓冲区配置rel_backlog_size 默认1m,网络“增强”。#10m

 4.规避复制风暴

             4.1   单主节点复制风暴

                     问题:主节点重启,多从节点复制

                     解决:更换复制拓扑

             4.2   单机器复制风暴

        主节点分散多机器

  • 单机器复制风暴(redis<4.0当master宕机重启,会导致该机器下所有slave同时产生复制。避免单机部署一套redis主从)====》主节点分散多台机

 1.读写分离  #读流量分摊到从节点,MySQL也是读写分离

            可能遇到的问题:

            复制数据延迟

            读到过期数据

            从节点故障  

39:redis sentinel 

故障转移

配置多套监控

40:安装配置流程

sentinal的默认端口26379,形成如下的安装配置(其实就是单机多实例)

sentinel节点主要配置

  info replicaton  

会显示主从相关配置信息
ps- ef | grep redis-server |grep 700

redis sentinel redis-sentinel.conf

sentinel 不能存储数据


客户端实现基本原理-1

客户端实现基本原理-2

客户端实现基本原理-3

客户端实现基本原理-4 验证

客户端实现基本原理-4 通知(发布订阅))

 
41:连接代码
public static void main(String[] args) {
Set<String> IPS = new HashSet<String>();
IPS.add("192.168.136.158:26379");
JedisSentinelPool pool = new JedisSentinelPool("mymaster", IPS);
Jedis jedis=null;
try{
jedis = pool.getResource();
jedis.set("foo", "bar");
System.out.println(jedis.get("foo"));
} catch(Exception e){
e.printStackTrace();
// logger.error(e.getMessage(),e);
} finally {
if(jedis != null)
jedis.close();
}

42:.Redis Sentinel实现原理

5.1 Redis Sentinel内部的三个定时任务

Redis Sentinel内部有三个定时任务来对redid节点进行故障判断和转移

  • 1.每10秒每个sentinel对master和slave执行info命令,以发现slave节点和确认主从关系

sentinel在master节点执行info replication命令,从命令执行结果中解析出slave节点

img_811ed033f0f986aa8abbd56923e585fe.png

  • 2.每2秒每个sentinel通过master节点的channel交换信息(发布订阅)

master节点上有一个发布订阅的channel频道:__sentinel__:hello,用于所有sentinel之间进行信息交换

一个sentinel发布消息,消息包含当前sentinel节点的信息,对其他sentinel节点的判断以及当前sentinel对master节点和slave节点的一些判断

其他sentinel都可以接收到这条消息

新加入sentinel节点时,sentinel节点之间可以相互感知,以达到信息交互的功能

img_8d9e65bcb4ec8ca2350a0314b98497d7.png

  • 3.每1秒每个sentinel对其他sentinel节点和Redis节点执行ping操作

每个sentinel都可以知道其他sentinel节点,当监控的master发生故障时,方便进行判断和新master的挑选,这个定时任务是master进行故障判定的依据

img_881b4c443e47e9e806c93cfe1d3e2e02.png

5.2 主观下线和客观下线

主观下线:每个sentinel节点对Redis节点失败的'偏见'

在redis-sentinel配置文件中,有下面这种配置

sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel down-after-milliseconds <master-name> <timeout>

一个sentinel集合可以同时监控多个master,slave的节点

sentinel对多个master,slave节点进行区分的标识就是master-name,ip和port是master节点的IP地址和端口,quorum是master客观下线之后sentinel进行判断的节点数

sentinel对master进行主观下线判断的时间,单们为毫秒

每个sentinel每秒对master和slave执行ping操作,当sentinel对master或slave在timeout定义的毫秒时间内没有回复,则sentinel会认为这个节点已经被主观下线了

在前面的例子中对sentinel的配置是

sentinel monitor mymaster 192.168.81.100 6379 2
sentinel down-after-milliseconds mymaster 30000
    

解释:

sentinel集合监控名为mymaster的master,slave节点
被监控的master节点的IP地址是192.168.81.100,端口为6379,
sentinel会在`__sentinel__:hello`频道中交流对master节点的看法,如果sentinel节点都对master节点ping失败'达成共识',sentinel个数超过quorum的个数,sentinel集合则会认为master节点客观下线
当两个sentinel对master节点执行ping操作,在30000毫秒(30秒)时间内没有得到回复,则认为节点已经被主观下线

quorum建议设置为:(sentinel节点数 / 2) + 1,可以根据应用场景进行设定

43: sentinel领导者选举

要点:

只需要一个sentinel节点就可以完成故障转移
通过`sentinel is-master-down-by-addr`命令来完成sentinel交换对master节点的失败判定和新master的选举

完成sentinel领导者选举步骤:

1.每个做主观下线的sentinel节点向其他sentinel节点发送命令,要求将自己设置为领导者
2.收到命令的sentinel节点如果没有同意同意其他sentinel节点发送的命令,那么将同意该请求,否则拒绝
3.如果该sentinel节点发现自己的票数已经超过sentinel集合半数且超过quorum,将成为领导者
4.如果此过程中有多个sentinel节点成为领导者,那么将等待一段时间重新进行选举
    

5.4 故障转移(由sentinel领导者节点完成)

故障转移步骤:

1.从slave节点中选出一个合适的节点作为新的master节点
2.对选出的slave节点执行`slaveof no one`命令,使成为新的master节点
3.向剩余的slave节点发送命令,让slave节点成为新master节点的slave节点,然后从新master节点同步数据
    数据同步规则和parallel-syncs参数有关
    如一个一主三从架构中,master故障,sentinel领导者从3个slave中选出一个作为新的master节点,剩余的两个slave节点会成为新master节点的slave,从新master节点同步同步数据
    master节点只需要生成一次RDB文件
        如果parallel-syncs参数设置为1,则剩余两个slave节点会按顺序从新master节点拷贝数据,一个slave切点拷贝完成,另外一个slave才会从新master节点拷贝数据
        如果parallel-syncs参数设置为2,则两个slave节点会同时从master节点进行数据拷贝,这无疑会加入新master的开销
4.sentinel领导者会把原来的master节点设置为slave节点,并保持对其'关注',当原来的master节点恢复后,sentinel会使其去复制新master节点的数据

5.5 slave节点的选择

slave节点选择规则

1.选择slave-priority(slave节点优先级)最高的slave节点,如果存在则返回,不存在则继续
2.选择复制偏移量(offset)最大的slave节点,offset最大说明对master的数据复制的最完整,如果存在则返回,不存在则继续
3.选择run_id最小的slave节点,run_id最小说明slave节点启动最早
    

6.总结:

Redis Sentinel是Redis的高可用实现方案:故障发现,故障自动转移,配置中心,客户端通知
Redis Sentinel是Redis 2.8版本开始才正式生产可用,之前版本不可用于生产
尽可以在不同物理机上部署Redis Sentinel所有节点,但是最好一个局域网内
Redis Sentinel中sentinel节点个数应该大于等于3,且最好为奇数,可以保证判断的公平
Redis Sentinel中的数据节点与普通数据节点没有区别
客户端初始化时连接的是Sentinel节点集合,不是具体的Redis节点,但是Sentinel只是配置中心不是代理
Redis Sentinel通过三个定时任务实现了Sentinel节点对于master,slave,其余sentinel节点的监控
Redis Sentinel在对节点做失败判定时分为主观下线和客观下线
看懂Redis Sentinel故障转移日志对于Redis Sentinel以及问题排查非常有帮助
Redis Sentinel实现读写分离高可用可以依赖Redis Sentinel节点的消息通知,获取Redis数据节点的状态变化
原文地址:https://www.cnblogs.com/zyy1688/p/10621088.html