Linux分布式缓存系统——Redis持久化+Sentinel哨兵模式+Redis集群

Redis介绍

Redis是一个开源的使用C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API
它通常被称为数据结构服务器,因为值(value) 可以是字符串(String)、哈希(Map)、列表(list)、 集合(sets) 和有序集合(sorted sets)等类型。

Redis与其他key - value缓存产品有以下特点:
(1)支持数据持久化,可以将内存放入数据保存在磁盘中,启动的时候可以再次加载进行使用。
(2)支持多种数据结构的存储,丰富的数据类型Redis支持二进制案例的Strings, list, Hashes, set以及Ordered set数据类型的操作
(3)支持数据备份,即master slave模式的数据备份
(4)所有的操作都是原子性的,同时Redis还支持几个操作合并后的原子执行
(5)高性能,Redis读的速度是110000次/s,写的速度是81000次/s

体系结构

redis结构

互联网数据目前基本使用关系数据库或者key value存储,但前者存在冗余数据,后者修改和删除比较麻烦。
Redis在内存中设计了各种数据类型,让业务能够高速原子的访问这些数据结构,并且不需要关心持久存储的问题,从架构上解决了前面两种存储需要走弯路的问题。

备份模式

在Redis中有Replication,由于Redis的高性能,复制基本没有延迟,达到了防止单点故障实现高可用

容灾模式

sentinel系统集群监控redis主从系统集群

数据类型

String (字符串)

Redis最基本的数据类型,一个key对应一个value,一个键最大能存储512MB
set key value赋值,用get key获得key的值

Hash(哈希)

是一个键值对集合,是一个string类型的field和value的映射表,适合用于存储对象
hset/hget 一次插入一个键值对
hmset/hmget 一次插入多个键值对
hgetall 用于获取hash对象

127.0.0.1:6379> hset set1 name zhangsan
(integer) 1
127.0.0.1:6379> hset set1 score 100
(integer) 1
127.0.0.1:6379> hset set1 age 20
(integer) 1

127.0.0.1:6379> hmget set1 name score age
1) "zhangsan"
2) "100"
3) "20"

127.0.0.1:6379> hgetall set1
1) "name"
2) "zhangsan"
3) "score"
4) "100"
5) "age"
6) "20"

LIST(列表)

Ipush 往列表的前边插入
Irange 闭区间

127.0.0.1:6379> lpush lvar 1
(integer) 1
127.0.0.1:6379> lpush lvar a
(integer) 2
127.0.0.1:6379> lpush lvar ab
(integer) 3
127.0.0.1:6379> lrange lvar 0 2
1) "ab"
2) "a"
3) "1"

Set(集合)

Redis的Set是string类型的无序集合,不能重复,通过哈希表实现,可以添加,删除
set 往集合中插入元素
smembers 列举出集合中的元素

127.0.0.1:6379> sadd setvar redis
(integer) 1
127.0.0.1:6379> sadd setvar mongodb
(integer) 1
127.0.0.1:6379> sadd setvar rabbitmq
(integer) 1
127.0.0.1:6379> SMEMBERS setvar
1) "mongodb"
2) "rabbitmq"
3) "redis"

zset(sorted sets:有序集合)

zset和set一样也是String类型的集合, 且不允许元素重复
zset和set不同的地方在于zset关联一个double类型的分数,redis通过分数对集合中的元素排序
zset的元素是唯一的,但是分数是可以重复的
分数可正可负可为0

127.0.0.1:6379> zadd zvar 1 redis
(integer) 1
127.0.0.1:6379> zadd zvar 1 mongodb
(integer) 1
127.0.0.1:6379> zadd zvar 2 mongodb		#已存在
(integer) 0
127.0.0.1:6379> zadd zvar 0 rabbitmq
(integer) 1
127.0.0.1:6379> zrangebyscore zvar 0 2
1) "rabbitmq"
2) "redis"
3) "mongodb"

redis的应用场景

