Redis单节点、主从、哨兵、集群构建方法

摘要

  • redis单节点、主从、哨兵、集群的构建过程,及其配置文件的说明
  • 本文基于redis-5.0.14

redis安装

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
# 下载
wget https://download.redis.io/releases/redis-5.0.14.tar.gz

# 解压
tar -zxvf redis-5.0.14.tar.gz

# 编译
sudo yum install gcc
cd redis-5.0.14
make

# 编辑配置文件
mv redis.conf redis-6379.conf
vim redis-6379.conf #见下面的配置信息

# 启动redis
# 启动前要先创建好相关目录结构
mkdir -p /usr/local/soft/dir-redis5/6379
src/redis-server redis-6379.conf

# 加入环境变量 /etc/bashrc
export PATH=$PATH:/usr/local/soft/redis-5.0.14/src

# 快捷命令
alias redis-start="redis-server /usr/local/soft/redis-5.0.14/redis-6379.conf"
alias redis-stop="pkill redis-server"

config命令设置

  • 对于已经启动的redis服务,如果不想修改配置文件重启服务的话,也可以通过命令对部分参数进行设置,比如慢查询日志设置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    # 查询
    127.0.0.1:6379> config get slow*
    1) "slowlog-log-slower-than"
    2) "10000"
    3) "slowlog-max-len"
    4) "128"

    # 设置
    127.0.0.1:6379> config set slowlog-max-len 1024
    OK

    # 写入redis.conf
    127.0.0.1:6379> config rewrite
    OK

单节点

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# 端口
port 6379

# 后台启动
daemonize yes

# 如果不设置密码,需要关闭保护模式,开启的话只有本机能够访问,建议开启密码保护
protected-mode no

# 注释掉bind,绑定的是自己机器网卡的ip,如果有多块网卡可以配多个ip,代表允许客户端通过机器的哪些网卡ip去访问,内网一般可以不配置
#bind 127.0.0.1

# 注释掉,因为会启用混合持久化,所以不需要开启rdb快照
# save xx xxx

# 设置dir路径,redis日志、aof和rdb文件都会生成在这个路径下
dir /usr/local/soft/dir-redis5/6379

# 开启aof,实际上只需要开启这个配置,以下aof相关配置默认即可
appendonly yes

# aof文件名称
appendfilename "6379-appendonly.aof"
# aof将数据fsync到磁盘的策略,默认即可,表示每秒一次,故障时最多会丢失一秒的数据
appendfsync everysec

# aof文件至少要达到64M才会自动重写,文件太小恢复速度本来就很快,重写的意义不大,默认即可
auto-aof-rewrite-min-size 64mb
# aof文件自上一次重写后文件大小增长了100%则再次触发重写,默认即可
auto-aof-rewrite-percentage 100

# 开启混合持久化,4.0以后版本支持,需要先开启aof
aof-use-rdb-preamble yes

# pid文件路径
pidfile /usr/local/soft/dir-redis5/6379/redis_6379.pid

# 日志文件名称
logfile "6379.log"

# 指定最大内存,单位bytes,这里设置4G
# 如果不设置最大内存,redis会默认为物理内存,达到上限时会频繁与磁盘发生交换,使redis性能急剧下降
maxmemory 4294967296
# 达到最大内存时的清除策略,推荐volatile-lru,淘汰很久没被访问过的数据,基于最近一次的访问时间
maxmemory-policy volatile-lru

# 慢查询日志
# 单位微妙,这里表示10毫秒,即超过10毫秒的操作都会记录下来
slowlog-log-slower-than 10000

# 设置慢查询日志记录保存数量,如果数量已满会删除最早的记录
slowlog-max-len 1024

# 开启密码
requirepass "password"

# 如果主节点开启了密码认证,则从节点需要设置主节点的密码,哨兵和集群模式时都要设置
masterauth "password"

单节点优点

  • 单机部署简单方便

单节点缺点

  • 不保证数据的可靠性,不适用于数据可靠性要求高的场景
  • 单点故障导致无法提供服务,或者硬盘损坏导致数据丢失
  • redis单节点最大qps为10w(取决于单核cpu的处理能力),超过这个qps就需要做前端限流

