一、Redis介绍
Redis是一个开源的使用C语言编写、开源、支持网络、可基于内存亦可持久化的日志型、高性能的key-value数据库,并提供多种语言的API。它通常被称为数据结构服务器,因为值(value)可以是字符串(string)、哈希(Map)、列表(List)、集合(sets)和有序集合(sorted sets)等类型。
(1)Redis和其他key-value缓存产品的特点
- Redis支持数据持久化,可以将内存中的数据写入磁盘中,重启之后可以再次加载进行使用。
- Redis不仅仅支持简单的key-value类型的数据,同时还提供list、set、zset、hash等数据结构的存储。
- Redis支持数据备份,即master-slave模式的数据备份。
(2)Redis的优势
- 性能极高。Redis的读速度大约为110000次/秒,写速度大约是8100次/秒。
- 丰富的数据类型。
- 原子性。Redis的所有操作都是原子行的,同时Redis还支持对几个操作合并之后的原子性执行(原子性是指事物的不可分割性,一个事务的所有操作要么不间断的全部被执行,要么一个也没有执行)
- 丰富的特性。Redis还支持发布/订阅通知,key过期等特性。
(3)Redis的一些介绍
互联网数据大多数是使用两种方式来存储的,关系数据库或key-value。但是关系数据库的存储对于互联网数据来说,都会产生一些冗余数据,会存储一些重复数据。key-value存储的修改和删除都比较麻烦,会导致所有的数据读出再写入。Redis在内存中设计了多种数据类型。让业务可以高速原子的访问这些数据结构。
Redis新版本增加了VM(虚拟内存)特性。VM特性就是暂时把不经常访问的数据(冷数据)从内存交换到磁盘中,从而将空间用于其他经常访问的数据(热数据)。通过VM实现冷热数据分离,使热数据保存到内存中,冷数据保存到磁盘中。这种方法使得Redis数据容量突破了物理内存的限制。
如果在没有实现VM特性的情况下,Redis的全部数据都要放置在内存中。如果一个key-value单元需要最小占用512个字节,即使只放入一个key-value也会占用512个字节;此时我们可以将key复用,几个key-value放入一个key中,value再作为一个数组放入,这样就会节省内存空间。
(4)Redis的存储方式
- RDB模式(默认方式) 【备份模式】
实现方式是定时将内存的快照持久化到磁盘,这种方式的缺点是持久化之后如果出现宕机则会丢失一段数据。原因:RDB是在某个时间点将数据写入一个临时文件,持久化结束后,用这个临时文件替换上次持久化的文件,达到数据恢复。
优点:使用单独子进程来进行持久化,主进程不会进行任何IO操作,保证了Redis的高性能。
缺点:RDB是间隔一段时间进行持久化,如果持久化之间redis发生故障,会发生数据丢失。
适用:数据要求不严谨的时候。
2. AOF模式【容灾模式】
AOF即append(追加) only file。该模式是在写入内存数据的同时将操作命令保存到日志文件,但在产生大型数据的系统中,命令日志会非常大,aof在这种系统中就失去了高可用的本意。
优点:AOF模式保证了数据的可靠性和高可用性,可以保持更高的数据完整性。
缺点:AOF文件比RDB文件大,且恢复速度较慢。
另一种达到容灾的方式:Replication。由于Redis复制基本上没有延迟,这样可以防止单点故障并实现高可用。(主从)
二、Redis的数据类型和Redis的应用场景
(1)Redis的数据类型
Redis支持五种数据类型:String(字符串),hash(哈希),set(集合),zset(有序集合),list(列表)。
1、String(字符串)
字符串是Redis最基础的数据类型。一个key对应一个vaule。value可以包含任何数据,包含图片或序列化对象。一个键最大能存储512MB。
序列化对象:序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
#添加一个key
1 127.0.0.1:6379> set var "String abc" #设置一个key(var)值(value)为(string abc)
2 OK
3 127.0.0.1:6379> get var #获取var的vaule
4 "String abc"
#redis中大小写敏感
127.0.0.1:6379> set name "redis"
OK
127.0.0.1:6379> get NAME
(nil)
127.0.0.1:6379> set NAME "REDIS"
OK
127.0.0.1:6379> get name
"redis"
127.0.0.1:6379> get NAME
"REDIS"
#设置自动过期时间
1 TTL #查看key的剩余生命周期
2 -1 #该选项代表key永不过期。重新对key赋值,之前有的生命周期会改变为永不过期
3 -2 #该选项代表key不存在。
4 num #出现数字代表剩余的生命周期
5
6 127.0.0.1:6379> set face wang EX 100 #设置face的生命周期为100秒
7 OK
8 127.0.0.1:6379> TTL face #查看face的生命周期
9 (integer) 89
10 127.0.0.1:6379> TTL face
11 (integer) 85
12 127.0.0.1:6379> set face zhang #修改face的值,生命周期改变为永不过期
13 OK
14 127.0.0.1:6379> TTL face
15 (integer) -1
16 127.0.0.1:6379> EXPIRE face 1000 #修改face的生命周期为1000秒
17 (integer) 1
18 127.0.0.1:6379> TTL face
19 (integer) 995
20 127.0.0.1:6379> PERSIST face #删除生命周期,设置为永不过期
21 (integer) 1
22 127.0.0.1:6379> TTL face
23 (integer) -1
#删除一个或多个key
1 127.0.0.1:6379> DEL face #删除一个key
2 (integer) 1
3 127.0.0.1:6379> get face
4 (nil)
5 127.0.0.1:6379> DEL face name #删除多个key
6 (integer) 2
7 127.0.0.1:6379> get face
8 (nil)
9 127.0.0.1:6379> get name
10 (nil)
#批量设置与获取key
1 127.0.0.1:6379> MSET key1 value1 key2 value2 key3 value3 #批量设置key
2 OK
3 127.0.0.1:6379> MGET key1 key2 key3 #批量获取key
4 1) "value1"
5 2) "value2"
6 3) "value3"
7 127.0.0.1:6379> KEYS n* #获取所有以n开头的key
8 1) "nc"
9 2) "na"
10 3) "nb"
11 127.0.0.1:6379> KEYS k* #获取所有以k开头的key
12 1) "key1"
13 2) "key3"
14 3) "key2"
15 127.0.0.1:6379> KEYS * #获取所有key
16 1) "key1"
17 2) "nc"
18 3) "na"
19 4) "bcd"
20 5) "key3"
21 6) "key2"
22 7) "var"
23 8) "nb"
24 9) "abc"
25 10) "NAME"
#追加数据与返回字符串长度
1 127.0.0.1:6379> get var
2 "String abc"
3 127.0.0.1:6379> APPEND var "append" #给key的value追加数据
4 (integer) 16
5 127.0.0.1:6379> get var
6 "String abcappend"
7 127.0.0.1:6379> STRLEN var #获取key的value的字符串长度
8 (integer) 16
9 127.0.0.1:6379> APPEND var "123456"
10 (integer) 22
11 127.0.0.1:6379> STRLEN var
12 (integer) 22
13 127.0.0.1:6379> get var
14 "String abcappend123456"
#数值递增与递减
1 127.0.0.1:6379> set num 10
2 OK
3 127.0.0.1:6379> INCR num #数值递增
4 (integer) 11
5 127.0.0.1:6379> get num
6 "11"
7 127.0.0.1:6379> STRLEN num
8 (integer) 2
9 127.0.0.1:6379> DECR num #数值递减
10 (integer) 10
11 127.0.0.1:6379> get num
12 "10"
#判断key是否存在
1 127.0.0.1:6379> keys *
2 1) "key1"
3 2) "nc"
4 3) "na"
5 4) "bcd"
6 5) "key3"
7 6) "key2"
8 7) "var"
9 8) "nb"
10 9) "abc"
11 10) "NAME"
12 11) "num"
13 127.0.0.1:6379> EXISTS NAME #判断是否存在
14 (integer) 1 (存在)
15 127.0.0.1:6379> EXISTS name
16 (integer) 0
2、哈希
hash是一个string类型的field和value的映射表,Redis中的每一个hash可以存储2^32-1键值对,类似于字典,存放了多个键值对,hash特别适合用于存储对象场景。
1 127.0.0.1:6379> HSET 9527 name zhouxingchi age 20 salary 5000000 #生成一个hash
2 (integer) 3
3 127.0.0.1:6379> HSET school teacher abc age 50 salary 5000 #生成一个hash
4 (integer) 3
5 127.0.0.1:6379> TYPE 9527 #查看这个key的类型
6 hash
7 127.0.0.1:6379> TYPE school
8 hash
9 127.0.0.1:6379> HGET 9527 age #查看hash中的某个key的值
10 "20"
11 127.0.0.1:6379> HGET 9527 name
12 "zhouxingchi"
13 127.0.0.1:6379> HGET school teacher
14 "abc"
15 127.0.0.1:6379> HMGET school teacher age salary #获取hash中多个值
16 1) "abc"
17 2) "50"
18 3) "5000"
19 127.0.0.1:6379> HDEL school teacher #删除hash中的某个key字段
20 (integer) 1
21 127.0.0.1:6379> HGET school teacher
22 (nil)
23 127.0.0.1:6379> HMSET school teacher zhangbs age 24 salary 90000 #重新设置一个hash中的值
24 OK
25 127.0.0.1:6379> HKEYS school #获取某一个hash中的所有key
26 1) "age"
27 2) "salary"
28 3) "teacher"
29 127.0.0.1:6379> HGETALL school #获取指定hash中的所有key和value
30 1) "age"
31 2) "24"
32 3) "salary"
33 4) "90000"
34 5) "teacher"
35 6) "zhangbs"
36 127.0.0.1:6379> DEL school #删除一个hash
37 (integer) 1
38 127.0.0.1:6379> HMGET school name
39 1) (nil)
40 127.0.0.1:6379> EXISTS school #hash以及不存在
41 (integer) 0
3、集合
set是string类型的无序集合,集合中的成员是唯一的,这就意味着集合中不能出现重复的数据,可以在两个不同的集合中对数据进行对比并取值,常用于取值判断,统计,交集等场景。
1 127.0.0.1:6379> SADD set1 v1 #创建一个集合,里面元素有v1
2 (integer) 1
3 127.0.0.1:6379> SADD set2 v2 v4 #创建一个集合,里面元素有v2 v4
4 (integer) 2
5 127.0.0.1:6379> SADD set1 v2 v3 v4 #往集合set1中添加元素
6 (integer) 3
7 127.0.0.1:6379> SADD set2 v2 v6 #往集合set2中添加元素,但只添加成功一个,因为集合中元素不能重复
8 (integer) 1
9 #查询集合中的所有元素
10 127.0.0.1:6379> SMEMBERS set1
11 1) "v1"
12 2) "v2"
13 3) "v4"
14 4) "v3"
15 127.0.0.1:6379> SMEMBERS set2
16 1) "v2"
17 2) "v6"
18 3) "v4"
19 #求set1和set2的交集
20 127.0.0.1:6379> SINTER set1 set2
21 1) "v2"
22 2) "v4"
23 #求set1和set2的并集
24 127.0.0.1:6379> SUNION set1 set2
25 1) "v3"
26 2) "v4"
27 3) "v2"
28 4) "v6"
29 5) "v1"
30 ##求set1和set2的差集
31 127.0.0.1:6379> SDIFF set1 set2
32 1) "v1"
33 2) "v3"
4、有序集合
Redis有序集合和集合一样也是string类型的元素的集合,且不允许有重复的成员,不同的是每个元素都会关联一个double(双精度浮点型)类型的分数,Redis通过该分数来为集合中的成员进行从小到大的排序,有序集合的成员是唯一的,但是分数是可以重复的,集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1),集合中最大的成员数为2^32-1(大概四亿多),经常用于排行榜的场景。
1 #生成有序集合
2 127.0.0.1:6379> ZADD zset01 1 chu #分数为一
3 (integer) 1
4 127.0.0.1:6379> ZADD zset01 2 ye
5 (integer) 1
6 127.0.0.1:6379> ZADD zset01 3 zhang
7 (integer) 1
8 127.0.0.1:6379> ZADD zset01 2 wu
9 (integer) 1
10 127.0.0.1:6379> ZADD zset01 3 wu #分数可以重复,但是元素值不可以重复
11 (integer) 0
12 #创建一个例子
13 127.0.0.1:6379> ZADD paihangbang 90 neizha 100 anqila 110 change 120 diaochan 130 daji #创建一个有序集合
14 (integer) 5
15 127.0.0.1:6379> ZRANGE paihangbang 0 -1 #正序排序后显示所有的key
16 1) "neizha"
17 2) "anqila"
18 3) "change"
19 4) "diaochan"
20 5) "daji"
21 127.0.0.1:6379> ZREVRANGE paihangbang 0 -1 #倒序排序后显示所有的key
22 1) "daji"
23 2) "diaochan"
24 3) "change"
25 4) "anqila"
26 5) "neizha"
27 127.0.0.1:6379> ZRANGE paihangbang 0 -1 WITHSCORES #正序显示多有的key和分数
28 1) "neizha"
29 2) "90"
30 3) "anqila"
31 4) "100"
32 5) "change"
33 6) "110"
34 7) "diaochan"
35 8) "120"
36 9) "daji"
37 10) "130"
38 127.0.0.1:6379> ZREVRANGE paihangbang 0 -1 WITHSCORES #倒序显示多有的key和分数
39 1) "daji"
40 2) "130"
41 3) "diaochan"
42 4) "120"
43 5) "change"
44 6) "110"
45 7) "anqila"
46 8) "100"
47 9) "neizha"
48 10) "90"
49
50 #获取该有序集合的长度
51 127.0.0.1:6379> ZCARD paihangbang
52 (integer) 5
53 127.0.0.1:6379> ZCARD zset01
54 (integer) 4
55
56
57 #根据索引获取key或根据key获取索引
58 127.0.0.1:6379> ZRANGE paihangbang 0 2 #获取索引为0~2的所有key
59 1) "neizha"
60 2) "anqila"
61 3) "change"
62 127.0.0.1:6379> ZRANGE paihangbang 0 10 #获取索引为0~10的所有key,超出范围不报错
63 1) "neizha"
64 2) "anqila"
65 3) "change"
66 4) "diaochan"
67 5) "daji"
68 127.0.0.1:6379> ZRANGE paihangbang 2 2
69 1) "change"
70 127.0.0.1:6379> ZRANK paihangbang change #获取key为change的索引
71 (integer) 2
72 127.0.0.1:6379> ZRANK paihangbang neuzha #key不存在
73 (nil)
5、列表
列表是一个双向可读写管道,其头部是左侧,尾部为右侧,一个列表最多可含2^32-1个元素。下标1表示第一个元素,下标2表示第二个元素,依此类推;下标-1表示倒数第一个元素,下标-2表示倒数第二个元素。元素值可以重复,常用于存入日志等场景。
#一个例子
127.0.0.1:6379> LPUSH list01 jack tom jhon Lucille #创建了一个列表
(integer) 4
127.0.0.1:6379> TYPE list01 #查看类型
list
127.0.0.1:6379> LRANGE list01 0 -1 #查看该列表的所有元素
1) "Lucille"
2) "jhon"
3) "tom"
4) "jack"
#新添加一个元素
1 127.0.0.1:6379> LPUSH list01 sunce #在原有列表中插入一个新元素
2 (integer) 5
3 127.0.0.1:6379> LRANGE list01 0 -1
4 1) "sunce"
5 2) "Lucille"
6 3) "jhon"
7 4) "tom"
8 5) "jack"
#获取列表长度
127.0.0.1:6379> LLen list01
(integer) 5
127.0.0.1:6379> LRANGE list01 0 -1
1) "sunce"
2) "Lucille"
3) "jhon"
4) "tom"
5) "jack"
#获取指定列表的某个值
127.0.0.1:6379> LINDEX list01 0
"sunce"
127.0.0.1:6379> LINDEX list01 -1
"jack"
#获取列表某个范围的值
127.0.0.1:6379> LRANGE list01 0 2
1) "sunce"
2) "Lucille"
3) "jhon"
127.0.0.1:6379> LRANGE list01 2 2
1) "jhon"
#移除列表与列表数据
1 127.0.0.1:6379> LRANGE abcd 0 -1 #查询列表abcd中的所有值
2 1) "d"
3 2) "c"
4 3) "b"
5 4) "a"
6 127.0.0.1:6379> LPOP abcd #删除第一个元素,即最左边的元素 序号为0的元素
7 "d"
8 127.0.0.1:6379> LRANGE abcd 0 -1
9 1) "c"
10 2) "b"
11 3) "a"
12 127.0.0.1:6379> RPOP abcd #删除最后一个元素 即最右边的元素
13 "a"
14 127.0.0.1:6379> LRANGE abcd 0 -1
15 1) "c"
16 2) "b"
17 127.0.0.1:6379>
18 127.0.0.1:6379> LPUSH list a b c d e f
19 (integer) 6
20 127.0.0.1:6379> LRANGE list 0 -1
21 1) "f"
22 2) "e"
23 3) "d"
24 4) "c"
25 5) "b"
26 6) "a"
27 127.0.0.1:6379> LTRIM list 1 2 #对列表进行修剪,不在指定区间的元素都被删除
28 OK
29 127.0.0.1:6379> LRANGE list 0 -1
30 1) "e"
31 2) "d"
32 127.0.0.1:6379>
33 127.0.0.1:6379> DEL list #删除列表
34 (integer) 1
35 127.0.0.1:6379> EXISTS list
36 (integer) 0
(2)Redis的应用场景
Redis最大的作用是增大原本的访问性能。Redis的典型使用场景:
- 缓存系统。Redis可以替代memcache,让缓存只能存储数据变得能够更新数据,因此我们不需要每次都重新生成数据。
- 计数器和排行榜等相关问题。计数器使用原子递增,就可以实现各种计数;GETSET可以重置计数器,或者过期属性。排行榜使用有序集合根据分数进行排序。
- 消息队列系统。简单的消息队列系统可以使用Redis,它支持模式匹配,能够实施订阅与取消频道。
- 社交网络。Redis可以很好的和社交网络进行结合,例如Redis就可以实现一些交互,例如实时聊天。
- 过期项目处理。通过UNIX时间作为关键字,用来保持列表能够按时间排序。
- 实时系统。使用位图来做布隆过滤器,例如:垃圾邮件过滤系统。
二、Redis持久化
Redis需要经常将内存中的数据同步到磁盘来保证持久化。Redis支持四种持久化方式。一种是RDB、另一种是AOF、还有一个是虚拟内存方式(该方式已被丢弃。)、最后一个是diskstore方式。
(1)RDB
RDB即快照是默认的持久化方式。这种方式就是将内存中的数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。可以通过设置自动做快照持久化的方式。我们可以配置redis在n秒内如果超过m个key被修改就自动做快照,配置文件为redis.conf 。
#如下是默认的快照保存设置
save 900 1 #900秒之内如果有一个key被修改,就发起快照保存
save 300 10 #300秒内如果有10个key被修改,就发起快照保存
save 60 10000 #60秒内如果有10000个key被修改,就发起快照保存
快照保存过程:
client请求也可以使用save或者bgsave命令通知redis做一次快照持久化。save操作是在线程中保存快照的,由于redis是用一个主线程来处理所有的client请求的,这种方式会阻塞所有的client请求,一般情况下不推荐使用。
另一个,每次快照持久化都是讲内存数据完整的写入到磁盘一次,并不是增量的。所以,如果数据量较大且写操作比较多的话,会引起大量的I/O操作,可能会严重影响性能。
由于快照方式的持久化是间隔一段时间进行一次,所以在间隔时间内,Redis因为意外宕机的话,就会丢失一部分数据。
(2)AOF
AOF持久化是将每一个收到的写命令都通过write函数追加到文件中(默认是appendonly.aof)。当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内存。
当然,由于OS会在内核中缓存write做的修改,所以可能不是立即写到磁盘上。这样AOF方式的持久化也可能会导致部分丢失。不过我们可以在配置文件中配置redis我们想要通过fsync函数强制os写入到磁盘的时机,如下:
appendonly no #是否启动aof持久化方式
# appendfsync always #每次收到写命令就立即强制写入磁盘,最慢的,但是可以保证完全的持久化,不推荐使用
appendfsync everysec #每秒总强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐使用
# appendfsync no #完全依赖os,性能最好,持久化没保证
AOF的方式也同时带来了另一个问题。持久化文件会变得越来越大。例如,如果我们调用了一个函数一百次,文件中就保存了100条命令,但其中99条就是多余的。因为要恢复数据库的状态其实文件中保存一条 “set 函数 100”就可以了。为了压缩aof的持久化文件,redis提供了bgrewriteaof命令,收到这个命令redis将使用与快照类似的方式将内存中的数据以命令的方式保存到临时文件中,最后替换原来的文件。
具体过程如下:
以上的aof文件重写的操作中,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件。
(3)数据持久化对比
RDB持久化 |
AOF持久化 | |
描述 | 默认的持久化方式。实现方法:每隔一段时间将内存的快照持久化到磁盘。 | 实现方式:在写入内存数据的同时将命令保存到一个临时文件。 |
优点 | 使用单独的子进程来进行持久化,主进程不会进行i/o操作,保证redis的性能。 | 保证了数据的可靠性和高可用性,保证更高的数据完整性。 |
缺点 | 间隔一段时间导致可能会导致数据丢失,在间隔时间中Redis宕机。 | 在并发较高的系统中,命令日志会很大,恢复时间较长;文件必RDB大很多。 |
适用场景 | 适合对数据要求不严谨的场景。 | 适合对数据完整性较高的场景。 |
(4)diskstore方式
diskstore方式是放弃了虚拟内存方式之后选择的一种新的实现方式。具体细节:
1、读操作。使用read through以及LRU方式。内存中不存在的数据从磁盘拉取并放入内存,内存中放不下的数据采用LRU(最近最少使用)淘汰。
2、写操作。采用另外的spawn一个线程单独处理,写线程通常是异步的(推荐)。当然也可以把cache-flush-delay配置为0,Redis尽量保证即使写入(这个方式可能会导致调用方卡住。以上选项设置为0,多个client需要排队等候,如果队列容量超过cache-max-memory,就会导致调用发卡住。)。
RDB可以和diskstore转换。通过BGSAVE可以随时将diskstore格式另存为rdb格式,而且rdb格式还用于Redis复制以及不同存储方式之间的中间格式。通过工具可以将rdb格式转化成diskstore格式。
三、Redis安装配置及运用
(1)安装
1、编译安装
#安装
[root@redis ~]# yum install gcc gcc-c++ make -y
[root@redis ~]# wget http://download.redis.io/releases/redis-5.0.4.tar.gz
[root@redis ~]# tar xf redis-5.0.4.tar.gz
[root@redis ~]# cd redis-5.0.4
[root@redis redis-5.0.4]# make
[root@redis redis-5.0.4]# echo $?
0
[root@redis redis-5.0.4]# mkdir -p /data/redis
[root@redis redis-5.0.4]# make PREFIX=/data/redis install
[root@redis redis-5.0.4]# echo $?
0
[root@redis redis-5.0.4]# mkdir /data/redis/conf
[root@redis redis-5.0.4]# cp redis.conf /data/redis/conf/
#启动redis
[root@redis redis-5.0.4]# /data/redis/bin/redis-server /data/redis/conf/redis.conf
12040:C 29 Dec 2021 21:45:31.021 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
12040:C 29 Dec 2021 21:45:31.021 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=12040, just started
12040:C 29 Dec 2021 21:45:31.021 # Configuration loaded
12040:M 29 Dec 2021 21:45:31.022 * Increased maximum number of open files to 10032 (it was originally set to 1024).
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 5.0.4 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in standalone mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
| `-._ `._ / _.-' | PID: 12040
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
#此时已启动,但如果需要在其上进行什么操作,可以重新启动一个终端。 #在后台启动
[root@redis redis-5.0.4]# /data/redis/bin/redis-server /data/redis/conf/redis.conf &
[1] 12044
12044:C 29 Dec 2021 21:47:00.969 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
12044:C 29 Dec 2021 21:47:00.969 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=12044, just started
12044:C 29 Dec 2021 21:47:00.969 # Configuration loaded
12044:M 29 Dec 2021 21:47:00.970 * Increased maximum number of open files to 10032 (it was originally set to 1024).
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 5.0.4 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in standalone mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
| `-._ `._ / _.-' | PID: 12044
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-' 12044:M 29 Dec 2021 21:47:00.970 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
12044:M 29 Dec 2021 21:47:00.970 # Server initialized
12044:M 29 Dec 2021 21:47:00.970 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
12044:M 29 Dec 2021 21:47:00.971 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_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 disabled.
12044:M 29 Dec 2021 21:47:00.971 * DB loaded from disk: 0.000 seconds
12044:M 29 Dec 2021 21:47:00.971 * Ready to accept connections
[root@redis redis-5.0.4]# #关闭redis
[root@redis redis-5.0.4]# /data/redis/bin/redis-cli shutdown
12044:M 29 Dec 2021 21:47:37.787 # User requested shutdown...
12044:M 29 Dec 2021 21:47:37.787 * Saving the final RDB snapshot before exiting.
12044:M 29 Dec 2021 21:47:37.811 * DB saved on disk
12044:M 29 Dec 2021 21:47:37.811 * Removing the pid file.
12044:M 29 Dec 2021 21:47:37.812 # Redis is now ready to exit, bye bye...
[1]+ 完成 /data/redis/bin/redis-server /data/redis/conf/redis.conf
2、yum安装
#安装
yum install epel-release -y #下载fedora的epel
yum install redis #下载redis
#启动等
#启动redis服务
systemctl start redis
#设置开启自启动
systemctl enable redis
#配置文件的地址
cat /etc/redis.conf
(2)调优
redis启动界面有几个警告:
12073:M 29 Dec 2021 21:59:03.066 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
(backlog参数控制的是三次握手的时候server端收到client 确认号之后的队列值,即全连接队列)
修改方法:vim /etc/sysctl.conf 添加 net.core.somaxconn=1024
net.core.somaxconn 该选项表示socket监听的backlog上限,backlog就是socket的监听队列,当一个请求尚未被处理或者建立时,他会进入backlog。net.core.somaxconn该选项的默认值为128
12073:M 29 Dec 2021 21:59:03.066 # Server initialized
12073:M 29 Dec 2021 21:59:03.066 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.0:表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
1:表示内核允许分配所有的物理内存,而不管当前的内存状态如何
2:表示内核允许分配超过所有物理内存和交换空间总和的内存
解决:vim /etc/sysctl.conf 添加 vm.overcommit_memory = 1
vm.overcommit_memory 是一种内核堆内存分配的策略。
12073:M 29 Dec 2021 21:59:03.066 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_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 disabled.警告:内核中启用了透明大页面(THP)支持。这将造成Redis的延迟和内存使用问题。要解决此问题,请以root用户身份运行命令'echo never>/sys/kernel/mm/transparent\u hugepage/enabled',并将其添加到/etc/rc。本地,以便在重新启动后保留设置。禁用THP后,必须重新启动Redis。
解决方式:
[root@redis ~]# cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never
[root@redis ~]# echo never > /sys/kernel/mm/transparent_hugepage/enabled
[root@redis ~]# cat /sys/kernel/mm/transparent_hugepage/enabled
always madvise [never][root@redis ~]# cat /etc/rc.d/rc.local
#!/bin/bash
# THIS FILE IS ADDED FOR COMPATIBILITY PURPOSES
#
# It is highly advisable to create own systemd services or udev rules
# to run scripts during boot instead of using this file.
#
# In contrast to previous versions due to parallel execution during boot
# this script will NOT be run after all other services.
#
# Please note that you must run 'chmod +x /etc/rc.d/rc.local' to ensure
# that this script will be executed during boot.touch /var/lock/subsys/local
echo never > /sys/kernel/mm/transparent_hugepage/enabled
[root@redis ~]# chmod +x /etc/rc.d/rc.local12073:M 29 Dec 2021 21:59:03.066 * Ready to accept connections
调优完成
(3)连接到Redis
1、人员连接
本机非密码连接
redis-cli
跨主机非密码连接
redis-cli -h hostname/IP -p port
跨主机密码连接
redis-cli -h hostname/IP -p port -a PASWORD
2、程序连接
shell脚本写入数据到Redis
[root@redis ~]# cat redis.sh
#!bin/bash
NUM=10
for((i=1;i<=$NUM;i++));do
echo $i;
/data/redis/bin/redis-cli -h 127.0.0.1 -p 6379 set 这是第${i}条数据 这条数据的内容为${i}
done;
python连接方式
#以LINUX系统 centos版本中使用python3连接为例 #准备工作(安装python3和redis-py)
[root@localhost ~]# yum install python3 -y
[root@localhost ~]# wget https://github.com/andymccurdy/redis-py/archive/master.zip #安装redis-py
[root@localhost ~]# unzip master.zip
[root@localhost ~]# cd redis-py-master/
[root@localhost redis-py-master]# python3 setup.py install #验证
[root@localhost redis-py-master]# python3
Python 3.6.8 (default, Nov 16 2020, 16:55:22)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import redis
>>> r = redis.StrictRedis(host='127.0.0.1',port=6379,password='123456');
>>> r.set('name','Lucille');
True
>>> r.get('name');
b'Lucille' #普通连接
注:该方法的redis.py必须放置在redis-py-master文件夹下
[root@localhost redis-py-master]# cat redis.py
import redis
r = redis.Redis(host='192.168.10.12',port=6379,password='123456')
r.set('name01','zhnagbs')
print(r.get('name01'))
[root@localhost redis-py-master]# python3.6 redis.py
b'zhnagbs' #连接池连接
[root@localhost redis-py-master]# cat redispool.py
import redis pool = redis.ConnectionPool(host='192.168.10.12',port=6379,password='123456')
r = redis.Redis(connection_pool=pool)
r.set('salary','value0000')
date=r.get('salary')
print(date) r.set('food','noodles',ex=3) #设置过期时间为秒
food=r.get('food')
print(food) r.set('abc','123',px=300) #设置过期时间为毫秒
food=r.get('food')
print(food) print((r.set('fruit','poor',nx=True))) #当name不存在时,当前set执行(新建)。 如果fruit不存在,输出True;如果fruit存在,输出None。 print((r.set('fruit','poor',xx=True))) #当name存在时,当前set执行(修改)。 如果fruit已经存在,输出True;如果fruit不存在,输出None。
(4)安全性设置
#修改Redis的登录密码
1 vim /etc/redis.conf
2 #bind 127.0.0.1 注释掉,否则只有本机可登录
3 protected-mode no #保护模式关闭
4 port 6379 #设置端口
5 requirepass 123456 #设置密码
6 重启
#连接
[root@localhost ~]# redis-cli
127.0.0.1:6379> info
NOAUTH Authentication required.
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> info
# Server
redis_version:3.2.12
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:7897e7d0e13773f
redis_mode:standalone
os:Linux 3.10.0-957.el7.x86_64 x86_64
arch_bits:64
multiplexing_api:epoll
…………
(5)Redis的常用命令详解
1、config
config命令用于查看当前的redis配置、以及在不重启Redis的情况下,动态更改Redis配置
#更改最大内存
127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "0"
127.0.0.1:6379> CONFIG SET maxmemory 8589934592
OK
127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "8589934592" #设置连接密码
127.0.0.1:6379> CONFIG GET requirepass
1) "requirepass"
2) "654321"
127.0.0.1:6379> CONFIG SET requirepass 123456
OK
127.0.0.1:6379> CONFIG GET requirepass
1) "requirepass"
2) "123456" #获取当前配置
127.0.0.1:6379> CONFIG GET *
1) "dbfilename"
2) "dump.rdb"
3) "requirepass"
4) "123456"
5) "masterauth"
6) ""
7) "unixsocket"
8) ""
9) "logfile"
…………
2、INFO
info命令用来显示节点redis运行状态信息。
127.0.0.1:6379> INFO
# Server
redis_version:3.2.12
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:7897e7d0e13773f
redis_mode:standalone
os:Linux 3.10.0-957.el7.x86_64 x86_64
arch_bits:64
multiplexing_api:epoll
gcc_version:4.8.5
process_id:8829
run_id:72db7986094df4763a54bd99a24fc6aa2048ab4f
tcp_port:6379
uptime_in_seconds:16123
uptime_in_days:0
hz:10
lru_clock:13411656
executable:/usr/bin/redis-server
config_file:/etc/redis.conf
…………
3、SELECT
切换数据库,等同于MYSQL的use databasename指令。
127.0.0.1:6379[1]> select 0
OK
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> select 16 #Redis的默认数据库为15个
(error) ERR invalid DB index
4、KEYS
keys命令用于查看当前库下的所有key,此命令在测试环境,以及key数量较少的环境下使用。如果在生产环境或数据量较大的环境中,该命令会导致redis锁住,CPU飙升。
127.0.0.1:6379> keys *
1) "name"
2) "salary"
3) "name01"
5、BGSAVE
bgsave该命令表示在后台执行RDB持久化操作。
[root@localhost ~]# ll /var/lib/redis/dump.rdb
-rw-r--r--. 1 redis redis 130 12月 29 22:53 /var/lib/redis/dump.rdb
[root@localhost ~]# redis-cli -h 127.0.0.1 -a '123456' BGSAVE
Background saving started
[root@localhost ~]# ll /var/lib/redis/dump.rdb
-rw-r--r--. 1 redis redis 130 1月 13 17:53 /var/lib/redis/dump.rdb
6、DBSIZE
该命令用于返回库中的所有key的数量
127.0.0.1:6379> DBSIZE
(integer) 3
127.0.0.1:6379> keys *
1) "name"
2) "salary"
3) "name01"
127.0.0.1:6379> SELECT 1
OK
127.0.0.1:6379[1]> DBSIZE
(integer) 0
127.0.0.1:6379[1]> keys *
(empty list or set)
7、FLUSHDB
该命令用于清除当前库的所有key
127.0.0.1:6379[1]> SELECT 2 #切换到一个辛苦
OK
127.0.0.1:6379[2]> mset key1 values key2 values2 key3 abc key4 567 #批量创建字符串
OK
127.0.0.1:6379[2]> DBSIZE #查看该库有几个key
(integer) 4
127.0.0.1:6379[2]> KEYS *
1) "key3"
2) "key2"
3) "key4"
4) "key1"
127.0.0.1:6379[2]> FLUSHDB
OK
127.0.0.1:6379[2]> KEYS *
(empty list or set)
8、FLUSHALL
该命令用于强制删除整个redis服务器中所有数据库中的所有key,即删除所有数据。
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> KEYS *
(empty list or set)
(6)配置详解
配置文件 使用yum安装是在/etc/redis.conf 使用其他安装方式可以使用“find / -name redis.conf”命令来查询
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
daemonize no
默认情况下,Redis不是作为守护进程运行的,如果需要放在后台运行,就可以把它改为yes #bind 127.0.0.1(如果需要异地连接,这个选项需要注释掉)
监听地址,可以用空格隔开后多个监听 #protected-mode no
该选项时redis3.2版本之后的特性,设置为no,外部网络可以直接访问;设置为yes,需配置bind访问地址和访问密码。 #port 6379
该选项是设置监听端口 #tcp-backlog 511
该选项是三次握手的时候server端收到client的确认号之后的队列值,即全队列长度。 #timeout 0
客户端和Redis服务端的连接超时时间,默认为0,表示永不超时。 #tcp-keepalive 300
TCP会话保持时间。 pidfile /var/run/redis_6379.pid
pid文件路径 databases 16
#设置默认的数据库数量 stop-writes-on-bgsave-error yes
yes时因空间满等原因快照无法保存出错时,禁止redis写入操作。
rdbcompression yes
持久化到RDB文件时,是否压缩。
rdbchecksum yes
是否对备份文件开启RC64校验
dbfilename dump.rdb
持久化快照的文件名
dir /var/lib/redis 快照的保存路径
slave-serve-stale-data yes #当主库同从库失去连接或复制正在进行,从库的两种运行方式:
yes:从库会继续响应客户客户端的读请求。
no: 除去指定的命令之外都会返回错误“SYNC with master in progress”
slave-read-only yes 是否设置从库只读,设置为no,主从同步时从库可能会覆盖数据,造成数据丢失。
repl-diskless-sync no #是否使用socket方式复制数据(无盘同步),新salve连接时需要做数据的全量同步,需要从内存dump出新的RDB文件,然后从master传到slave,传输方式:
no:master新建一个进程dump生成RDB磁盘文件,RDB完成之后由父进程(主进程)将RDB文件发送给SLAVE。
yes:master创建一个新进程直接dump RDB文件到slave的网络socket,不经过主进程和硬盘。
repl-diskless-sync-delay 5 diskless时复制的服务器等待的延迟时间,设置0为关闭。
在延迟时间内到达的客户端,会一起通过diskless方式同步数据,但是复制开始之后,master节点就不接受slave的复制请求,直到下一次同步开始才重新接受复制请求。
四、核心组件
(1)复制
(2)发布订阅
Redis发布订阅是一种消息通信模式,发送者(pub)发送信息,订阅者(sub)接受信息。
Redis客户端可以订阅任意数量的频道。
例子:
一、创建订阅频道
[root@localhost ~]# redis-cli
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> subscribe redisChat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
3) (integer) 1 二、打开客户端,订阅频道
[root@localhost ~]# redis-cli -h 192.168.10.11 -p 6379 -a "123456"
192.168.10.11:6379> psubscribe redisChat
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "redisChat"
3) (integer) 1 三、推送
127.0.0.1:6379> publish redisChat "hello"
(integer) 3
127.0.0.1:6379> publish redisChat "litter chu"
(integer) 3 四、结果
[root@localhost ~]# redis-cli -h 192.168.10.11 -p 6379 -a "123456"
192.168.10.11:6379> psubscribe redisChat
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "redisChat"
3) (integer) 1
1) "pmessage"
2) "redisChat"
3) "redisChat"
4) "hello"
1) "pmessage"
2) "redisChat"
3) "redisChat"
4) "litter chu"
推送的原理:
当客户端向某个频道发送消息时,Redis首先在结构体redisServer中的pubsub_channels中找出键为该频道的结点,遍历该结点的值,找出所有的客户端,将消息发送给这些客户端。然后,遍历结构体Redis Client中的pubsub_patterns,找出包含该频道的模式的结点,将消息发送给订阅了该模式的客户端。
创建订阅频道的原理:
首先,在客户端结构体client中,有一个属性为pubsub_channels,该属性表明了该客户端订阅的所有频道,它是一个字典类型,通过哈希表实现,其中的每个元素都包含了一个键值对以及指向下一个元素的指针,每次订阅都要向其中插入一个结点,键表示订阅的频道,值为空。然后,在表示服务器端的结构体redisServer中,也有一个属性为pubsub_channels,但此处它表示的是该服务器端中的所有频道以及订阅了这个频道的客户端,它也是一个字典类型,插入结点时,键表示频道,值则是订阅了这个频道的所有客户端组成的链表。最后Redis通知客户端其订阅成功。
(3)事务
事务可以保证多个操作同时执行成功。
127.0.0.1:6379> MULTi #标记事务开始
OK
127.0.0.1:6379> set name yang #多条命令按照顺序入队
QUEUED
127.0.0.1:6379> set people 123
QUEUED
127.0.0.1:6379> set abc 678
QUEUED
127.0.0.1:6379> PING
QUEUED
127.0.0.1:6379> EXEC #执行
1) OK
2) OK
3) OK
4) PONG
(0.71s)
在一个事务中,任何一个操作发生错误,所有操作都会回滚。
127.0.0.1:6379> Multi
OK
127.0.0.1:6379> set a 10
QUEUED
127.0.0.1:6379> INCR a
QUEUED
127.0.0.1:6379> INCR a 12
(error) ERR wrong number of arguments for 'incr' command
127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get a
(nil)
五、主从复制
1、描述
Redis的复制功能是支持多个数据库之间的数据同步。一类的主数据库(master),另一种是从数据库(slave),主数据库可以进行读写操作,当发生写数据时自动将数据同步到从数据库;然而从数据库一般是只读的,并接收主数据库同步过来的数据。一个主数据库可以由多个从数据库;而一个从数据库只能有一个主数据库。
通过Redis的复制功能可以很好的实现数据库的读写分离,提高服务器的负载能力,主数据库主要进行写操作,从数据库负责读操作。
2、原理
Redis的主从同步支持全量同步和增量同步。第一次同步必为全量同步。
(1)全量同步
全量同步流程图:
(2)增量同步
增量同步流程图:
3、配置
方法一(该方法在任何一方重启之后就会不复存在):
(1)主库操作
(2)从库操作
[root@slave ~]# redis-cli -a "123456"
127.0.0.1:6379> INFO replication
# Replication
role:master #依旧是master
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6379> set key1 v1-slave
OK
127.0.0.1:6379> get key1 #设置一个数据
"v1-slave"
127.0.0.1:6379> SLAVEOF 192.168.10.11 6379 #设置master服务器
OK
127.0.0.1:6379> CONFIG SET masterauth 123456 #设置master服务器的密码
OK
127.0.0.1:6379> INFO replication
# Replication
role:slave #此时已是从服务器
master_host:192.168.10.11
master_port:6379
master_link_status:up #且已启动
master_last_io_seconds_ago:10
master_sync_in_progress:0
slave_repl_offset:995
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6379> get key1 #此时的相同数据显示的值是主服务器的值。
"v1-master"
127.0.0.1:6379>
方法二(永久保存):
在slave的redis.conf中设置:
(3)观察日志
#master的日志
[root@master ~]# tail /var/log/redis/redis.log
8115:M 14 Jan 00:03:10.387 * Background saving terminated with success
8115:M 14 Jan 00:03:10.387 * Synchronization with slave 192.168.10.12:6379 succeeded
8115:M 14 Jan 00:15:10.245 * Slave 192.168.10.10:6379 asks for synchronization
8115:M 14 Jan 00:15:10.246 * Full resync requested by slave 192.168.10.10:6379
8115:M 14 Jan 00:15:10.246 * Starting BGSAVE for SYNC with target: disk
8115:M 14 Jan 00:15:10.304 * Background saving started by pid 8283
8283:C 14 Jan 00:15:10.425 * DB saved on disk
8283:C 14 Jan 00:15:10.426 * RDB: 4 MB of memory used by copy-on-write
8115:M 14 Jan 00:15:10.469 * Background saving terminated with success
8115:M 14 Jan 00:15:10.470 * Synchronization with slave 192.168.10.10:6379 succeeded #slave的日志
[root@slave ~]# tail /var/log/redis/redis.log
7257:S 14 Jan 00:15:10.187 * Connecting to MASTER 192.168.10.11:6379
7257:S 14 Jan 00:15:10.187 * MASTER <-> SLAVE sync started
7257:S 14 Jan 00:15:10.187 * Non blocking connect for SYNC fired the event.
7257:S 14 Jan 00:15:10.188 * Master replied to PING, replication can continue...
7257:S 14 Jan 00:15:10.189 * Partial resynchronization not possible (no cached master)
7257:S 14 Jan 00:15:10.254 * Full resync from master: 294e46b3ebccaf679b057d1c22fe2af3dd4ca4f3:981
7257:S 14 Jan 00:15:10.414 * MASTER <-> SLAVE sync: receiving 98 bytes from master
7257:S 14 Jan 00:15:10.414 * MASTER <-> SLAVE sync: Flushing old data
7257:S 14 Jan 00:15:10.414 * MASTER <-> SLAVE sync: Loading DB in memory
7257:S 14 Jan 00:15:10.415 * MASTER <-> SLAVE sync: Finished with success
六、哨兵模式
1、一个场景
一共有三台服务器,分别为192.168.10.10、192.168.10.11、192.168.10.12。在该场景中,192.168.10.10为主,其他两个机器为它的从。然后,192.168.10.10服务器宕掉了,将192.168.10.11提升为主,192.168.10.12指向新的主服务器。
目前情况:
主服务器
从服务器
修改过程:
①、停止192.168.10.10的redis服务。
②、192.168.10.11的操作 ③、192.168.10.12的操作
以上情况下,我们通过手动方式实现了一个故障的切换,但在日常使用中,我们没有办法在很短的时间内进行故障切换,可能会对业务造成损失。所以,需要一个方式自动进行切换,即哨兵模式。
2、哨兵模式
Sentinel进程适用于监控redis集群中Master主服务器工作的状态,在Master主服务器发生故障时,可以实现Master和Slave服务器的切换,保证系统的高可用。它被集成在Redis2.6+的版本中,稳定于2.8+之后的版本中。哨兵是一个分布式系统,可以在一个架构中运行多个哨兵进程。这些进程使用流言协议来接收关于Master主服务器是否下线的信息,并使用投票协议来决定是否执行自动故障迁移,以及选择哪个Slave作为新的Master。
(1)工作原理
每个哨兵进程会向其他哨兵、Master、Slave定时发送信息,以确定对方是否还“活”着。如果发现对方在指定配置时间(可配置)未给到回应,则认为对方已经下线,这个方法被称为”主观认为宕机“,简称SDOWN;当”哨兵群“中的多数哨兵(Sentinel)进程在对master主服务器做出SDOWN的判断,并且通过 SENTINEL is-master-down-by-addr命令互相交流之后,得出master server下线判断,这种办法叫做”客观宕机“,简称ODOWN。
通过一定的vote算法,从剩下的Slave服务器节点中,选一台提升未Master服务器节点,然后自动修改相关配置,并开启故障转移(failover)。Sentinel机制可以解决master和slave角色的自动切换问题。
(2)配置
初始设置:redis哨兵模式的前提是已经实现了一个master-slave的运行环境,从而实现一个一主两从基于哨兵的高可用redis架构。
配置哨兵模式:
[root@master etc]# vim redis-sentinel.conf
port 26379
dir /tmp
sentinel monitor mymaster 192.168.10.10 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
logfile /var/log/redis/sentinel.log
配置完成后,将该文件复制到另两个服务器(slave)
[root@master etc]# scp /etc/redis-sentinel.conf root@192.168.10.11:/etc
[root@master etc]# scp /etc/redis-sentinel.conf root@192.168.10.12:/etc
复制完成后,分别在两台机器上启动哨兵进程
[root@master etc]# systemctl restart redis-sentinel.service
[root@slave1 etc]# systemctl restart redis-sentinel.service
[root@slave1 etc]# systemctl restart redis-sentinel.service
启动之后又,查看
[root@master etc]# ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:26379 *:*
LISTEN 0 128 *:6379 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 :::26379 :::*
LISTEN 0 128 :::6379 :::*
LISTEN 0 128 :::22 :::*
LISTEN 0 100 ::1:25 :::*
[root@slave1 etc]# ps -ef | grep redis
redis 7845 1 0 12月29 ? 00:00:44 /usr/bin/redis-server *:6379
redis 7936 1 0 12月29 ? 00:00:45 /usr/bin/redis-sentinel *:26379 [sentinel]
root 17628 7677 4 00:13 pts/0 00:00:00 grep --color=auto redis
[root@slave2 etc]# ps -ef | grep redis
redis 7823 1 0 12月29 ? 00:00:44 /usr/bin/redis-server *:6379
redis 7902 1 0 12月29 ? 00:00:44 /usr/bin/redis-sentinel *:26379 [sentinel]
root 17594 7654 0 00:14 pts/0 00:00:00 grep --color=auto redis
至此配置完成!!
查看哨兵模式日志:
#查看哨兵日志:
[root@master etc]# tail -f /var/log/redis/sentinel.log #master日志
`-._ _.-'
`-.__.-' 7610:X 14 Jan 22:44:57.838 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
7610:X 14 Jan 22:44:57.873 # Sentinel ID is 0e531e0dc2f12a696905287c5a66ca8c2fbc091a
7610:X 14 Jan 22:44:57.873 # +monitor master mymaster 192.168.10.10 6379 quorum 1
7610:X 14 Jan 22:44:57.884 * +slave slave 192.168.10.11:6379 192.168.10.11 6379 @ mymaster 192.168.10.10 6379
7610:X 14 Jan 22:44:57.923 * +slave slave 192.168.10.12:6379 192.168.10.12 6379 @ mymaster 192.168.10.10 6379
7610:X 14 Jan 22:44:58.291 * +sentinel sentinel ff71c9c1fe12b5d8a0f321982e25b71af1a06b9e 192.168.10.11 26379 @ mymaster 192.168.10.10 6379
7610:X 14 Jan 22:44:58.855 * +sentinel sentinel 03708ce901a87a120f69909a041c346a1340a655 192.168.10.12 26379 @ mymaster 192.168.10.10 6379 [root@slave1 etc]# tail -f /var/log/redis/sentinel.log #slave1的日志
`-._ _.-'
`-.__.-' 7936:X 29 Dec 21:51:18.081 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
7936:X 29 Dec 21:51:18.205 # Sentinel ID is ff71c9c1fe12b5d8a0f321982e25b71af1a06b9e
7936:X 29 Dec 21:51:18.205 # +monitor master mymaster 192.168.10.10 6379 quorum 1
7936:X 29 Dec 21:51:18.234 * +slave slave 192.168.10.11:6379 192.168.10.11 6379 @ mymaster 192.168.10.10 6379
7936:X 29 Dec 21:51:18.235 * +slave slave 192.168.10.12:6379 192.168.10.12 6379 @ mymaster 192.168.10.10 6379
7936:X 29 Dec 21:51:18.405 * +sentinel sentinel 03708ce901a87a120f69909a041c346a1340a655 192.168.10.12 26379 @ mymaster 192.168.10.10 6379
7936:X 29 Dec 21:51:23.263 * +sentinel sentinel 0e531e0dc2f12a696905287c5a66ca8c2fbc091a 192.168.10.10 26379 @ mymaster 192.168.10.10 6379 [root@slave2 etc]# tail -f /var/log/redis/sentinel.log #slave2的日志
`-._ _.-'
`-.__.-' 7902:X 29 Dec 21:51:56.490 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
7902:X 29 Dec 21:51:56.530 # Sentinel ID is 03708ce901a87a120f69909a041c346a1340a655
7902:X 29 Dec 21:51:56.530 # +monitor master mymaster 192.168.10.10 6379 quorum 1
7902:X 29 Dec 21:51:56.724 * +slave slave 192.168.10.11:6379 192.168.10.11 6379 @ mymaster 192.168.10.10 6379
7902:X 29 Dec 21:51:56.765 * +slave slave 192.168.10.12:6379 192.168.10.12 6379 @ mymaster 192.168.10.10 6379
7902:X 29 Dec 21:52:10.070 * +sentinel sentinel ff71c9c1fe12b5d8a0f321982e25b71af1a06b9e 192.168.10.11 26379 @ mymaster 192.168.10.10 6379
7902:X 29 Dec 21:52:13.898 * +sentinel sentinel 0e531e0dc2f12a696905287c5a66ca8c2fbc091a 192.168.10.10 26379 @ mymaster 192.168.10.10 6379
验证哨兵模式:
#关闭master的redis服务
[root@master etc]# systemctl stop redis #查看slave1
[root@slave1 etc]# grep -vE "^$|^#" /etc/redis-sentinel.conf
protected-mode no
port 26379
dir "/tmp"
sentinel myid ff71c9c1fe12b5d8a0f321982e25b71af1a06b9e
sentinel monitor mymaster 192.168.10.11 6379 1
sentinel config-epoch mymaster 2
sentinel leader-epoch mymaster 2
logfile "/var/log/redis/sentinel.log"
supervised systemd
sentinel known-slave mymaster 192.168.10.10 6379
sentinel known-slave mymaster 192.168.10.12 6379
sentinel known-sentinel mymaster 192.168.10.12 26379 03708ce901a87a120f69909a041c346a1340a655
sentinel known-sentinel mymaster 192.168.10.10 26379 0e531e0dc2f12a696905287c5a66ca8c2fbc091a
sentinel current-epoch 2 #查看slave2
[root@slave2 etc]# grep -vE "^$|^#" /etc/redis-sentinel.conf
protected-mode no
port 26379
dir "/tmp"
sentinel myid 03708ce901a87a120f69909a041c346a1340a655
sentinel monitor mymaster 192.168.10.11 6379 1
sentinel config-epoch mymaster 2
sentinel leader-epoch mymaster 2
logfile "/var/log/redis/sentinel.log"
supervised systemd
sentinel known-slave mymaster 192.168.10.12 6379
sentinel known-slave mymaster 192.168.10.10 6379
sentinel known-sentinel mymaster 192.168.10.11 26379 ff71c9c1fe12b5d8a0f321982e25b71af1a06b9e
sentinel known-sentinel mymaster 192.168.10.10 26379 0e531e0dc2f12a696905287c5a66ca8c2fbc091a
sentinel current-epoch 2
哨兵模式配置成功!!
哨兵模式解决了redis的高可用问题,即当master故障后可以自动将slave提升为master,从而可以本宗衡redis服务的正常使用,但是无法解决redis的单机写入瓶颈问题,即单机redis写入性能受限于单机的内存大小、并发数量、网卡速率等因素。
七,集群
Redis3.0+的版本支持集群功能。用来解决master的写瓶颈等。
Redis集群是一个提供在多个Redis间节点的共享数据。它通过分区share来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下继续处理命令。
优势:自动分割数据到不同的节点上。整个集群的部分节点失败或者不可达的情况下能够继续处理命令。
特点:①、所有Redis节点使用(PING机制)互联。
②、集群中某个节点是否失效,是由整个集群中超过半数的节点监测都失效,才能算真正的失效。
③、客户端不需要proxy即可直接连接redis,应用程序需要写全部的redis服务器IP
④、redis集群把所有的redis node平均映射到0-16383个槽位上,读写需要到指定的redis node上进行操作,因此有多少个redis node相当于redis并发扩展了多少倍,每个redis node承担16284/N个槽位。
⑤、Redis集群预先分配16384个槽位,当需要在redis集群总写入一个key-value的时候,会使用CRC16(key) mod16384之后的值,决定将key写入值哪一个槽位而绝当写入哪个Redis节点上,从而解决单机瓶颈。
(1)Redis集群的数据分片
redis使用哈希槽,每个key通过CRC16校验后对16384去模来决定放置那个槽位,集群的每一个节点来负责一部分槽位。
例如当前集群有三个节点。
节点A:包含0-5500号hash槽。
节点B:包含5501-11000号hash槽。
节点A:包含11001-16384号hash槽。
数据到底放置在哪个槽上,数据hash运算除以16384取余。
(2)集群的主存服复制模型
redis并不能保证数据的强一致性,这意味着在实际中集群在特定条件下操作可能会对视一些数据,集群使用了异步复制的写操作过程。
(3)集群搭建
1、环境准备
三台机器,分别开启两个redis服务
192.168.10.10 端口:6379,6380
192.168.10.11 端口:6379,6380
192.168.10.12 端口:6379,6380
修改配置文件,配置文件如下(其他两个服务器的配置相同):
#一些默认操作
[root@localhost ~]# mkdir /data/redis/6380
[root@localhost ~]# cp /data/redis/conf/redis.conf /data/redis/6380/redis6380.conf #配置文件的操作
[root@localhost ~]# grep -vE "^$|^#" /data/redis/conf/redis.conf
protected-mode no
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no
supervised no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile "/data/redis/conf/redis.log"
databases 16
always-show-logo yes
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir ./
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
slave-lazy-flush no
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble no
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes
cluster-enabled yes
cluster-config-file nodes-6379.conf
[root@localhost ~]# grep -vE "^$|^#" /data/redis/6380/redis6380.conf
protected-mode no
port 6380
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no
supervised no
pidfile /var/run/redis_6380.pid
loglevel notice
logfile "/data/redis/6380/redis6380.log"
databases 16
always-show-logo yes
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir ./
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
slave-lazy-flush no
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble no
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes
cluster-enabled yes
cluster-config-file nodes-6380.conf
启动redis服务.
[root@localhost ~]# redis-server /data/redis/conf/redis.conf
[root@localhost ~]# redis-server /data/redis/6380/redis6380.conf
[root@localhost ~]# tail -f /data/redis/conf/redis.log==> /usr/local/redis/cluster/redis_7001.log <==
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-' 17449:M 19 Jan 14:21:39.532 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
17449:M 19 Jan 14:21:39.532 # Server started, Redis version 3.2.12
17449:M 19 Jan 14:21:39.532 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
17449:M 19 Jan 14:21:39.548 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_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 disabled.
17449:M 19 Jan 14:21:39.549 * The server is now ready to accept connections on port 7001
[root@localhost ~]# tail -f /data/redis/6380/redis6380.log
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-' 17453:M 19 Jan 14:21:42.850 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
17453:M 19 Jan 14:21:42.850 # Server started, Redis version 3.2.12
17453:M 19 Jan 14:21:42.850 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
17453:M 19 Jan 14:21:42.851 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_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 disabled.
17453:M 19 Jan 14:21:42.851 * The server is now ready to accept connections on port 7002
集群管理工具安装(redis5以下的版本)
低版本(redis4和redis3版本):需要安装集群管理工具redis-trib.rb。
[root@localhost ~]# find / -name redis-trib.rb
/opt/redis-4.0.9/src/redis-trib.rb
[root@localhost ~]# cp /opt/redis-4.0.9/src/redis-trib.rb /usr/bin/
[root@localhost ~]# redis-trib.rb (缺少ruby环境)
/usr/bin/env: ruby: 没有那个文件或目录 问题解决:
[root@localhost ~]# yum install gcc openssl-devel zlib-devel -y
[root@localhost ~]# wget https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.9.tar.gz
[root@localhost ~]# tar xf ruby-2.5.9.tar.gz
[root@localhost ~]# cd ruby-2.5.9
[root@localhost ruby-2.5.9]# ./configure
[root@localhost ruby-2.5.9]# make -j 2
[root@localhost ruby-2.5.9]# make install
[root@localhost ruby-2.5.9]# ruby -v
ruby 2.5.9p229 (2021-04-05 revision 67939) [x86_64-linux]
[root@localhost ruby-2.5.9]# gem install redis
Fetching: redis-4.5.1.gem (100%)
Successfully installed redis-4.5.1
Parsing documentation for redis-4.5.1
Installing ri documentation for redis-4.5.1
Done installing documentation for redis after 46 seconds
1 gem installed 成功
[root@localhost ruby-2.5.9]# redis-trib.rb
Usage: redis-trib <command> <options> <arguments ...> create host1:port1 ... hostN:portN
--replicas <arg>
check host:port
info host:port
fix host:port
--timeout <arg>
reshard host:port
--from <arg>
--to <arg>
--slots <arg>
--yes
--timeout <arg>
--pipeline <arg>
rebalance host:port
--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
--from <arg>
--copy
--replace
help (show this help) For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.
[root@localhost ruby-2.5.9]#
修改redis的登录密码
[root@localhost ~]# find / -name client.rb
/root/ruby-2.5.9/gems/xmlrpc-0.3.0/lib/xmlrpc/client.rb
/usr/local/lib/ruby/gems/2.5.0/gems/xmlrpc-0.3.0/lib/xmlrpc/client.rb
/usr/local/lib/ruby/gems/2.5.0/gems/redis-4.5.1/lib/redis/client.rb
[root@localhost ~]# vim /root/ruby-2.5.9/gems/xmlrpc-0.3.0/lib/xmlrpc/client.rb
def initialize(host=nil, path=nil, port=nil, proxy_host=nil, proxy_port=nil,
user=nil, use_ssl=nil, timeout=nil)#删除其中的password
确保三台服务器的六个redis都在运行
[root@localhost ~]# netstat -nltp | grep redis
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 7289/redis-server *
tcp 0 0 0.0.0.0:6380 0.0.0.0:* LISTEN 7293/redis-server *
tcp 0 0 0.0.0.0:16379 0.0.0.0:* LISTEN 7289/redis-server *
tcp 0 0 0.0.0.0:16380 0.0.0.0:* LISTEN 7293/redis-server *
tcp6 0 0 :::6379 :::* LISTEN 7289/redis-server *
tcp6 0 0 :::6380 :::* LISTEN 7293/redis-server *
tcp6 0 0 :::16379 :::* LISTEN 7289/redis-server *
tcp6 0 0 :::16380 :::* LISTEN 7293/redis-server *
2、创建集群
redis4以及以下版本
[root@localhost ~]# redis-trib.rb create --replicas 1 192.168.10.10:6379 192.168.10.10:6380 192.168.10.11:6379 192.168.10.11:6380 192.168.10.12:6379 192.168.10.12:6380
>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
192.168.10.10:6379
192.168.10.11:6379
192.168.10.12:6379
Adding replica 192.168.10.11:6380 to 192.168.10.10:6379
Adding replica 192.168.10.12:6380 to 192.168.10.11:6379
Adding replica 192.168.10.10:6380 to 192.168.10.12:6379
M: 7bcdba4859d10eae99e17d7d93efc7973af0d50c 192.168.10.10:6379
slots:0-5460 (5461 slots) master
S: 46dafd34daaa3f9c4092217098c0791331db96da 192.168.10.10:6380
replicates 7756a52a33dd9e99b19109bf4eaa461c8d079936
M: 4e468829617e1e62e764b3ab3e477ba5f99bdf16 192.168.10.11:6379
slots:5461-10922 (5462 slots) master
S: 39c3771e87184b5f27a596c23abc882dfa2bc02a 192.168.10.11:6380
replicates 7bcdba4859d10eae99e17d7d93efc7973af0d50c
M: 7756a52a33dd9e99b19109bf4eaa461c8d079936 192.168.10.12:6379
slots:10923-16383 (5461 slots) master
S: 3d0acde0db99b58ec0d1cfa0dfb5444a3056634f 192.168.10.12:6380
replicates 4e468829617e1e62e764b3ab3e477ba5f99bdf16
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.10.10:6379)
M: 7bcdba4859d10eae99e17d7d93efc7973af0d50c 192.168.10.10:6379
slots:0-5460 (5461 slots) master
1 additional replica(s)
M: 7756a52a33dd9e99b19109bf4eaa461c8d079936 192.168.10.12:6379
slots:10923-16383 (5461 slots) master
1 additional replica(s)
M: 4e468829617e1e62e764b3ab3e477ba5f99bdf16 192.168.10.11:6379
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: 39c3771e87184b5f27a596c23abc882dfa2bc02a 192.168.10.11:6380
slots: (0 slots) slave
replicates 7bcdba4859d10eae99e17d7d93efc7973af0d50c
S: 46dafd34daaa3f9c4092217098c0791331db96da 192.168.10.10:6380
slots: (0 slots) slave
replicates 7756a52a33dd9e99b19109bf4eaa461c8d079936
S: 3d0acde0db99b58ec0d1cfa0dfb5444a3056634f 192.168.10.12:6380
slots: (0 slots) slave
replicates 4e468829617e1e62e764b3ab3e477ba5f99bdf16
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.c
redis5及以上版本
redis-cli (-a 123456#如果有密码的话) --cluster create 192.168.10.10:6379 192.168.10.10:6380 192.168.10.11:6379 192.168.10.11:6380 192.168.10.12:6379 192.168.10.12:6380 --cluster-replicas 1
查看集群对应关系
[root@localhost ~]# cat /root/nodes-6379.conf
7756a52a33dd9e99b19109bf4eaa461c8d079936 192.168.10.12:6379@16379 master - 0 1643073510000 5 connected 10923-16383
4e468829617e1e62e764b3ab3e477ba5f99bdf16 192.168.10.11:6379@16379 master - 0 1643073510551 3 connected 5461-10922
39c3771e87184b5f27a596c23abc882dfa2bc02a 192.168.10.11:6380@16380 slave 7bcdba4859d10eae99e17d7d93efc7973af0d50c 0 1643073511566 4 connected
46dafd34daaa3f9c4092217098c0791331db96da 192.168.10.10:6380@16380 slave 7756a52a33dd9e99b19109bf4eaa461c8d079936 0 1643073511000 5 connected
3d0acde0db99b58ec0d1cfa0dfb5444a3056634f 192.168.10.12:6380@16380 slave 4e468829617e1e62e764b3ab3e477ba5f99bdf16 0 1643073509000 6 connected
7bcdba4859d10eae99e17d7d93efc7973af0d50c 192.168.10.10:6379@16379 myself,master - 0 1643073512000 1 connected 0-5460
vars currentEpoch 6 lastVoteEpoch 0
查看状态
[root@localhost ~]# redis-trib.rb info 192.168.10.10:6379
192.168.10.10:6379 (7bcdba48...) -> 0 keys | 5461 slots | 1 slaves.
192.168.10.12:6379 (7756a52a...) -> 0 keys | 5461 slots | 1 slaves.
192.168.10.11:6379 (4e468829...) -> 0 keys | 5462 slots | 1 slaves.
[OK] 0 keys in 3 masters.
0.00 keys per slot on average. [root@localhost ~]# redis-trib.rb check 192.168.10.10:6379
>>> Performing Cluster Check (using node 192.168.10.10:6379)
M: 7bcdba4859d10eae99e17d7d93efc7973af0d50c 192.168.10.10:6379
slots:0-5460 (5461 slots) master
1 additional replica(s)
M: 7756a52a33dd9e99b19109bf4eaa461c8d079936 192.168.10.12:6379
slots:10923-16383 (5461 slots) master
1 additional replica(s)
M: 4e468829617e1e62e764b3ab3e477ba5f99bdf16 192.168.10.11:6379
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: 39c3771e87184b5f27a596c23abc882dfa2bc02a 192.168.10.11:6380
slots: (0 slots) slave
replicates 7bcdba4859d10eae99e17d7d93efc7973af0d50c
S: 46dafd34daaa3f9c4092217098c0791331db96da 192.168.10.10:6380
slots: (0 slots) slave
replicates 7756a52a33dd9e99b19109bf4eaa461c8d079936
S: 3d0acde0db99b58ec0d1cfa0dfb5444a3056634f 192.168.10.12:6380
slots: (0 slots) slave
replicates 4e468829617e1e62e764b3ab3e477ba5f99bdf16
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
[root@localhost ~]# [root@localhost ~]# redis-cli
127.0.0.1:6379> CLUSTER INFO
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:3243
cluster_stats_messages_pong_sent:3060
cluster_stats_messages_sent:6303
cluster_stats_messages_ping_received:3055
cluster_stats_messages_pong_received:3243
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:6303
127.0.0.1:6379>
模拟master故障,对应的slave节点自动提升为新master
[root@localhost ~]# redis-cli -h 192.168.10.11 -p 6379
192.168.10.11:6379> shutdown
not connected> exit
[1]- 完成 redis-server /data/redis/conf/redis.conf [root@localhost ~]# redis-trib.rb check 192.168.10.10:6379
>>> Performing Cluster Check (using node 192.168.10.10:6379)
M: 7bcdba4859d10eae99e17d7d93efc7973af0d50c 192.168.10.10:6379
slots:0-5460 (5461 slots) master
1 additional replica(s)
M: 7756a52a33dd9e99b19109bf4eaa461c8d079936 192.168.10.12:6379
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: 39c3771e87184b5f27a596c23abc882dfa2bc02a 192.168.10.11:6380
slots: (0 slots) slave
replicates 7bcdba4859d10eae99e17d7d93efc7973af0d50c
S: 46dafd34daaa3f9c4092217098c0791331db96da 192.168.10.10:6380
slots: (0 slots) slave
replicates 7756a52a33dd9e99b19109bf4eaa461c8d079936
M: 3d0acde0db99b58ec0d1cfa0dfb5444a3056634f 192.168.10.12:6380
slots:5461-10922 (5462 slots) master
0 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
故障恢复后,该节点加入集群成为新的slave
[root@localhost ~]# redis-server /data/redis/conf/redis.conf &
[3] 7425
root@localhost ~]# redis-trib.rb check 192.168.10.10:6379
>>> Performing Cluster Check (using node 192.168.10.10:6379)
M: 7bcdba4859d10eae99e17d7d93efc7973af0d50c 192.168.10.10:6379
slots:0-5460 (5461 slots) master
1 additional replica(s)
M: 7756a52a33dd9e99b19109bf4eaa461c8d079936 192.168.10.12:6379
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: 4e468829617e1e62e764b3ab3e477ba5f99bdf16 192.168.10.11:6379
slots: (0 slots) slave
replicates 3d0acde0db99b58ec0d1cfa0dfb5444a3056634f
S: 39c3771e87184b5f27a596c23abc882dfa2bc02a 192.168.10.11:6380
slots: (0 slots) slave
replicates 7bcdba4859d10eae99e17d7d93efc7973af0d50c
S: 46dafd34daaa3f9c4092217098c0791331db96da 192.168.10.10:6380
slots: (0 slots) slave
replicates 7756a52a33dd9e99b19109bf4eaa461c8d079936
M: 3d0acde0db99b58ec0d1cfa0dfb5444a3056634f 192.168.10.12:6380
slots:5461-10922 (5462 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.
(4)集群维护
1、添加节点到集群
因为各种各样的业务增长,目前的架构可能会导致无法满足现有业务的并发,加入新的服务器,并将他们添加进集群中。
添加节点,需要与之前的redis node版本相同,配置相同,再分别启动,且为一主一从。
添加节点到集群
add-node new_host:new_port existing_host:existing_port 说明:
new_host:new_port #新添加的主机IP和端口
existing_host:existing_port #已经存在于集群中任意节点的IP和端口。 redis4添加:
[root@localhost ~]# redis-trib.rb add-node 119.3.46.177:6379 192.168.10.10:6379
>>> Adding node 119.3.46.177:6379 to cluster 192.168.10.10:6379
>>> Performing Cluster Check (using node 192.168.10.10:6379)
M: 7bcdba4859d10eae99e17d7d93efc7973af0d50c 192.168.10.10:6379
slots:0-5460 (5461 slots) master
1 additional replica(s)
M: 7756a52a33dd9e99b19109bf4eaa461c8d079936 192.168.10.12:6379
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: 4e468829617e1e62e764b3ab3e477ba5f99bdf16 192.168.10.11:6379
slots: (0 slots) slave
replicates 3d0acde0db99b58ec0d1cfa0dfb5444a3056634f
S: 39c3771e87184b5f27a596c23abc882dfa2bc02a 192.168.10.11:6380
slots: (0 slots) slave
replicates 7bcdba4859d10eae99e17d7d93efc7973af0d50c
S: 46dafd34daaa3f9c4092217098c0791331db96da 192.168.10.10:6380
slots: (0 slots) slave
replicates 7756a52a33dd9e99b19109bf4eaa461c8d079936
M: 3d0acde0db99b58ec0d1cfa0dfb5444a3056634f 192.168.10.12:6380
slots:5461-10922 (5462 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.
>>> Send CLUSTER MEET to node 119.3.46.177:6379 to make it join the cluster.
[OK] New node added correctly. redis5添加:
[root@localhost ~]# redis-cli --cluster add-node 119.3.46.177:6379 192.168.10.10:6379 -a 密码
#添加时至少添加两个节点(一主一从)
添加两个服务器时一主一从设置
方法一:在新加节点到集群时,直接将他设置为主从模式
例: redis-cli -a 123456 --cluster add-node 192.168.10.13:7001 192.168.10.10:7001 #添加master节点
redis-cli -a 123456 --cluster add-node 192.168.10.13:7002 192.168.10.10:7001 --cluster-slave --cluster-master-id 086082f1e218640593aa9776c80845cf84c97a06 方法二:先将新节点加入集群,再修改为slave
redis-cli -a 123456 --cluster add-node 192.168.10.13:7001 192.168.10.10:7001 #添加节点进入集群
手动修改
redis-cli -a 123456 -h 192.168.10.10 -p 7001
192.168.10.10:7001> CLUSTER NODES #查找master的ID
192.168.10.10:7001> CLUSTER REPLICATE master的ID #设置为slave
192.168.10.10:7001> CLUSTER NODES
添加成功后重新分配槽位
[root@localhost ~]# redis-cli -a 123456 --cluster reshared 192.168.10.10:7001 (ip+port可为集群中任意节点) 出现第一个需要输入:输入数为(16384除以master的个数)
出现第二个需要输入:输入数为(新添加的节点的master节点的id)
出现第三个需要输入:输入数为 (all:表示将哪些源主机的槽位分配给新的节点)
出现第四个需要输入:表示确认分配 分配后查看:
[root@localhost ~]# redis-cli -a 123456 --cluster check 192.168.10.10:7001
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.10.10:7001 (2ca33c82...) -> 0 keys | 4096 slots | 1 slaves.
192.168.10.13:7001 (fd9d61eb...) -> 0 keys | 4096 slots | 1 slaves.
192.168.10.12:7001 (fce781a3...) -> 0 keys | 4096 slots | 1 slaves.
192.168.10.11:7001 (be7b9fef...) -> 0 keys | 4096 slots | 1 slaves.
[OK] 0 keys in 4 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 192.168.10.10:7001)
M: 2ca33c822373a073cfe06f3bd65e832ff551a052 192.168.10.10:7001
slots:[1365-5460] (4096 slots) master
1 additional replica(s)
S: a901767a5f6bd51a13ee2b822f64ce4bbe1f435e 192.168.10.11:7002
slots: (0 slots) slave
replicates 2ca33c822373a073cfe06f3bd65e832ff551a052
S: aa84800441affebc4c10a3f43a6c8dcaa2548317 192.168.10.13:7002
slots: (0 slots) slave
replicates fd9d61eb447dc196b8c27e36a7976530ca5e02bc
S: 39cb8b3aca80388373252eb36598f9a58acf4175 192.168.10.10:7002
slots: (0 slots) slave
replicates fce781a33203003acaa8e4d6f2d4831f3c5a1eb7
S: 690ff3113371d470101c16046371de2a0bb87bcd 192.168.10.12:7002
slots: (0 slots) slave
replicates be7b9fefd8d78c8f310acc403d871866d5101074
M: fd9d61eb447dc196b8c27e36a7976530ca5e02bc 192.168.10.13:7001
slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master
1 additional replica(s)
M: fce781a33203003acaa8e4d6f2d4831f3c5a1eb7 192.168.10.12:7001
slots:[12288-16383] (4096 slots) master
1 additional replica(s)
M: be7b9fefd8d78c8f310acc403d871866d5101074 192.168.10.11:7001
slots:[6827-10922] (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.
2、减少节点
可能会因为一些服务器老旧的问题,造成需要将某个节点移出集群。
删除节点的过程:
删除节点的操作与添加操作顺序相反,是先将被删除的redis上的槽位迁移到集群中的其他redis节点上,然后再将其删除。 且被删除的服务器必须保证没有数据。
过程:
迁移槽位
#查看目前状态
[root@localhost ~]# redis-cli -a 123456 --cluster check 192.168.10.10:7001
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.10.10:7001 (2ca33c82...) -> 0 keys | 4096 slots | 1 slaves.
192.168.10.13:7001 (fd9d61eb...) -> 0 keys | 4096 slots | 1 slaves.
192.168.10.12:7001 (fce781a3...) -> 0 keys | 4096 slots | 1 slaves.
192.168.10.11:7001 (be7b9fef...) -> 0 keys | 4096 slots | 1 slaves.
[OK] 0 keys in 4 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 192.168.10.10:7001)
M: 2ca33c822373a073cfe06f3bd65e832ff551a052 192.168.10.10:7001
slots:[1365-5460] (4096 slots) master
1 additional replica(s)
S: a901767a5f6bd51a13ee2b822f64ce4bbe1f435e 192.168.10.11:7002
slots: (0 slots) slave
replicates 2ca33c822373a073cfe06f3bd65e832ff551a052
S: aa84800441affebc4c10a3f43a6c8dcaa2548317 192.168.10.13:7002
slots: (0 slots) slave
replicates fd9d61eb447dc196b8c27e36a7976530ca5e02bc
S: 39cb8b3aca80388373252eb36598f9a58acf4175 192.168.10.10:7002
slots: (0 slots) slave
replicates fce781a33203003acaa8e4d6f2d4831f3c5a1eb7
S: 690ff3113371d470101c16046371de2a0bb87bcd 192.168.10.12:7002
slots: (0 slots) slave
replicates be7b9fefd8d78c8f310acc403d871866d5101074
M: fd9d61eb447dc196b8c27e36a7976530ca5e02bc 192.168.10.13:7001
slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master
1 additional replica(s)
M: fce781a33203003acaa8e4d6f2d4831f3c5a1eb7 192.168.10.12:7001
slots:[12288-16383] (4096 slots) master
1 additional replica(s)
M: be7b9fefd8d78c8f310acc403d871866d5101074 192.168.10.11:7001
slots:[6827-10922] (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. #连接到集群,并将192.168.10.13上的槽位移动到其他master节点上
[root@localhost ~]# redis-cli -a 123456 --cluster reshard 192.168.10.10:7001 --cluster-slots 10(将要删除的节点上的槽位平均分配给其他master节点) --cluster-from fd9d61eb447dc196b8c27e36a7976530ca5e02bc(要删除的节点) --cluster-to 2ca33c822373a073cfe06f3bd65e832ff551a052(承接槽位的节点) --cluster-yes #结果
[root@localhost ~]# redis-cli -a 123456 --cluster check 192.168.10.10:7001
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.10.10:7001 (2ca33c82...) -> 0 keys | 5462 slots | 2 slaves.
192.168.10.13:7001 (fd9d61eb...) -> 0 keys | 0 slots | 0 slaves.
192.168.10.12:7001 (fce781a3...) -> 0 keys | 5461 slots | 1 slaves.
192.168.10.11:7001 (be7b9fef...) -> 0 keys | 5461 slots | 1 slaves.
[OK] 0 keys in 4 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 192.168.10.10:7001)
M: 2ca33c822373a073cfe06f3bd65e832ff551a052 192.168.10.10:7001
slots:[0-1355],[1365-5460],[12278-12287] (5462 slots) master
2 additional replica(s)
S: a901767a5f6bd51a13ee2b822f64ce4bbe1f435e 192.168.10.11:7002
slots: (0 slots) slave
replicates 2ca33c822373a073cfe06f3bd65e832ff551a052
S: aa84800441affebc4c10a3f43a6c8dcaa2548317 192.168.10.13:7002
slots: (0 slots) slave
replicates 2ca33c822373a073cfe06f3bd65e832ff551a052
S: 39cb8b3aca80388373252eb36598f9a58acf4175 192.168.10.10:7002
slots: (0 slots) slave
replicates fce781a33203003acaa8e4d6f2d4831f3c5a1eb7
S: 690ff3113371d470101c16046371de2a0bb87bcd 192.168.10.12:7002
slots: (0 slots) slave
replicates be7b9fefd8d78c8f310acc403d871866d5101074
M: fd9d61eb447dc196b8c27e36a7976530ca5e02bc 192.168.10.13:7001
slots: (0 slots) master
M: fce781a33203003acaa8e4d6f2d4831f3c5a1eb7 192.168.10.12:7001
slots:[1356-1364],[5461-6816],[12288-16383] (5461 slots) master
1 additional replica(s)
M: be7b9fefd8d78c8f310acc403d871866d5101074 192.168.10.11:7001
slots:[6817-12277] (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@localhost ~]# redis-cli -a 123456 --cluster del-node 192.168.10.13:7001 fd9d61eb447dc196b8c27e36a7976530ca5e02bc
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Removing node fd9d61eb447dc196b8c27e36a7976530ca5e02bc from cluster 192.168.10.13:7001
>>> Sending CLUSTER FORGET messages to the cluster...
>>> SHUTDOWN the node.
删除成功:
[root@localhost ~]# redis-cli -a 123456 --cluster check 192.168.10.10:7001
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.10.10:7001 (2ca33c82...) -> 0 keys | 5462 slots | 2 slaves.
192.168.10.12:7001 (fce781a3...) -> 0 keys | 5461 slots | 1 slaves.
192.168.10.11:7001 (be7b9fef...) -> 0 keys | 5461 slots | 1 slaves.
[OK] 0 keys in 3 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 192.168.10.10:7001)
M: 2ca33c822373a073cfe06f3bd65e832ff551a052 192.168.10.10:7001
slots:[0-1355],[1365-5460],[12278-12287] (5462 slots) master
2 additional replica(s)
S: a901767a5f6bd51a13ee2b822f64ce4bbe1f435e 192.168.10.11:7002
slots: (0 slots) slave
replicates 2ca33c822373a073cfe06f3bd65e832ff551a052
S: aa84800441affebc4c10a3f43a6c8dcaa2548317 192.168.10.13:7002
slots: (0 slots) slave
replicates 2ca33c822373a073cfe06f3bd65e832ff551a052
S: 39cb8b3aca80388373252eb36598f9a58acf4175 192.168.10.10:7002
slots: (0 slots) slave
replicates fce781a33203003acaa8e4d6f2d4831f3c5a1eb7
S: 690ff3113371d470101c16046371de2a0bb87bcd 192.168.10.12:7002
slots: (0 slots) slave
replicates be7b9fefd8d78c8f310acc403d871866d5101074
M: fce781a33203003acaa8e4d6f2d4831f3c5a1eb7 192.168.10.12:7001
slots:[1356-1364],[5461-6816],[12288-16383] (5461 slots) master
1 additional replica(s)
M: be7b9fefd8d78c8f310acc403d871866d5101074 192.168.10.11:7001
slots:[6817-12277] (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@localhost ~]# redis-cli -a 123456 --cluster del-node 192.168.10.13:7002 aa84800441affebc4c10a3f43a6c8dcaa2548317
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Removing node aa84800441affebc4c10a3f43a6c8dcaa2548317 from cluster 192.168.10.13:7002
>>> Sending CLUSTER FORGET messages to the cluster...
>>> SHUTDOWN the node.
最终结果:
[root@localhost ~]# redis-cli -a 123456 --cluster check 192.168.10.10:7001
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.10.10:7001 (2ca33c82...) -> 0 keys | 5462 slots | 1 slaves.
192.168.10.12:7001 (fce781a3...) -> 0 keys | 5461 slots | 1 slaves.
192.168.10.11:7001 (be7b9fef...) -> 0 keys | 5461 slots | 1 slaves.
[OK] 0 keys in 3 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 192.168.10.10:7001)
M: 2ca33c822373a073cfe06f3bd65e832ff551a052 192.168.10.10:7001
slots:[0-1355],[1365-5460],[12278-12287] (5462 slots) master
1 additional replica(s)
S: a901767a5f6bd51a13ee2b822f64ce4bbe1f435e 192.168.10.11:7002
slots: (0 slots) slave
replicates 2ca33c822373a073cfe06f3bd65e832ff551a052
S: 39cb8b3aca80388373252eb36598f9a58acf4175 192.168.10.10:7002
slots: (0 slots) slave
replicates fce781a33203003acaa8e4d6f2d4831f3c5a1eb7
S: 690ff3113371d470101c16046371de2a0bb87bcd 192.168.10.12:7002
slots: (0 slots) slave
replicates be7b9fefd8d78c8f310acc403d871866d5101074
M: fce781a33203003acaa8e4d6f2d4831f3c5a1eb7 192.168.10.12:7001
slots:[1356-1364],[5461-6816],[12288-16383] (5461 slots) master
1 additional replica(s)
M: be7b9fefd8d78c8f310acc403d871866d5101074 192.168.10.11:7001
slots:[6817-12277] (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.
3、导入现有数据
基础准备
导入数据与原有数据不能有重复的key名称。
导入数据之前需要关闭redis各服务器的密码,包括集群中的各node和源Redis
redis-cli -h 192.168.10.10 -p 7001 -a 123456 CONFIG SET requirepass ""
执行
redis-cli --cluster import 集群服务器IP:PORT --CLUSTER-FROM 外部redis node-IP:port --cluster-copy --cluster-replace
Redis正式完结!!!!!