(1)缓存系统:与Memcached类似。
(2)计数器:例如转发数、评论数,有了原子递增(Atomic Increment),可以加上计数,用GETSET重置,或者是让其过期。
(3)消息队列系统:类似于kafka,运行稳定并且快速,支持模式匹配,能够实时订阅与取消频道。
(4)社交网络: Redis可以非常好的与社交网络结合,用户和状态消息将会聚焦很多有用的信息,很多交互如实时聊天就是通过Redis来实现的。
(5)过期项目处理:通过系统时间为关键字,用来保持列表能够按时间排序;对currenttime和timetolive进行检索,完成查找过期项目的艰巨任务。
(6)实时系统:使用位图来做布隆过滤器,例如实现垃圾邮件过滤系统的开发变的非常容易。

Redis持久化

Snapshotting

快照是默认的持久化方式。这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。可以通过配置设置自动做快照持久化的方式。我们可以配置redis在n秒内如果超过m个key被修改就自动做快照,下面是默认的快照保存配置:

save 300 10 #300秒内容如超过10个key被修改,则发起快照保存

AOF Append-only-file

使用aof持久化方式时,redis会将每一个收到的写命令都通过write函数追加文件中(默认是appendonly.aof)。当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。

由于os会在内核中缓存write做的修改,所以可能不是立即写到磁盘上。这样aof方式的持久化也还是有可能会丢失部分修改。可以通过配置文件告诉redis通过fsync函数强制os写入到磁盘的时机。有三种方式如下(默认是:每秒fsync一次) :

appendonly yes
#启用aof持久化方式
# appendfsync always
#每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用
appendfsync everysec
#每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐
# appendfsync no
#完全依赖os,性能最好,持久化没保证

redis提供了bgrewriteaof命令,收到此命令redis将使用与快照类似的方式将内存中的数据以命令的方式保存到临时文件中,最后替换原来的文件。这样做可以压缩aof的持久化文件。

数据持久化对比

RDB方式AOF方式
描述默认方式,实现方式是定时将内存的快照(snapshot) 持久化到硬盘。Aof即append only file,在写入内存数据的同时将操作命令保存到日志文件中。
优点使用单独子进程来进行持久化,主进程不会进行任何IO操作,保证redis的高性能。保证了数据的可靠性及安全性,保证更高的数据完整性。
缺点RDB是间隔一段时间进行持久化,如果持久化之间redis发生故障,会发生数据丢失。在并发更改上万的系统中,命令日志是一个非常庞大的数据,管理维护成本非常高,恢复创建时间会非常长;AOF文件比RDB文件大,且恢复速度慢。
应用更适合数据要求不严谨的时候适合数据完整性要求较高的场景

Redis安装配置及运用

redis安装

[ ~]# yum install gcc gcc-c++ make -y
[ ~]# wget http://download.redis.io/releases/redis-5.0.4.tar.gz
[ ~]# tar xf redis-5.0.4.tar.gz -C /opt
[ ~]# cd /opt/redis-5.0.4/
[ redis-5.0.4]# make
Hint: It‘s a good idea to run ‘make test‘ ;)
[ redis-5.0.4]# echo $?
0
[ redis-5.0.4]# mkdir -p /data/redis/
[ redis-5.0.4]# make PREFIX=/data/redis install
Hint: It‘s a good idea to run ‘make test‘ ;)
[ redis-5.0.4]# mkdir /data/redis/conf
[ redis-5.0.4]# cp -p redis.conf /data/redis/conf/
#添加系统路径
[ ~]# echo "export PATH=$PATH:/data/redis/bin" >>/etc/bashrc
[ ~]# source /etc/bashrc

生成的指令

[ redis-5.0.4]# cd /data/redis/bin/
[ bin]# ll
total 32700
-rwxr-xr-x 1 root root 4366520 Mar  8 10:03 redis-benchmark
-rwxr-xr-x 1 root root 8101224 Mar  8 10:03 redis-check-aof
-rwxr-xr-x 1 root root 8101224 Mar  8 10:03 redis-check-rdb
-rwxr-xr-x 1 root root 4806736 Mar  8 10:03 redis-cli
lrwxrwxrwx 1 root root      12 Mar  8 10:03 redis-sentinel -> redis-server
-rwxr-xr-x 1 root root 8101224 Mar  8 10:03 redis-server