主从

  • 主从配置时,主节点不需要做任何修改,以上面单节点配置为例,其作为主节点

  • 从节点参照主节点的配置文件进行配置,如果在同一台机器上,需要修改端口号和相关文件路径,如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 端口
    port 6380

    # pid文件路径
    pidfile /usr/local/soft/dir-redis5/6380/redis_6380.pid

    # 日志文件名称
    logfile "6380.log"

    # 设置dir路径,redis日志、aof和rdb文件都会生成在这个路径下
    dir /usr/local/soft/dir-redis5/6380

    # aof文件名称
    appendfilename "6380-appendonly.aof"
  • 从节点配置文件增加同步主节点信息

    1
    2
    3
    4
    5
    6
    7
    8
    # 指定主节点,从节点会从主节点同步数据,这里10.250.0.103 6379是主节点的ip和端口号
    replicaof 10.250.0.103 6379

    # 配置从节点只读,默认开启,避免数据写入从节点导致主从数据不一致
    replica-read-only yes

    # 如果主节点开启了密码认证,则从节点需要设置主节点的密码
    masterauth "password"
  • 此时启动从节点src/redis-server redis-6379.conf,会自动从主节点同步数据,同步前如果从节点已经有数据,则会先清除原有数据再进行同步

  • 主节点接收到从节点的同步请求后,会通过bgsave将内存数据dump到rdb文件中并传递给从节点

  • 主节点生成rdb文件并传递给从节点期间会继续处理客户端的请求,并将这部分数据缓存到内存中,待从节点接收到主节点发过来的rdb文件并完成内存加载后,主节点会将这部分缓存在内存中的数据发送给从节点

  • 从节点相当于主节点的备份,主节点挂了,从节点不能自动切换为主节点,如果需要自动切换,可以使用哨兵或者集群部署方式

  • 此时登录redis执行info命令可以在Replication中查看到主从配置信息

    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
    28
    29
    30
    31
    32
    33
    34
    master:
    # Replication
    role:master
    connected_slaves:1
    slave0:ip=10.250.0.217,port=6379,state=online,offset=770728,lag=1
    master_replid:23d3f04c39a91dbef52f03c57179932b6d189719
    master_replid2:0af821e669f22c03e624d91f6bb88671c9085591
    master_repl_offset:770728
    second_repl_offset:147042
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:114822
    repl_backlog_histlen:655907

    slave:
    # Replication
    role:slave
    master_host:10.250.0.103
    master_port:6379
    master_link_status:up
    master_last_io_seconds_ago:1
    master_sync_in_progress:0
    slave_repl_offset:788994
    slave_priority:100
    slave_read_only:1
    connected_slaves:0
    master_replid:23d3f04c39a91dbef52f03c57179932b6d189719
    master_replid2:0000000000000000000000000000000000000000
    master_repl_offset:788994
    second_repl_offset:-1
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:149845
    repl_backlog_histlen:639150

主从优点

  • 对请求进行读写分离,提高处理效率
  • 可以提供多个副本,提高数据安全性

主从缺点

  • 不具备自动容错和恢复功能,主节点故障,集群则无法进行工作,可用性比较低,从节点升主节点需要人工手动干预

哨兵

  • 创建三个哨兵

  • 哨兵模式时,主节点如果开启了密码认证则从节点也要开启密码认证,且密码一致,另外主节点也要配置masterauth "password",否则主节点挂了重启后不能与从节点进行数据同步

  • 编辑sentinel.conf

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    # 端口号
    port 26379

    # 后台启动
    daemonize yes

    # pid文件路径
    pidfile /usr/local/soft/dir-redis5/redis-sentinel.pid

    # 日志文件名称
    logfile "sentinel.log"

    # dir
    dir /usr/local/soft/dir-redis

    # 配置监听的主节点地址和端口,mymaster为自定义的名称,最后的2表示,只要有2个哨兵节点认为主节点挂了就会进行重新选主,一般设置为sentinel总数/2+1
    sentinel monitor mymaster 10.250.0.103 6379 2

    # 主节点密码
    sentinel auth-pass mymaster "password"
  • 分别启动三个哨兵节点redis-sentinel sentinel.conf,此时登录哨兵节点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=10.250.0.103:6379,slaves=1,sentinels=2
  • 此时查看sentinel.conf可以在文件最后看到从节点信息和其它的哨兵节点信息,如下

    1
    2
    3
    sentinel known-replica mymaster 10.250.0.217 6379
    sentinel known-sentinel mymaster 10.250.0.189 26379 228936dfc6bb7a0fafb6a1503330887a94fff478
    sentinel known-sentinel mymaster 10.250.0.190 26379 228936dfc6bb7a0fafb6a1503330887a94fff478
  • 此时关闭master节点,然后登录哨兵节点或者从节点查看info,都会发现从节点已经变成了master节点

  • 此时再次开启原master节点,会发现其变成了从节点,相应的配置文件也发生了变更