启动

[ bin]# ./redis-server -h
Usage: ./redis-server [/path/to/redis.conf] [options]
       ./redis-server - (read config from stdin)
       ./redis-server -v or --version
       ./redis-server -h or --help
       ./redis-server --test-memory <megabytes>

Examples:
       ./redis-server (run the server with default conf)
       ./redis-server /etc/redis/6379.conf
       ./redis-server --port 7777
       ./redis-server --port 7777 --replicaof 127.0.0.1 8888
       ./redis-server /etc/myredis.conf --loglevel verbose

Sentinel mode:
       ./redis-server /etc/sentinel.conf --sentinel
[ bin]# /data/redis/bin/redis-server /data/redis/conf/redis.conf
(服务已启动,但进程未退出,重新打开一个终端测试)
[ ~]# tty
/dev/pts/1
[ ~]# ps -ef|grep redis
root       5578   1260  0 10:09 pts/0    00:00:00 /data/redis/bin/redis-server 127.0.0.1:6379
root       5583   1293  0 10:10 pts/1    00:00:00 grep --color=auto redis

需要退出,Ctrl+C即可杀死进程,退出服务
若需要进程一直处于运行状态, 则可将进程放在后台使用

[ ~]# /data/redis/bi n/redis-server /data/ redis/conf/redis .conf &
[ ~]# /data/redis/bin/redis-cli shutdown

调优

内核参数解释
net.core .somaxconn表示socket监听(listen) 的backlog上限,backlog就是socket的监听队列,当一个请求(request) 尚未被处理或建立时,他会进入backlog。而socket server可以一次性处理backlog中的所有请求, 处理后的请求不再位于监听队列中。当server处理请求较慢, 以至于监听(队列被填满后,新来的请求会被拒绝。Linux的参数net.core.somaxconn默认值同样为128。 当服务端繁忙时,128是远远不够的。这样就需要增:大backlog。
overcommit_ memory是一个内核对内存分配的一种策略。overcommit _memory=0,表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。overcommit. memory=1,表示内核允许分配所有的物理内存,而不管当前的内存状态如何。overcommit memory=2,表示内核允许分配超过所有物理内存和交换空间总和的内存
hugepagehugepage动态分配

redis启动后,有这样3个警告

5578:M 08 Mar 2020 10:09:02.235 # WARNING: The TCP backlog setting of 511 canno                                                t be enforced because /proc/sys/net/core/somaxconn is set to the lower value of                                                 128.
5578:M 08 Mar 2020 10:09:02.235 # Server initialized
5578:M 08 Mar 2020 10:09:02.235 # WARNING overcommit_memory is set to 0! Backgr                                                ound save may fail under low memory condition. To fix this issue add ‘vm.overco                                                mmit_memory = 1‘ to /etc/sysctl.conf and then reboot or run the command ‘sysctl                                                 vm.overcommit_memory=1‘ for this to take effect.
5578:M 08 Mar 2020 10:09:02.235 # WARNING you have Transparent Huge Pages (THP)                                                 support enabled in your kernel. This will create latency and memory usage issu                                                es with Redis. To fix this issue run the command ‘echo never > /sys/kernel/mm/t                                                ransparent_hugepage/enabled‘ as root, and add it to your /etc/rc.local in order                                                 to retain the setting after a reboot. Redis must be restarted after THP is dis                                                abled.

需要我们调整对应的内核参数

[ ~]# echo 1024 > /proc/sys/net/core/somaxconn
[ ~]# echo 1 > /proc/sys/vm/overcommit_memory
#overcommit_ memory 1容许过量使用内存 《= 物理内存+ swap 8G+2G ==10G
#12G内存	1inux内存	oom内存泄漏	oom_kill
[ ~]# echo never > /sys/kernel/mm/transparent_hugepage/enabled

客户端连接

本地连接

[ ~]# /data/redis/bin/redis-cli
127.0.0.1:6379> set name anliu
OK
127.0.0.1:6379> get name
"anliu"
127.0.0.1:6379> set IP 192.168.213.129
OK
127.0.0.1:6379> get IP
"192.168.213.129"

启动客户端、验证

127.0.0.1:6379> ping
PONG
127.0.0.1:6379> set var "hello world"
OK
127.0.0.1:6379> get var
"hello world"

远程连接

需要已经安装redis,可以使用redis-cli命令
redis-cli -h host -p port -a password

安全性设置

设置密码

[ ~]# vim /data/redis/conf/redis.conf
requirepass redis
[ ~]# redis restart
[ ~]# /data/redis/bin/redis-cli
127.0.0.1:6379> auth redis
OK

命令别名

可以通过把一个命令重命名为空串或随机字符串来彻底kill掉这个命令

[ ~]# vim /data/redis/conf/redis.conf
#rename-command CONFIG ""
#rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52

#测试
192.168.213.129:63789> config get max--entries*
config get max--entries* (error) ERR unknown command ‘config‘

设置启动日志

[ ~]# vim /data/redis/conf/redis.conf
logfile "/data/redis/log/logs"

redis启动脚本

[ ~]# cat /data/redis/bin/redis
#!/bin/bash
stop() {
/data/redis/bin/redis-cli -a redis shutdown
}
start(){
/data/redis/bin/redis-server /data/redis/conf/redis.conf &
}
case $1 in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        start
        ;;
     *)
        echo "Usage:$0 (start|stop|restart)"
esac
[ ~]# chmod +x /data/redis/bin/redis
[ ~]# ln -s /data/redis/bin/redis /usr/local/bin/redis

退出

redis-cli shutdown

如果设置上密码后,单纯的redis-cli是关不掉的,必须加上ip、port、passwd
/data/redis/bin/redis-cli -h 192.168.213.129 -p 6380 -a redis shutdown

查看redis-server统计信息

配置详解

#yes作为守护进程后台运行
daemonize yes
#当redis作为守护进程运行的时候,它会把pid默认写到/var/run/redis.pid 文件里面,你也可以指定写入的位置
pidfile /var/run/redis_6379.pid

发布订阅

创建订阅频道redisChat

192.168.213.129:6379> subscribe redisChat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
3) (integer) 1

客户端订阅

192.168.213.129:6379> psubscribe redisChat
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "redisChat"
3) (integer) 1

发布消息

192.168.213.129:6379> publish redisChat "hello world"
(integer) 2

客户端会收到消息

1) "pmessage"
2) "redisChat"
3) "redisChat"
4) "hello world"

事务

保证多个操作同时成功执行,在一个事务中,任何一个操作发生error,所有操作都会回滚。

主从复制企业级方案

配置

主从复制的创建

(1)方法一: redis-server --slaveof,配置当前服务成为某个Redis服务的slave

实例1:目前有两个redis实例,一个基于当前主机的6379端口,一个基于当前主机的6380端口,将6379端口机器设置成6380的slave

[ ~]# /data/redis/bin/redis-server /data/redis/conf/6380.conf
[ ~]# ps -ef|grep redis
root      13189      1  0 15:23 ?        00:00:00 ./redis-server *:6380
root      13220      1  0 15:24 ?        00:00:00 /data/redis/bin/redis-server *:6379
root      13226   1260  0 15:24 pts/0    00:00:00 grep --color=auto redis
#加上--slaveof参数可启动一个从节点
[ ~]# /data/redis/bin/redis-server --port 6379 --slaveof 192.168.213.129 6380
14713:S 08 Mar 2020 15:53:19.078 * MASTER <-> REPLICA sync: Finished with success

测试