哨兵优点

  • 主节点故障,可以自动在从节点中重新选主

哨兵缺点

  • 哨兵单点故障,则集群无法访问,所以需要对哨兵集群部署
  • 从节点仅作为备份不提供对外服务,只有当master出现故障时其晋升为master后才能提供服务,所以不支持读写分离

集群

  • 还是基于单节点配置文件,注意如果开启了密码认证,则也要配置masterauth "password"

  • 搭建6个redis的集群,3主3从,如果一台服务器上有多个redis,注意修改端口号和dir路径

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    port 6379
    dir /usr/local/soft/dir-redis5/6379
    requirepass "password"
    masterauth "password"

    # 启动集群模式
    cluster-enabled yes

    # 集群节点信息文件,这里最好和port对应上
    cluster-config-file nodes-6379.conf

    # 集群节点间通信的超时时间,单位毫秒,默认15000,这个时间别设置太短,避免网络抖动等原因干扰
    cluster-node-timeout 15000

    # 写数据成功最少同步的slave数量,默认数据写入master就返回给client了,加上这个配置,就需要数据同步到指定数量的slave后才能返回,
    # 注意这个配置不仅会延长client的等待时间,而且可能会影响集群的可用性,比如这里配置至少同步1个slave,但是如果此时master对应可用的slave不足1个,集群就不能提供服务了,所以建议每个master至少配置了2个以上的slave时才开启这个配置
    # 开启这个配置可以预防集群脑裂问题
    min-replicas-to-write 1

    # 如果集群中某个master/slave全部挂掉,整个集群的其它master/slave是否还可以对外提供服务,默认yes,不能
    # 如果设置为no,则表示依旧可以提供服务,不过如果有key落在了挂掉的主从上就会失败
    cluster-require-full-coverage yes
  • 分别启动6个redis服务

    1
    src/redis-server redis.conf
  • 创建集群,3主3从,注意创建集群前所有redis不能有数据,如果有需要先清空

    1
    redis-cli -a password --cluster create --cluster-replicas 1 10.250.0.67:6379 10.250.0.170:6379 10.250.0.114:6379 10.250.0.110:6379 10.250.0.244:6379 10.250.0.206:6379
  • 此时会列出集群内主从和槽位的分配方案,输入yes即可

    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    >>> Performing hash slots allocation on 6 nodes...
    Master[0] -> Slots 0 - 5460
    Master[1] -> Slots 5461 - 10922
    Master[2] -> Slots 10923 - 16383
    Adding replica 10.250.0.244:6379 to 10.250.0.67:6379
    Adding replica 10.250.0.206:6379 to 10.250.0.170:6379
    Adding replica 10.250.0.110:6379 to 10.250.0.114:6379
    M: df05843701533a368831b4d414a867e8350e8ad6 10.250.0.67:6379
    slots:[0-5460] (5461 slots) master
    M: 0beec83cd2788e35f3b373aad8c60fb5f0f17a3b 10.250.0.170:6379
    slots:[5461-10922] (5462 slots) master
    M: 35ca216e53df5fac37c3996059b19b443ed19e78 10.250.0.114:6379
    slots:[10923-16383] (5461 slots) master
    S: 87509b2809a6c1645416ba03f54ee8a61293bac9 10.250.0.110:6379
    replicates 35ca216e53df5fac37c3996059b19b443ed19e78
    S: 812b99df229ca9143ae72c4447ab4e889f1af113 10.250.0.244:6379
    replicates df05843701533a368831b4d414a867e8350e8ad6
    S: 80e8dcb95905a2c25d8bbb0290e77aa0ca37aa56 10.250.0.206:6379
    replicates 0beec83cd2788e35f3b373aad8c60fb5f0f17a3b
    Can I set the above configuration? (type 'yes' to accept): 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 10.250.0.67:6379)
    M: df05843701533a368831b4d414a867e8350e8ad6 10.250.0.67:6379
    slots:[0-5460] (5461 slots) master
    1 additional replica(s)
    M: 0beec83cd2788e35f3b373aad8c60fb5f0f17a3b 10.250.0.170:6379
    slots:[5461-10922] (5462 slots) master
    1 additional replica(s)
    S: 80e8dcb95905a2c25d8bbb0290e77aa0ca37aa56 10.250.0.206:6379
    slots: (0 slots) slave
    replicates 0beec83cd2788e35f3b373aad8c60fb5f0f17a3b
    M: 35ca216e53df5fac37c3996059b19b443ed19e78 10.250.0.114:6379
    slots:[10923-16383] (5461 slots) master
    1 additional replica(s)
    S: 812b99df229ca9143ae72c4447ab4e889f1af113 10.250.0.244:6379
    slots: (0 slots) slave
    replicates df05843701533a368831b4d414a867e8350e8ad6
    S: 87509b2809a6c1645416ba03f54ee8a61293bac9 10.250.0.110:6379
    slots: (0 slots) slave
    replicates 35ca216e53df5fac37c3996059b19b443ed19e78
    [OK] All nodes agree about slots configuration.
    >>> Check for open slots...
    >>> Check slots coverage...
    [OK] All 16384 slots covered.

  • 登录集群并查询集群配置信息

    1
    2
    # -c 表示以集群模式登录,-h 集群内任意ip
    src/redis-cli -c -h 10.250.0.67 -p 6379 -a password
  • 查看集群信息

    cluster info

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    cluster_state:ok
    cluster_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:147
    cluster_stats_messages_pong_sent:156
    cluster_stats_messages_sent:303
    cluster_stats_messages_ping_received:151
    cluster_stats_messages_pong_received:147
    cluster_stats_messages_meet_received:5
    cluster_stats_messages_received:303
  • 查看节点列表

    cluster nodes

    1
    2
    3
    4
    5
    6
    0beec83cd2788e35f3b373aad8c60fb5f0f17a3b 10.250.0.170:6379@16379 master - 0 1662724614912 2 connected 5461-10922
    80e8dcb95905a2c25d8bbb0290e77aa0ca37aa56 10.250.0.206:6379@16379 slave 0beec83cd2788e35f3b373aad8c60fb5f0f17a3b 0 1662724615000 6 connected
    35ca216e53df5fac37c3996059b19b443ed19e78 10.250.0.114:6379@16379 master - 0 1662724613000 3 connected 10923-16383
    df05843701533a368831b4d414a867e8350e8ad6 10.250.0.67:6379@16379 myself,master - 0 1662724614000 1 connected 0-5460
    812b99df229ca9143ae72c4447ab4e889f1af113 10.250.0.244:6379@16379 slave df05843701533a368831b4d414a867e8350e8ad6 0 1662724613910 5 connected
    87509b2809a6c1645416ba03f54ee8a61293bac9 10.250.0.110:6379@16379 slave 35ca216e53df5fac37c3996059b19b443ed19e78 0 1662724615914 4 connected