127.0.0.1:6380> set a linux
OK
127.0.0.1:6379> get a
"linux"
127.0.0.1:6379> set b apache
(error) READONLY You can‘t write against a read only replica.

在主库上创建数据正常,在从库上创建数据将报错,get的时候,能够获取到主库上创建的值,因此,从库只能读,不能写

(2)方法二: slaveof host port命令,将当前服务器状态从master修改为别的服务的slave

redis > SLAVEOF 192.168.213.122 6379	#将服务器转换为slave
redis > SLAVE OF NO ONE	#将服务器重新恢复到Master,不会丢弃已经同步的数据

实例2:已有一台master实例:127.0.0.1: 8000处于正常工作状态,接受读写请求,由于单台机器的压力过大,再启动一个slave实例:127.0.0.1: 8001来分担master的读压力

127.0.0.1:8001> SLAVEOF 127.0.0.1 8000

(3)方法三: 启动时,服务器读取配置文件,并自动成为指定服务器的从服务器

实例3: Redis主从结构支持一主多从(所有从节点的配置都一样,只需要额外修改从节点中redis的配置文件中的slaveof属性即可)

#replicaof <masterip> <masterport>
replicaof 127.0.0.1 6379

主从复制的问题

哨兵模式

手动模拟故障切换

实例4:配置本机的6379端口的redis实例为Master,6380、6381端口的redis实例为两个Slave,手动模拟当Master节点故障之后,启动一个Slave为Master

[ conf]# /data/redis/bin/redis-server redis.conf
[ conf]# /data/redis/bin/redis-server 6380.conf
[ conf]# /data/redis/bin/redis-server 6381.conf
[ conf]# ps -ef|grep redis
root      16425      1  0 16:27 ?        00:00:00 /data/redis/bin/redis-server 0.0.0.0:6379
root      16435      1  0 16:27 ?        00:00:00 /data/redis/bin/redis-server 0.0.0.0:6380
root      16442      1  0 16:27 ?        00:00:00 /data/redis/bin/redis-server 0.0.0.0:6381
root      16455   1260  0 16:27 pts/0    00:00:00 grep --color=auto redis

设置6380,6381实例为6379实例的从

127.0.0.1:6380> slaveof 192.168.213.129 6379
OK
127.0.0.1:6381> slaveof 192.168.213.129 6379
OK

此时,ctrl+c当掉6379实例(Master)

[ ~]# /data/redis/bin/redis-cli -h 192.168.213.129 -p 6379 shutdown

6380以及6381实例(Slave) 日志报错
将6380设置为Master,6381实例(Slave) 指向6380 (Master)

127.0.0.1:6380> SLAVEOF NO ONE
127.0.0.1:6381> SLAVEOF 192.168.213.129 6380

以上实例是通过手动方式实现的一个故障的切换,可以使用一个监控机制来完成该操作,当有节点故障时,故障自动转移,也就是哨兵模式。

Sentinel介绍

1.sentinel高可用

(1)官方提供的高可用方案,可以用它管理多个Redis服务实例
(2)编译后产生redis-sentinel程序文件
(3)Redis sentinel是一个分布式系统,可以在一个架构中运行多个Sentinel进程

2.Sentinel启动方式

(1)将src目录下产生的redis-sentinel程序文件复制到/data/redis/bin/
(2)启动一个运行在Sentinel模式下的Redis服务实例
nohup /data/redis/bin/redis-sentinel /data/redis/conf/sentinel/sentinel1.conf >> /data/redis/log/sentinel1.log 2>&1 &
(3)redis Sentinel是一个分布式系统,可以在一个架构中运行Sentinel进程

3.监控Monitoring

(1)sentinel会不断检查Master和Slaves是否正常
(2)每一个Sentinel可以监控任意多个Master和该Master下的Slaves

4.sentinel配置文件

(1)至少包含一个监控配置选项,用于指定被监控Master的相关信息
(2)sentinel monitor例如:
1 sentinel monitor mymaster 127.0.0.1 6379 2
监视mymaster的主服务器,服务器ip和端口,将这个主服务器下线失效至少需要2个sentinel同意,如果多数Sentinel同意才会执行故障转移
(3)sentinel会根据Master配置,自动发现Master的Slaves
(4)sentinel默认端口为26379

sentinel配置实例

主机规划

redis一主两从环境搭建

[ ~]# cd /data/redis/conf/
[ conf]# /data/redis/bin/redis-server redis.conf
[ conf]# /data/redis/bin/redis-server 6780.conf
[ conf]# /data/redis/bin/redis-server 6380.conf
[ conf]# /data/redis/bin/redis-server 6381.conf
127.0.0.1:6380> slaveof 192.168.213.129 6379
OK
127.0.0.1:6381> slaveof 192.168.213.129 6379
OK

哨兵模式集群的搭建

创建sentinel.conf文件
Sentinel monitor <name> <ip> <port> <quorum>

选项含义
nameredis主服务名称,可以自行命名,但是在一个sentine1网络中,一个redis主服务只能有一个名称
ipredis主服务的IP地址
portredis主服务的端口号
quorum表示要将这个主服务器判断为失效并下线至少需要2个sentine1同意
protected-mode no关闭保护模式(默认yes,若想从远程连接redis集群,需要将redis node和sentine 1的protected-mode都修改为no,并增加密码证或是IP限制等保护机制)
[ conf]# mkdir sentinel
[ conf]# vim sentinel/sentinel1.conf
port 26379
sentinel monitor s1 127.0.0.1 6379 2
#protected-mode no	远程连接需要,同时要设置保护密码
[ conf]# vim sentinel/sentinel2.conf
port 26380
sentinel monitor s1 127.0.0.1 6379 2
#protected-mode no
[ ~]# nohup /data/redis/bin/redis-sentinel /data/redis/conf/sentinel/sentinel1.conf >> /data/redis/log/sentinel1.log 2>&1 &
[1] 19581
[ ~]# nohup /data/redis/bin/redis-sentinel /data/redis/conf/sentinel/sentinel2.conf >> /data/redis/log/sentinel2.log 2>&1 &
[2] 19593
[ ~]# netstat -tunpl|grep redis
tcp        0      0 0.0.0.0:26379           0.0.0.0:*               LISTEN      19581/redis-sentine
tcp        0      0 0.0.0.0:6379            0.0.0.0:*               LISTEN      18692/redis-server
tcp        0      0 0.0.0.0:26380           0.0.0.0:*               LISTEN      19593/redis-sentine
tcp        0      0 0.0.0.0:6380            0.0.0.0:*               LISTEN      18720/redis-server
tcp        0      0 0.0.0.0:6381            0.0.0.0:*               LISTEN      18728/redis-server
tcp6       0      0 :::26379                :::*                    LISTEN      19581/redis-sentine
tcp6       0      0 :::26380                :::*                    LISTEN      19593/redis-sentine

结果测试

#模拟master破坏
[ ~]# kill 18692
#查看日志,此时6381实例已被选举为master, 6380实例连接到了6381实例上
[ ~]# cat /data/redis/log/6380.log
18720:S 08 Mar 2020 17:51:01.760 * REPLICAOF 192.168.213.129:6381 enabled (user request from ‘id=13 addr=127.0.0.1:38526 fd=14 name=sentinel-4cd7af2d-cmd age=1041 idle=0 flags=x db=0 sub=0 psub=0 multi=3 qbuf=302 qbuf-free=32466 obl=36 oll=0 omem=0 events=r cmd=exec‘)
18720:S 08 Mar 2020 17:51:01.761 # CONFIG REWRITE executed with success.
18720:S 08 Mar 2020 17:51:02.053 * Connecting to MASTER 192.168.213.129:6381
#再次启动6379实例
[ conf]# /data/redis/bin/redis-server 6380.conf
#由6379实例的日志可知,其数据从6381上同步
[ ~]# cat /data/redis/log/6379.log
Connecting to MASTER 127.0.0.1:6381