此时查看nodes-6379.conf也会看到和上面一样的节点信息

  • 此时关闭其中一个master节点,比如10.250.0.67,则其对以的slave节点10.250.0.244会切换为新的master节点,此时10.250.0.67的状态为fail

    1
    2
    3
    4
    5
    6
    7
    10.250.0.206:6379> cluster nodes
    87509b2809a6c1645416ba03f54ee8a61293bac9 10.250.0.110:6379@16379 slave 35ca216e53df5fac37c3996059b19b443ed19e78 0 1662780661815 4 connected
    80e8dcb95905a2c25d8bbb0290e77aa0ca37aa56 10.250.0.206:6379@16379 myself,slave 0beec83cd2788e35f3b373aad8c60fb5f0f17a3b 0 1662780661000 6 connected
    df05843701533a368831b4d414a867e8350e8ad6 10.250.0.67:6379@16379 master,fail - 1662780649679 1662780648000 1 connected
    812b99df229ca9143ae72c4447ab4e889f1af113 10.250.0.244:6379@16379 master - 0 1662780661000 7 connected 0-5460
    0beec83cd2788e35f3b373aad8c60fb5f0f17a3b 10.250.0.170:6379@16379 master - 0 1662780661000 2 connected 5461-10922
    35ca216e53df5fac37c3996059b19b443ed19e78 10.250.0.114:6379@16379 master - 0 1662780662000 3 connected 10923-16383
  • 再次启动10.250.0.67,其会变成10.250.0.244的slave节点

    1
    2
    3
    4
    5
    6
    7
    10.250.0.206:6379> cluster nodes
    87509b2809a6c1645416ba03f54ee8a61293bac9 10.250.0.110:6379@16379 slave 35ca216e53df5fac37c3996059b19b443ed19e78 0 1662781012000 4 connected
    80e8dcb95905a2c25d8bbb0290e77aa0ca37aa56 10.250.0.206:6379@16379 myself,slave 0beec83cd2788e35f3b373aad8c60fb5f0f17a3b 0 1662781012000 6 connected
    df05843701533a368831b4d414a867e8350e8ad6 10.250.0.67:6379@16379 slave 812b99df229ca9143ae72c4447ab4e889f1af113 0 1662781013708 7 connected
    812b99df229ca9143ae72c4447ab4e889f1af113 10.250.0.244:6379@16379 master - 0 1662781011000 7 connected 0-5460
    0beec83cd2788e35f3b373aad8c60fb5f0f17a3b 10.250.0.170:6379@16379 master - 0 1662781012706 2 connected 5461-10922
    35ca216e53df5fac37c3996059b19b443ed19e78 10.250.0.114:6379@16379 master - 0 1662781012000 3 connected 10923-16383
  • redis集群会将2的14次幂(16384)的soft平均分配到所有master上,然后对key进行hash后计算应该存储到那个soft

    1
    2
    3
    4
    5
    6
    HASH_SLOT=CRC16(key) mod 16384

    # 跳转重定位
    10.250.0.206:6379> set name zhangsan
    -> Redirected to slot [5798] located at 10.250.0.170:6379
    OK
  • 关闭集群,6个redis分别关闭

    1
    src/redis-cli -c -h 10.250.0.67 -p 6379 -a password shutdown
  • 重启集群,6个redis分别启动即可

    1
    src/redis-server redis.conf
  • mset/mget要求key都落在同一个soft上,每个key都加上前缀{prefix}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    10.250.0.170:6379> mset name1 lisi name2 wangwu
    (error) CROSSSLOT Keys in request don't hash to the same slot

    10.250.0.170:6379> mset {user}:name1 lisi {user}:name2 wangwu
    OK

    10.250.0.206:6379> mget {user}:name1 {user}:name2
    -> Redirected to slot [5474] located at 10.250.0.170:6379
    1) "lisi"
    2) "wangwu"
  • 集群推举新的master时要求至少一半的master同意,所以一个集群至少需要3个master,官方推荐master节点数为奇数,比如3个和4个master节点,都至多允许一个master节点挂掉时进行选主,但是3个master可以节省资源

  • 集群通过10000+port这个端口号进行集群间通信,所以除了要开放prot这个端口,还要开放10000+port这个端口

  • 有关redis集群及其水平扩展的进一步说明,可以参看Redis集群

集群优点

  • 无中心架构,集群内部自行维护数据的分片和主从的切换
  • 数据分片存储,提供很高的访问效率
  • 高可用性,可实现部分节点不可用时,集群仍可用
  • 高扩展性,可以横向扩展1000个节点后依旧保证访问效率,扩容缩容都支持

集群缺点

  • 数据通过异步复制,不保证数据的强一致性
  • 不支持多数据库空间,单机下的redis可以支持到16个数据库,集群模式下只能使用1个数据库空间,即db 0
  • 不支持跨slot操作,如使用mset、mget目前只支持具有相同slot值的Key执行批量操作
  • Key作为数据分区的最小粒度,不能将一个很大的键值对象如hash、list等映射到不同的节点
  • Key事务操作支持有限,只支持多key在同一节点上的事务操作,当多个Key分布于不同的节点上时无法使用事务功能
  • 不建议使用pipeline和multi-keys操作