sentinel.conf是动态变化的

集群

集群介绍

redis3.0版本以上,提供集群功能
redis集群cluster是一个提供在多个Redis节点间共享数据的程序集,通过分区share来提供一定程度的可用性,在实际环境中当某一个节点宕机或者不可达的请况下继续处理命令
优势
自动分割数据到不同的节点上
整个集群的部分节点失败或者不可达的情况下能够继续处理命令

redis集群的数据分片

redis使用hash槽,每个key通过CRC16校验后对16384模运算来决定放置在哪个槽,集群的每一个节点负责一部分hash槽

例如当前集群有三个节点,数据hash运算除以16384取余决定数据存放的槽

节点A:包含0-5460号hash槽
节点B:包含5461-10922号hash槽
节点C:包含10923-16383号hash槽

>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
#将副本192.168.213.129:6381添加到192.168.213.122:7001
#即7001是6381的主
Adding replica 192.168.213.129:6381 to 192.168.213.122:7001
Adding replica 192.168.213.122:7003 to 192.168.213.129:6379
Adding replica 192.168.213.129:6380 to 192.168.213.122:7002
M: 4838bf825e942e4a1a79b61081ce749c8932dcb1 192.168.213.122:7001
   slots:[0-5460] (5461 slots) master
M: 5ade0db448b0a37c3d7330f11f2831bf83e54c00 192.168.213.122:7002
   slots:[10923-16383] (5461 slots) master
S: d088be29c75658b2aa4ed239eab5e7f13dbfc447 192.168.213.122:7003
   replicates 5875462598cefde5b92f3292a81aa0828656c566
M: 5875462598cefde5b92f3292a81aa0828656c566 192.168.213.129:6379
   slots:[5461-10922] (5462 slots) master
S: 5731e62cf465d5fe4cd47802566ce9d80dc308ef 192.168.213.129:6380
   replicates 5ade0db448b0a37c3d7330f11f2831bf83e54c00
S: 3fc2693b0e5b27776a9730e42e1e69f9b5eba9a3 192.168.213.129:6381
   replicates 4838bf825e942e4a1a79b61081ce749c8932dcb1

集群的主从复制模型

redis并不能保证数据的强一致性,集群使用异步复制写操作过程,这意味着在实际中集群在特定条件下操作可能丢失一些数据

集群搭建过程

参数修改

搭建并使用Redis集群。
需要启动集群模式的实例。

cluster-enabled yes	#启动集群模式
cluster-config-file nodes.conf	#指定集群文件(自动生成)
cluster-node-timeout 5000	#集群超时时间(毫秒)
appendonly yes

集群搭建

192.168.213.129 6379 6380 6381
192.168.25.122 7003 7004 7005

同步时间
关闭防火墙
卸载mariadb-libs,postfix

集群配置

(1)分别在两个节点上安装redis
(2)为了方便使用创建集群命令,将其复制到/usr/local/bin

[ src]# pwd
/opt/redis-5.0.4/src
[ src]# cp -p redis-trib.rb /usr/local/bin

[ ~]# cd /usr/local/src/redis-5.0.4/src/
[ src]# cp -p redis-trib.rb /usr/local/bin

添加系统路径 export PATH=$PATH: /data/redis/bin
(3)修改配置文件

bind 192.168.213.129
port 6380
daemonize yes
1ogfile "/data/redis/log/6380.log"
pidfile /var/run/redis_6380.pid
cluster-enabled yes
cluster-config-file nodes-6380.conf
cluster-node-timeout 5000
appendonly yes

(4)启动实例

[ conf]# redis-server redis.conf
[ conf]# redis-server 6380.conf
[ conf]# redis-server 6381.conf

[ conf]# redis-server redis.conf
[ conf]# redis-server 7002.conf
[ conf]# redis-server 7003.conf

(5)创建集群

[ ~]# redis-cli --cluster create 192.168.213.122:7001 192.168.213.122:7002 192.168.213.122:7003 192.168.213.129:6379 192.168.213.129:6380 192.168.213.129:6381 --cluster-replicas 1
>>> 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.213.129:6381 to 192.168.213.122:7001
Adding replica 192.168.213.122:7003 to 192.168.213.129:6379
Adding replica 192.168.213.129:6380 to 192.168.213.122:7002
M: 4838bf825e942e4a1a79b61081ce749c8932dcb1 192.168.213.122:7001
   slots:[0-5460] (5461 slots) master
M: 5ade0db448b0a37c3d7330f11f2831bf83e54c00 192.168.213.122:7002
   slots:[10923-16383] (5461 slots) master
S: d088be29c75658b2aa4ed239eab5e7f13dbfc447 192.168.213.122:7003
   replicates 5875462598cefde5b92f3292a81aa0828656c566
M: 5875462598cefde5b92f3292a81aa0828656c566 192.168.213.129:6379
   slots:[5461-10922] (5462 slots) master
S: 5731e62cf465d5fe4cd47802566ce9d80dc308ef 192.168.213.129:6380
   replicates 5ade0db448b0a37c3d7330f11f2831bf83e54c00
S: 3fc2693b0e5b27776a9730e42e1e69f9b5eba9a3 192.168.213.129:6381
   replicates 4838bf825e942e4a1a79b61081ce749c8932dcb1
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 192.168.213.122:7001)
M: 4838bf825e942e4a1a79b61081ce749c8932dcb1 192.168.213.122:7001
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
M: 5ade0db448b0a37c3d7330f11f2831bf83e54c00 192.168.213.122:7002
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 5731e62cf465d5fe4cd47802566ce9d80dc308ef 192.168.213.129:6380
   slots: (0 slots) slave
   replicates 5ade0db448b0a37c3d7330f11f2831bf83e54c00
S: d088be29c75658b2aa4ed239eab5e7f13dbfc447 192.168.213.122:7003
   slots: (0 slots) slave
   replicates 5875462598cefde5b92f3292a81aa0828656c566
M: 5875462598cefde5b92f3292a81aa0828656c566 192.168.213.129:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: 3fc2693b0e5b27776a9730e42e1e69f9b5eba9a3 192.168.213.129:6381
   slots: (0 slots) slave
   replicates 4838bf825e942e4a1a79b61081ce749c8932dcb1
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

(6)向集群里面存储数据

[ ~]# redis-cli -h 192.168.213.122 -p 7001 -c
192.168.213.122:7001> set name 123
-> Redirected to slot [5798] located at 192.168.213.129:6379
OK
192.168.213.129:6379> set name 456
OK
192.168.213.129:6379> quit
[ ~]# redis-cli -h 192.168.213.129 -p 6379 -c
192.168.213.129:6379> get name
"456"
192.168.213.129:6379> quit
[ ~]# redis-cli -h 192.168.213.129 -p 6380 -c
192.168.213.129:6380> get name
-> Redirected to slot [5798] located at 192.168.213.129:6379
"456"

主挂掉,对应的从会升级为主;一个服务器挂掉,另一个服务器会全部升级为主,客户端不会挂掉

问题

1.redis Connection refused 远程连接错误
安装redis时,其配置文件默认是绑定本地ip的,bind 127.0.0.1,把它注释掉,再重启redis服务器,就可以进行远程连接了

[ ~]# vim /data/redis/conf/redis.conf
#bind 127.0.0.1
[ ~]# /data/redis/bin/redis-server /data/redis/conf/redis.conf

2.在群集模式下不允许复制指令
将配置文件中的 replicaof 127.0.0.1 6379 注释掉即可

[ conf]# redis-server 7001.conf
*** FATAL CONFIG FILE ERROR ***
Reading the configuration file, at line 1381
>>> ‘replicaof 127.0.0.1 6379‘
replicaof directive not allowed in cluster mode

3.查看集群状态

192.168.213.129:6379> cluster info

相关推荐