redis运维手册

非关系数据库-Redis

目录

第一章: 关系型和非关系型

关系型 mysql oracle
非关系型 redis mongo

SQL
NoSQL: Not Only SQL

1.Redis 是什么

Redis 是一种基于键值对的NoSQL 数据库,与很多键值对数据库不同,redis 中的值可以有string,hash,list,set,zset,geo 等多种数据结构和算法组成.
因为Redis 会将所有的数据都放在内存中,所以他的读写性能非常惊人.不仅如此,Redis 还可以将内存中的数据利用快照和日志的形式保存到硬盘上,Redis 还提供了键过期,发布订阅,事务,流水线等附加功能.

=======================================

第二章:Redis特点

1.速度快

Redis 所有的数据都存放在内存中
Redis 使用c语言实现
Redis 使用单线程架构

2.基于键值对的数据结构服务器

5种数据结构:字符串,哈希,列表,集合,有序集合

3.丰富的功能

提供了键过期功能,可以实现缓存
提供了发布订阅功能,可以实现消息系统
提供了pipeline功能,客户端可以将一批命令一次性传到 Redis,减少了网络开销

4.简单稳定

源码很少,3.0 版本以后 5 万行左右.
使用单线程模型法,是的Redis服务端处理模型变得简单.
不依赖操作系统的中的类库

5.客户端语言多

java,PHP,python,C,C++,Nodejs等

6.数据持久化

把所有的数据都存在磁盘中
RDB和AOF

7.主从复制

8.高可用和分布式

哨兵 redis-sentinel
集群 redis-cluster

第三章:Redis应用场景

1.缓存-键过期时间

缓存session会话
缓存用户信息,找不到再去mysql查,查到然后回写到 redis
优惠卷过期时间

2.排行榜-列表&有序集合

热度排名排行榜
发布时间排行榜

3.计数器应用-天然支持计数器

帖子浏览数
视频播放次数
商品浏览数

4.社交网络-集合

踩/赞,粉丝,共同好友/喜好,推送,打标签

5.消息队列系统-发布订阅

配合elk实现日志收集

=======================================

第三章:安装部署

1.Redis安装部署

# 下载:
wget http://download.redis.io/releases/redis-3.2.12.tar.gz
# 解压:
# 上传至 /data
tar xzf redis-3.2.12.tar.gz -C /data/
ln -s  redis-3.2.12 redis

# 安装:
yum -y install gcc automake autoconf libtool make
cd redis
make

# 环境变量:
vim /etc/profile 
export PATH=/data/redis/src:$PATH
source /etc/profile 

启动:
redis-server & 

连接测试:
redis-cli 
127.0.0.1:6379> set num 10
OK
127.0.0.1:6379> get num
10

2.基础配置文件介绍

mkdir /data/6379
cat > /data/6379/redis.conf<<EOF
daemonize yes
port 6379
logfile /data/6379/redis.log
dir /data/6379
dbfilename dump.rdb
EOF

redis-cli shutdown 
redis-server /data/6379/redis.conf 
netstat -lnp|grep 63

# +++++++++++配置文件说明++++++++++++++
### 以守护进程模式启动
daemonize yes
### 绑定的主机地址
bind 10.0.0.1
### 监听端口
port 6379
### pid 文件和log 文件的保存地址
pidfile /data/6379/redis.pid
logfile /data/6379/redis.log
### 设置数据库的数量,默认数据库为0
databases 16
### 指定本地持久化文件的文件名,默认是dump.rdb
dbfilename redis_6379.rdb
### 本地数据库的目录
dir /data/6379
# ++++++++++++++++++++++++++++++++++++++
redis-cli
127.0.0.1:6379> set name zhangsan 
OK
127.0.0.1:6379> get name
"zhangsan"

3.启动与关闭redis

### 启动
[root@db01 ~]# redis-server /data/6379/redis.conf
### 关闭
[root@db01 ~]# redis-cli  shutdown

4.登录测试

# redis-cli  -h 10.0.0.1
10.0.0.1:6379> set k1 v1
OK
10.0.0.1:6379> get k1
"v1"

第四章:redis基本操作命令

Redis 有5 种数据结构,他们是键值对中的值,对于键来说有一些通用的命令

String :      字符类型
Hash:         字典类型
List:         列表     
Set:          集合 
Sorted set:   有序集合

1.KEY的通用操作

KEYS *   keys a  keys a*    查看已存在所有键的名字   ****
TYPE                        返回键所存储值的类型     ****
EXPIRE PEXPIRE             以秒毫秒设定生存时间       ***
TTL PTTL                   以秒毫秒为单位返回生存时间 ***
PERSIST                     取消生存时间设置            ***
DEL                         删除一个key
EXISTS                      检查是否存在
RENAME                      变更KEY名

1.查看所有的key

keys *
# 十分危险的命令,线上禁止使用

2.查看有多少个key,注意,是估值

DBSIZE
# dbsize 命令在计算键总数时不会遍历所有键,而是直接获取Redis 内置的键总数变量.

3.查看是否存在这个KEY

EXISTS k1
EXISTS k1 k2 k3 

状态码:
0 表示这个key不存在
1 表示这个key存在
N 表示有的N个key存在

4.删除key

DEL k1
DEL k1 k2 k3

状态码:
0 表示这个key不存在
1 表示这个key存在,并且删除成功
N 表示有的N个key存在,并且删除N个Key

5.键过期

设置过期时间
EXPIRE k1 100

取消过期时间
PERSIST k2

状态码:
0: 表示这个key原来就没有设置过期时间
1: 表示这个key存在过期时间,并且取消成功

查看key是否过期
TTL k1

状态码:
-1: 这个key存在,但是没有设置过期时间
-2: 这个key不存在
N:  表示这个key还有多久过期,时间是秒

过期后的key直接会被删除
10.0.0.1:6379> set k2 v2 ex 60
OK
10.0.0.1:6379> ttl k2
(integer) 56
10.0.0.1:6379> persist k2
(integer) 1
10.0.0.1:6379> ttl k2
(integer) -1

 查看key是否存在
 exists key5
 
 状态码:
0: 表示这个key不存在
1: 表示这个key存在

2.strings

应用场景
session 共享
常规计数:微博数,粉丝数,订阅、礼物
key:value
----------
(1)
 set name zhangsan  
(2)
 MSET id 101 name zhangsan age 20 gender m
 等价于以下操作:
 SET id 101 
 set name zhangsan 
 set age 20 
 set gender m
(3)计数器
每点一次关注,都执行以下命令一次
127.0.0.1:6379> set num 5
127.0.0.1:6379> incr num  # 以后每执行一次就默认加1
# 显示粉丝数量:
127.0.0.1:6379> get num
(integer) 6
# 暗箱操作:
127.0.0.1:6379> INCRBY num 10000 #加10000
(integer) 10006
127.0.0.1:6379> get num
"10006"
127.0.0.1:6379> DECRBY num 10000 #减10000
(integer) 6
127.0.0.1:6379> get num
"6"
详细的例子:------------------------------------

增
set mykey "test"                为键设置新值,并覆盖原有值
getset mycounter 0              设置值,取值同时进行
setex mykey 10 "hello"          设置指定 Key 的过期时间为10秒,在存活时间可以获取value
setnx mykey "hello"             若该键不存在,则为键设置新值
mset key3  "zyx"  key4 "xyz"    批量设置键

删
del mykey                        删除已有键

改
append mykey "hello"            若该键并不存在,返回当前 Value 的长度
                                该键已经存在,返回追加后 Value的长度
incr mykey                      值增加1,若该key不存在,创建key,初始值设为0,增加后结果为1
decrby  mykey  5                值减少5
setrange mykey 20 dd            把第21和22个字节,替换为dd, 超过value长度,自动补0
查  
exists mykey                    判断该键是否存在,存在返回 1,否则返回0
get mykey                       获取Key对应的value
strlen mykey                    获取指定 Key 的字符长度
ttl mykey                       查看一下指定 Key 的剩余存活时间(秒数)
getrange mykey 1 20             获取第2到第20个字节,若20超过value长度,则截取第2个和后面所有的
mget key3 key4                  批量获取键

3.LIST(列表)

应用场景
消息队列系统
比如sina微博
在Redis中我们的最新微博ID使用了常驻缓存,这是一直更新的。
但是做了限制不能超过5000个ID,因此获取ID的函数会一直询问Redis。
只有在start/count参数超出了这个范围的时候,才需要去访问数据库。
系统不会像传统方式那样“刷新”缓存,Redis实例中的信息永远是一致的。
SQL数据库(或是硬盘上的其他类型数据库)只是在用户需要获取“很远”的数据时才会被触发,
而主页或第一个评论页是不会麻烦到硬盘上的数据库了。


微信朋友圈:
127.0.0.1:6379> LPUSH wechat "today is nice day !"
127.0.0.1:6379> LPUSH wechat "today is bad day !"
127.0.0.1:6379> LPUSH wechat "today is good  day !"
127.0.0.1:6379> LPUSH wechat "today is rainy  day !"
127.0.0.1:6379> LPUSH wechat "today is friday !"


127.0.0.1:6379> lrange wechat  0 0
1) "today is friday !"
127.0.0.1:6379> lrange wechat  0 1
1) "today is friday !"
2) "today is rainy  day !"
127.0.0.1:6379> lrange wechat  0 2
1) "today is friday !"
2) "today is rainy  day !"
3) "today is good  day !"
127.0.0.1:6379> lrange wechat  0 3
127.0.0.1:6379> lrange wechat  -2 -1
1) "today is bad day !"
2) "today is nice day !"


-----------------
插入列表:
LPUSH:从列表左侧插入数据
RPUSH:从列表右侧插入数据
增 
lpush mykey a b             若key不存在,创建该键及与其关联的List,依次插入a ,b, 若List类型的key存在,则插入value中
lpushx mykey2 e             若key不存在,此命令无效, 若key存在,则插入value中
linsert mykey before a a1   在 a 的前面插入新元素 a1
linsert mykey after e e2    在e 的后面插入新元素 e2
rpush mykey a b             在链表尾部先插入b,在插入a
rpushx mykey e              若key存在,在尾部插入e, 若key不存在,则无效
rpoplpush mykey mykey2      将mykey的尾部元素弹出,再插入到mykey2 的头部(原子性的操作)

删除列表元素:
LPOP: 从列表左侧删除
RPOP: 从列表右侧删除

删
del mykey                   删除已有键 
lrem mykey 2 a              从头部开始找,按先后顺序,值为a的元素,删除数量为2个,若存在第3个,则不删除
ltrim mykey 0 2             从头开始,索引为0,1,2的3个元素,其余全部删除
改
lset mykey 1 e              从头开始, 将索引为1的元素值,设置为新值 e,若索引越界,则返回错误信息
rpoplpush mykey mykey       将 mykey 中的尾部元素移到其头部
查
lrange mykey 0 -1           取链表中的全部元素,其中0表示第一个元素,-1表示最后一个元素。
lrange mykey 0 2            从头开始,取索引为0,1,2的元素
lrange mykey 0 0            从头开始,取第一个元素,从第0个开始,到第0个结束
lpop mykey                  获取头部元素,并且弹出头部元素,出栈
lindex mykey 6              从头开始,获取索引为6的元素 若下标越界,则返回nil 

db01:6379> LPUSH list1 A
(integer) 1
db01:6379> LPUSH list1 B
(integer) 2
db01:6379> LPUSH list1 C
(integer) 3
db01:6379> RPUSH list1 D
(integer) 4

查看列表的长度:
db01:6379> LLEN list1
(integer) 4

查看列表的内容:
db01:6379> LRANGE list1 0 -1
1) "C"
2) "B"
3) "A"
4) "D"



db01:6379> LPOP list1 
"C"
db01:6379> RPOP list1
"D"
db01:6379> LRANGE list1 0 -1
1) "B"
2) "A"

删除列表内容:
db01:6379> DEL list1 
(integer) 1

4.hash类型(字典类型)

应用场景:
存储部分变更的数据,如用户信息等。
最接近mysql表结构的一种类型
主要是可以做数据库缓存。

Hash 看起来就像一个’hash’的样子.由键值对组成
HMSET 指令设置hash 中的多个域
HGET 取回单个域.
HMGET 取回一系列的值

存数据:
hmset stu  id 101 name zhangsan age 20 gender m
hmset stu1 id 102 name zhangsan1 age 21 gender f

取数据:
HMGET stu id name age gender
HMGET stu1 id name age gender

生成一个hash类型:
db01:6379> hmset user:1000 username zhangya age 27 job it
OK

查看hash里的一个值
db01:6379> HGET user:1000 job
"it"
db01:6379> HGET user:1000 username
"zhangya"

查看hash里的多个值
db01:6379> HMGET user:1000 username age job
1) "zhangya"
2) "27"
3) "it"

查看hash里的所有的值
db01:6379> HGETALL user:1000
1) "username"
2) "zhangya"
3) "age"
4) "27"
5) "job"
6) "it"

select concat("hmset city_",id," id ",id," name ",name," countrycode ",countrycode," district ",district," population ",population) from city limit 10 into outfile '/tmp/hmset.txt'

---------------------更多的例子
增
hset myhash field1 "s"    
若字段field1不存在,创建该键及与其关联的Hashes, Hashes中,key为field1 ,并设value为s ,若存在会覆盖原value
hsetnx myhash field1 s    
若字段field1不存在,创建该键及与其关联的Hashes, Hashes中,key为field1 ,并设value为s, 若字段field1存在,则无效
hmset myhash field1 "hello" field2 "world       一次性设置多个字段
删
hdel myhash field1                      删除 myhash 键中字段名为 field1 的字段
del myhash                              删除键
改  
hincrby myhash field 1                  给field的值加1

查
hget myhash field1                      获取键值为 myhash,字段为 field1 的值
hlen myhash                             获取myhash键的字段数量
hexists myhash field1                   判断 myhash 键中是否存在字段名为 field1 的字段
hmget myhash field1 field2 field3       一次性获取多个字段
hgetall myhash                          返回 myhash 键的所有字段及其值
hkeys myhash                            获取myhash 键中所有字段的名字
hvals myhash                            获取 myhash 键中所有字段的值

5.SET 集合类型(join union)

应用场景:
案例:在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。
Redis还为集合提供了求交集、并集、差集等操作,可以非常方便的实现如共同关注、共同喜好、二度好友等功能,
对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存集到一个新的集合中。

集合是字符串的无序排列,
SADD 指令把新的元素添加到set 中

创建集合
sadd set1 1 2 3
sadd set2 3 4 5

查看集合的成员:
db01:6379> SMEMBERS set1
1) "1"
2) "2"
3) "3"
db01:6379> SMEMBERS set2
1) "3"
2) "4"
3) "5"

查看集合的差集,以前面一个集合为基准对比后面的
db01:6379> SDIFF set1 set2
1) "1"
2) "2"
db01:6379> SDIFF set2 set1
1) "4"
2) "5"

查看集合的交集
db01:6379> SINTER set1 set2
1) "3"

查看集合的并集
db01:6379> SUNION set1 set2
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"

集合不允许出现重复的值
db01:6379> SADD set1 1 2 3 4 5 6 6 7 7 
(integer) 4
db01:6379> SMEMBERS set1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"

增
sadd myset a b c  
若key不存在,创建该键及与其关联的set,依次插入a ,b,若key存在,则插入value中,若a 在myset中已经存在,则插入了 d 和 e 两个新成员。
删
spop myset              尾部的b被移出,事实上b并不是之前插入的第一个或最后一个成员
srem myset a d f        若f不存在, 移出 a、d ,并返回2
改
smove myset myset2 a        将a从 myset 移到 myset2,
查
sismember myset a           判断 a 是否已经存在,返回值为 1 表示存在。
smembers myset          查看set中的内容
scard myset             获取Set 集合中元素的数量
srandmember myset       随机的返回某一成员
sdiff myset1 myset2 myset3      1和2得到一个结果,拿这个集合和3比较,获得每个独有的值
sdiffstore diffkey myset myset2 myset3      3个集和比较,获取独有的元素,并存入diffkey 关联的Set中
sinter myset myset2 myset3              获得3个集合中都有的元素
sinterstore interkey myset myset2 myset3  把交集存入interkey 关联的Set中
sunion myset myset2 myset3              获取3个集合中的成员的并集
sunionstore unionkey myset myset2 myset3  把并集存入unionkey 关联的Set中

6.SortedSet(有序集合)

应用场景:
排行榜应用,取TOP N操作
这个需求与上面需求的不同之处在于,前面操作以时间为权重,这个是以某个条件为权重,比如按顶的次数排序,
这时候就需要我们的sorted set出马了,将你要排序的值设置成sorted set的score,将具体的数据设置成相应的value,
每次只需要执行一条ZADD命令即可。

127.0.0.1:6379> zadd topN 0 smlt 0 fskl 0 fshkl 0 lzlsfs 0 wdhbx 0 wxg 
(integer) 6
127.0.0.1:6379> ZINCRBY topN 100000 smlt
"100000"
127.0.0.1:6379> ZINCRBY topN 10000 fskl
"10000"
127.0.0.1:6379> ZINCRBY topN 1000000 fshkl
"1000000"
127.0.0.1:6379> ZINCRBY topN 100 lzlsfs
"100"
127.0.0.1:6379> ZINCRBY topN 10 wdhbx
"10"
127.0.0.1:6379> ZINCRBY topN 100000000 wxg
"100000000"

127.0.0.1:6379> ZREVRANGE topN 0 2 
1) "wxg"
2) "fshkl"
3) "smlt"
127.0.0.1:6379> ZREVRANGE topN 0 2 withscores
1) "wxg"
2) "100000000"
3) "fshkl"
4) "1000000"
5) "smlt"
6) "100000"


增
zadd myzset 2 "two" 3 "three"       添加两个分数分别是 2 和 3 的两个成员
删
zrem myzset one two                 删除多个成员变量,返回删除的数量
改
zincrby myzset 2 one                将成员 one 的分数增加 2,并返回该成员更新后的分数
查 
zrange myzset 0 -1 WITHSCORES       返回所有成员和分数,不加WITHSCORES,只返回成员
zrank myzset one                    获取成员one在Sorted-Set中的位置索引值。0表示第一个位置
zcard myzset                        获取 myzset 键中成员的数量
zcount myzset 1 2                   获取分数满足表达式 1 <= score <= 2 的成员的数量
zscore myzset three                 获取成员 three 的分数
zrangebyscore myzset  1 2               获取分数满足表达式 1 < score <= 2 的成员
#-inf 表示第一个成员,+inf最后一个成员
#limit限制关键字
#2  3  是索引号
zrangebyscore myzset -inf +inf limit 2 3  返回索引是2和3的成员
zremrangebyscore myzset 1 2         删除分数 1<= score <= 2 的成员,并返回实际删除的数量
zremrangebyrank myzset 0 1              删除位置索引满足表达式 0 <= rank <= 1 的成员
zrevrange myzset 0 -1 WITHSCORES        按位置索引从高到低,获取所有成员和分数
#原始成员:位置索引从小到大
      one  0  
      two  1
#执行顺序:把索引反转
      位置索引:从大到小
      one 1
      two 0
#输出结果: two  
       one
zrevrange myzset 1 3                获取位置索引,为1,2,3的成员
#相反的顺序:从高到低的顺序
zrevrangebyscore myzset 3 0             获取分数 3>=score>=0的成员并以相反的顺序输出
zrevrangebyscore myzset 4 0 limit 1 2    获取索引是1和2的成员,并反转位置索引

7.发布订阅

PUBLISH channel msg
    将信息 message 发送到指定的频道 channel
SUBSCRIBE channel [channel ...]
    订阅频道,可以同时订阅多个频道
UNSUBSCRIBE [channel ...]
    取消订阅指定的频道, 如果不指定频道,则会取消订阅所有频道
PSUBSCRIBE pattern [pattern ...]
    订阅一个或多个符合给定模式的频道,每个模式以 * 作为匹配符,比如 it* 匹配所   有以 it 开头的频道( it.news 、 it.blog 、 it.tweets 等等), news.* 匹配所有 以 news. 开头的频道( news.it 、 news.global.today 等等),诸如此类
PUNSUBSCRIBE [pattern [pattern ...]]
    退订指定的规则, 如果没有参数则会退订所有规则
PUBSUB subcommand [argument [argument ...]]
    查看订阅与发布系统状态
注意:使用发布订阅模式实现的消息队列,当有客户端订阅channel后只能收到后续发布到该频道的消息,之前发送的不会缓存,必须Provider和Consumer同时在线。

发布订阅例子:
窗口1:
127.0.0.1:6379> SUBSCRIBE baodi 
窗口2:
127.0.0.1:6379> PUBLISH baodi "jin tian zhen kaixin!"
订阅多频道:
窗口1:
127.0.0.1:6379> PSUBSCRIBE wang*
窗口2:
127.0.0.1:6379> PUBLISH wangbaoqiang "jintian zhennanshou "

8.redis事务

redis的事务是基于队列实现的,redis是乐观锁机制,仅实现原子性的保证,属于弱事务支持
mysql的事务是基于事务日志、悲观锁机制、mvcc等机制一起保证,强事务支持。
redis是乐观锁机制。

开启事务功能时(multi)
multi 
command1      
command2
command3
command4
exec 
discard

4条语句作为一个组,并没有真正执行,而是被放入同一队列中。
如果,这时执行discard,会直接丢弃队列中所有的命令,而不是做回滚。
exec
当执行exec时,对列中所有操作,要么全成功要么全失败

127.0.0.1:6379> set a b
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set a b
QUEUED
127.0.0.1:6379> set c d
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
# redis乐观锁实现(模拟买票)  watch
发布一张票
set ticket 1
窗口1:
watch ticket
multi
set ticket 0       1---->0
窗口2:
multi 
set ticket 0 
exec 
窗口1:
exec

9.服务器管理命令

Info
Client list
Client kill ip:port
config get *
CONFIG RESETSTAT 重置统计
CONFIG GET/SET 动态修改
Dbsize
FLUSHALL 清空所有数据 
select 1
FLUSHDB 清空当前库
MONITOR 监控实时指令
SHUTDOWN 关闭服务器

第五章: Redis持久化

1.RDB和AOF优缺点

可以在指定的时间间隔内生成数据集的 时间点快照(point-in-time snapshot)。
优点:速度快,适合于用做备份,主从复制也是基于RDB 持久化功能实现的。
缺点:会有数据丢失

记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。
AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。
优点:可以最大程度保证数据不丢
缺点:日志记录量级比较大

2.配置RDB

save 900 1                #900 秒(15 分钟)内有1 个更改
save 300 10               #300 秒(5 分钟)内有10 个更改
save 60 10000             #60 秒内有10000 个更改
dir /data/redis_cluster/redis_6379/
dbfilename redis_6379.rdb

结论:
1.执行shutdown的时候,内部会自动执行bgsave,然后再执行shutdown
2.pkill kill killall 都类似于执行shutdown命令.会触发bgsave持久化
3.恢复的时候,rdb文件名称要和配置文件里写的一样
4.如果没有配置save参数,执行shutdown不会自动bgsave持久化
5.如果没有配置save参数,可以手动执行bgsave触发持久化保存

3.配置AOF

appendonly yes                   #是否打开aof 日志功能
appendfsync always               #每1 个命令,都立即同步到aof
appendfsync everysec             #每秒写1 次
appendfsync no                   #写入工作交给操作系统,由操作系统判断缓冲区大小,统一写入到aof.

4.如果aof和rdb文件同时存在,redis会如何读取:

实验步骤:
1.插入一条数据
aof: 有记录
rdb: 没有记录
2.复制到其他地方
3.把redis停掉
4.清空数据目录
5.把数据文件拷贝过来
aof: 有记录
rdb: 没有记录
6.启动redis
7.测试,如果有新插入的数据,就表示读取的是aof,如果没有,就表示读取的是rdb

实验结论:
如果2种数据格式都存在,优先读取aof

第六章: Redis安全与认证

1.Redis用户认证

redis 默认开启了保护模式,只允许本地回环地址登录并访问数据库

# redis默认开启了保护模式,只允许本地回环地址登录并访问数据库。
禁止protected-mode
protected-mode yes/no (保护模式,是否只允许本地访问)

# (1)Bind :指定IP进行监听
vim /data/6379/redis.conf
bind 10.0.0.51  127.0.0.1

# (2)增加requirepass  {password}
vim /data/6379/redis.conf
requirepass 123456

----------验证-----
方法一:
# redis-cli -a 123456
127.0.0.1:6379> set name zhangsan 
OK
127.0.0.1:6379> exit
方法二:
# redis-cli
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> set a b
# redis-cli -a 123456 -h 10.0.0.1 -p 6379
10.0.0.1:6379> set b 2
OK

2.在线查看和修改配置

127.0.0.1:6379> CONFIG GET *
127.0.0.1:6379> CONFIG GET requirepass
127.0.0.1:6379> CONFIG GET r*
127.0.0.1:6379> CONFIG SET requirepass 123

3.禁用危险命令

禁用危险指令:
#设置配置文件
# vim /data/6379/redis.conf
rename-command KEYS  ""
#重启redis
# redis-cli -a 123456 shutdown
# redis-server /data/6379/redis.conf 

#验证是否禁用
# redis-cli -a 123456
127.0.0.1:6379> keys *
(error) ERR unknown command 'keys'

第七章: Redis主从复制

1.主从复制介绍

在分布式系统中为了解决单点问题,通常会把数据复制多个副本到其他机器,满足故障恢复和负载均衡等求.
Redis 也是如此,提供了复制功能.
复制功能是高可用Redis 的基础,后面的哨兵和集群都是在复制的基础上实现高可用的.

快速创建第二台redis节点命令:

rsync -avz /opt/* db02:/opt/
rsync -avz /data db02:/
cd /opt/redis_cluster/redis 
make install 
sed -i 's#51#52#g' /opt/redis_cluster/redis_6379/conf/redis_6379.conf
rm -rf /data/redis_cluster/redis_6379/* 
redis-server /opt/redis_cluster/redis_6379/conf/redis_6379.conf

2.配置主从

配置方法
方法1: 临时生效

[root@db-02 ~]# redis-cli -h 10.0.0.52
10.0.0.52:6379> SLAVEOF 10.0.0.51 6379
OK

方法2: 写入配置文件

SLAVEOF 10.0.0.51 6379

查看复制状态信息命令

Info replication

3.主从复制的原理

1. 副本库通过slaveof 10.0.0.51 6379命令,连接主库,并发送SYNC给主库 
2. 主库收到SYNC,会立即触发BGSAVE,后台保存RDB,发送给副本库
3. 副本库接收后会先清空自己的数据,再载入从主节点接收的rdb文件到自己的内存里
4. 主库会陆续将中间产生的新的操作,保存并发送给副本库
5. 到此,我们主复制集就正常工作了
6. 再此以后,主库只要发生新的操作,都会以命令传播的形式自动发送给副本库.
7. 所有复制相关信息,从info信息中都可以查到.即使重启任何节点,他的主从关系依然都在.
8. 如果发生主从关系断开时,从库数据没有任何损坏,在下次重连之后,从库发送PSYNC给主库
9. 主库只会将从库缺失部分的数据同步给从库应用,达到快速恢复主从的目的

4.主从其他操作

4.1 取消主从复制

[root@db-02 ~]# redis-cli -h 10.0.0.52
10.0.0.52:6379> SLAVEOF no one

4.2 主从注意事项

1.从节点只读不可写
2.从节点不会自动故障转移,它会一直同步主

10.0.0.52:6379> set k1 v1
(error) READONLY You can't write against a read only slave.

3.主从复制故障转移需要人工介入

  • 修改代码指向REDIS的IP地址
  • 从节点需要执行SLAVEOF no one

4.从节点会清空自己原有的数据,如果同步的对象写错了,就会导致数据丢失

安全的操作:
1.无论是同步,无论是主节点还是从节点
2.先备份一下数据

===================================================================

第八章: Redis哨兵

1.哨兵模式

Redis的主从复制模式下, 一旦主节点由于故障不能提供服务, 需要人工将从节点晋升为主节点, 同时还要通知应用方更新主节点地址, 对于很多应用场景这种故障处理的方式是无法接受的。 可喜的是Redis从2.8开始正式
提供了Redis Sentinel(哨兵) 架构来解决这个问题。

Redis主从复制的缺点:没有办法对master进行动态选举,需要使用Sentinel机制完成动态选举

1. 哨兵模式介绍

  • Sentinel(哨兵)进程是用于监控redis集群中Master主服务器工作的状态
  • 在Master主服务器发生故障的时候,可以实现Master和Slave服务器的切换,保证系统的高可用(HA)
  • 其已经被集成在redis2.6+的版本中,Redis的哨兵模式到了2.8版本之后就稳定了下来。

2.哨兵进程的作用

  1. 监控(Monitoring): 哨兵(sentinel) 会不断地检查你的Master和Slave是否运作正常。
  2. 提醒(Notification):当被监控的某个Redis节点出现问题时, 哨兵(sentinel) 可以通过 API 向管理员或者其他应用程序发送通知。

3.自动故障迁移(Automatic failover):当一个Master不能正常工作时,哨兵(sentinel) 会开始一次自动故障迁移操作

  • 它会将失效Master的其中一个Slave升级为新的Master, 并让失效Master的其他Slave改为复制新的Master;
  • 当客户端试图连接失效的Master时,集群也会向客户端返回新Master的地址,使得集群可以使用现在的Master替换失效Master。
  • Master和Slave服务器切换后,Master的redis.conf、Slave的redis.conf和sentinel.conf的配置文件的内容都会发生相应的改变,即,Master主服务器的redis.conf配置文件中会多一行slaveof的配置,sentinel.conf的监控目标会随之调换。

3.解决了什么?

  • 故障转移自动完成.不需要人工干预

注意:

  • 不要手动去修改配置文件,哨兵会自己同步自己处理最新的信息

手工发起选举

  • 其他节点权重调为0
  • 手动发起重新选举
  • 选举完成后,恢复所有节点的权重

4.哨兵进程的工作方式

  1. 每个Sentinel(哨兵)进程以每秒钟一次的频率向整个集群中的Master主服务器,Slave从服务器以及其他Sentinel(哨兵)进程发送一个 PING 命令。
  2. 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值,则这个实例会被 Sentinel(哨兵)进程标记为主观下线SDOWN)。
  3. 如果一个Master主服务器被标记为主观下线(SDOWN),则正在监视这个Master主服务器的所有
    Sentinel(哨兵)
    进程要以每秒一次的频率确认Master主服务器的确进入了主观下线状态
  4. 有足够数量的 Sentinel(哨兵)进程(大于等于配置文件指定的值)在指定的时间范围内确认Master主服务器进入了主观下线状态(SDOWN), 则Master主服务器会被标记为客观下线(ODOWN)
  5. 在一般情况下, 每个Sentinel(哨兵)进程会以每 10 秒一次的频率向集群中的所有Master主服务器、Slave从服务器发送 INFO 命令。
  6. 当Master主服务器被 Sentinel(哨兵)进程标记为客观下线(ODOWN)时,Sentinel(哨兵)进程向下线的 Master主服务器的所有 Slave从服务器发送 INFO 命令的频率会从 10 秒一次改为每秒一次。
  7. 若没有足够数量的 Sentinel(哨兵)进程同意 Master主服务器下线, Master主服务器的客观下线状态就会被移除。若 Master主服务器重新向 Sentinel(哨兵)进程发送 PING 命令返回有效回复,Master主服务器的主观下线状态就会被移除。

2.安装部署redis哨兵

1.安装部署3个单节点

# 三台主机分别部署redis
mkdir -p /data/redis_cluster/redis_6379
mkdir -p /opt/redis_cluster/redis_6379/{conf,pid,logs}
cd /data/soft/
wget http://download.redis.io/releases/redis-3.2.9.tar.gz
tar zxf redis-3.2.9.tar.gz -C /opt/redis_cluster/
ln -s /opt/redis_cluster/redis-3.2.9/ /opt/redis_cluster/redis
cd /opt/redis_cluster/redis
make && make install
cd /opt/redis_cluster/redis_6379/conf/
cat >redis_6379.conf <<EOF
daemonize yes
bind 10.0.0.5x   #三个节点修改为自己的IP地址
port 6379
pidfile /opt/redis_cluster/redis_6379/pid/redis_6379.pid
logfile /opt/redis_cluster/redis_6379/logs/redis_6379.log
databases 16
dbfilename redis_6379.rdb
dir /data/redis_cluster/redis_6379
requirepass 123
masterauth 123
EOF 
# 启动所有的单节点
redis-server /opt/redis_cluster/redis_6379/conf/redis_6379.conf 

2.安装部署3个哨兵节点

# 三个节点的bind IP修改为自己的IP地址
mkdir -p /data/redis_cluster/redis_26379
mkdir -p /opt/redis_cluster/redis_26379/{conf,pid,logs}
# 配置哨兵的配置文件
cat >/opt/redis_cluster/redis_26379/conf/redis_26379.conf << EOF
bind 10.0.0.5x
port 26379
daemonize yes
logfile /opt/redis_cluster/redis_26379/logs/redis_26379.log
dir /data/redis_cluster/redis_26379
sentinel monitor mymaster 10.0.0.51 6379 2 
sentinel down-after-milliseconds mymaster 3000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 18000
sentinel auth-pass mymaster 123 
EOF

3.配置主从复制

redis-cli -h db02 -a 123 slaveof 10.0.0.51 6379
redis-cli -h db03 -a 123 slaveof 10.0.0.51 6379

4.启动哨兵

redis-sentinel /opt/redis_cluster/redis_26379/conf/redis_26379.conf

5.验证主节点

redis-cli -h db01 -p 26379 -a 123 Sentinel get-master-addr-by-name mymaster
redis-cli -h db02 -p 26379 -a 123 Sentinel get-master-addr-by-name mymaster
redis-cli -h db03 -p 26379 -a 123 Sentinel get-master-addr-by-name mymaster
redis-cli -h db03 -p 26379 -a 123 info replication

3.哨兵故障转移

  • 关闭主节点服务上的所有redis进程
  • 观察其他2个节点会不会发生选举
  • 查看配置文件里会不会自动更新
  • 查看新的主节点能不能写入
  • 查看从节点能否正常同步

模拟故障修复上线

  • 启动单节点
  • 启动哨兵

模拟权重选举

  • 设置其他节点的权重为0
  • 手动发起重新选举
  • 观察所有节点消息是否同步
  • 观察切换结果是否符合预期

命令解释:
1.查询命令:CONFIG GET slave-priority
2.设置命令:CONFIG SET slave-priority 0
3.主动切换:sentinel failover mymaster

操作命令:
redis-cli -h db02 -p 6379 CONFIG SET slave-priority 0
redis-cli -h db03 -p 6379 CONFIG SET slave-priority 0
redis-cli -h db01 -p 26379 sentinel failover mymaster

验证选举结果:
redis-cli -h db01 -p 26379 Sentinel get-master-addr-by-name mymaster

第九章 redis cluster

1.集群介绍

# 高性能
1、在多分片节点中,将16384个槽位,均匀分布到多个分片节点中
2、存数据时,将key做crc16(key),然后和16384进行取模,得出槽位值(0-16383之间)
3、根据计算得出的槽位值,找到相对应的分片节点的主节点,存储到相应槽位上
4、如果客户端当时连接的节点不是将来要存储的分片节点,分片集群会将客户端连接切换至真正存储节点进行数据存储

# 高可用
在搭建集群时,会为每一个分片的主节点,对应一个从节点,实现slaveof的功能,同时当主节点down,实现类似于sentinel的自动failover的功能。

1、redis会有多组分片构成(3组)
2、redis cluster 使用固定个数的slot存储数据(一共16384slot)
3、每组分片分得1/3 slot个数(0-5500  5501-11000  11001-16383)
4、基于CRC16(key) % 16384 ====》值 (槽位号)。

2.安装部署

1.规划

6个redis实例,一般会放到3台硬件服务器
注:在企业规划中,一个分片的两个分到不同的物理机,防止硬件主机宕机造成的整个分片数据丢失。

2.实例搭建

db01操作步骤:

mkdir -p /opt/redis_cluster/redis_{6380,6381}/{conf,logs,pid}
mkdir –p /data/redis_cluster/redis_{6380,6381}
cat >/opt/redis_cluster/redis_6380/conf/redis_6380.conf<<EOF
bind 10.0.0.51
port 6380
daemonize yes
pidfile "/opt/redis_cluster/redis_6380/pid/redis_6380.pid"
logfile "/opt/redis_cluster/redis_6380/logs/redis_6380.log"
dbfilename "redis_6380.rdb"
dir "/data/redis_cluster/redis_6380/"
cluster-enabled yes
cluster-config-file nodes_6380.conf
cluster-node-timeout 15000
EOF
cd /opt/redis_cluster/
cp redis_6380/conf/redis_6380.conf redis_6381/conf/redis_6381.conf
sed -i 's#6380#6381#g' redis_6381/conf/redis_6381.conf 
rsync -avz /opt/redis_cluster/redis_638* db02:/opt/redis_cluster/
rsync -avz /opt/redis_cluster/redis_638* db03:/opt/redis_cluster/
redis-server /opt/redis_cluster/redis_6380/conf/redis_6380.conf
redis-server /opt/redis_cluster/redis_6381/conf/redis_6381.conf

db02操作:

find /opt/redis_cluster/redis_638* -type f -name "*.conf"|xargs sed -i "/bind/s#51#52#g"
mkdir –p /data/redis_cluster/redis_{6380,6381}
redis-server /opt/redis_cluster/redis_6380/conf/redis_6380.conf
redis-server /opt/redis_cluster/redis_6381/conf/redis_6381.conf

db03操作

find /opt/redis_cluster/redis_638* -type f -name "*.conf"|xargs sed -i "/bind/s#51#53#g"
mkdir –p /data/redis_cluster/redis_{6380,6381}
redis-server /opt/redis_cluster/redis_6380/conf/redis_6380.conf
redis-server /opt/redis_cluster/redis_6381/conf/redis_6381.conf
ps -ef | grep redis

集群发现

redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.51 6381
redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.52 6380
redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.52 6381
redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.53 6380
redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.53 6381

3.分配槽位

1.槽位规划:

db01:6380  5461	 0-5361
db02:6380  5461  5462-10923
db03:6380  5462  10924-16384

2.分配槽位

redis-cli -h db01 -p 6380 CLUSTER ADDSLOTS {0..5461}
redis-cli -h db02 -p 6380 CLUSTER ADDSLOTS {5462..10923}
redis-cli -h db03 -p 6380 CLUSTER ADDSLOTS {10924..16383}

3.测试

redis-cli -h db01 -p 6380 CLUSTER INFO
redis-cli -h db01 -p 6380 CLUSTER NODES
redis-cli -h db01 -p 6380 set k1 v1 

4.手动配置集群高可用

1.先查看所有的节点信息
redis-cli -c -h db01 -p 6380 CLUSTER NODES

查看集群状态,以及每个实例的ID

2.操作命令

需要在你要同步的从节点上执行:

redis-cli -c -h db01 -p 6381 CLUSTER REPLICATE db02:6380的ID 
redis-cli -c -h db02 -p 6381 CLUSTER REPLICATE db03:6380的ID 
redis-cli -c -h db03 -p 6381 CLUSTER REPLICATE db01:6380的ID
3.验证
redis-cli -c -h db01 -p 6380 CLUSTER NODES 

查看所有的6381节点是否都变成slave了

4.模拟故障转移

1.关掉任意的6380节点,观察从节点是否主动接管了主节点
2.关掉某台服务器上的所有redis节点,观察从节点是否主动接管了主节点
3.关掉所有的主节点,观察从节点是否主动接管了主节点

5.模拟故障修复

1.把故障的主节点重新启动
2.观察复制关系是否发生改变
3.理想中的情况是,原来的主节点变成了从节点

6.模拟手动切换角色

1.在你需要切换的那个节点上执行CLUSTER FAILOVER
2.每操作一步,就更新一下进度图
3.观察主从复制结果是否正确

redis-cli -c -h db01 -p 6380 CLUSTER FAILOVER
redis-cli -c -h db02 -p 6380 CLUSTER FAILOVER
redis-cli -c -h db03 -p 6380 CLUSTER FAILOVER

注意

涉及到数据迁移,故障转移,故障修复的时候,要在业务流量低峰期操作
因为集群也是基于主从复制,而传输RDB文件需要依靠网络,会占用大量的带宽资源,会影响用户体验
操作过程中,需要时刻关注集群健康状态是否为OK

5.使用工具安装部署集群

清空原有的集群配置,重新做:

1.删除node的配置文件
pkill redis
rm -rf /data/redis_cluster/redis_6380/*  
rm -rf /data/redis_cluster/redis_6381/*
sh redis_shell.sh start 6380
sh redis_shell.sh start 6381
2.安装依赖包:
yum makecache fast
yum install rubygems -y
gem sources --remove https://rubygems.org/
gem sources -a http://mirrors.aliyun.com/rubygems/
gem update –system
gem install redis -v 3.3.5
3.工具操作命令:
# 将节点加入集群管理
cd /opt/redis_cluster/redis/src/
./redis-trib.rb create --replicas 1 10.0.0.51:6380 10.0.0.52:6380 10.0.0.53:6380 10.0.0.51:6381 10.0.0.52:6381 10.0.0.53:6381

Adding replica 10.0.0.52:6381 to 10.0.0.51:6380
Adding replica 10.0.0.51:6381 to 10.0.0.52:6380
Adding replica 10.0.0.53:6381 to 10.0.0.53:6380

# 集群主节点状态
redis-cli -p 6380 cluster nodes | grep master
# 集群从节点状态
redis-cli -p 6380 cluster nodes | grep slave

通过一条命令直接搭建好,使用工具安装部署会出现同一台机器自己复制自己的情况
这时候只需要你手动的修改一下复制关系即可

4508d07a5580245cdb274d04ed0c8e80f7c03aed 10.0.0.52:6380 
8d6e55d1d8a498291fa6b79b49d2babe2af5f4f7 10.0.0.51:6381 
61a466ad46d88df74f38c106f64ed7f57477936b 10.0.0.51:6380 
fd8c74508f8dfe03a1a9868b87452555c0180234 10.0.0.52:6381 
a6c0fa8e0b82171aa414927cfb5d2033f49f36af 10.0.0.53:6380 
a939936517d175a9bb86b67a6429c930908775d8 10.0.0.53:6381 

通过命令调整主从指向

10.0.0.53:6381     10.0.0.51:6380
redis-cli -c -h db03 -p 6381 CLUSTER REPLICATE 61a466ad46d88df74f38c106f64ed7f57477936b 
10.0.0.52:6381     10.0.0.53:6380
redis-cli -c -h db02 -p 6381 CLUSTER REPLICATE a6c0fa8e0b82171aa414927cfb5d2033f49f36af 
4.工具其他命令

检查集群是否负载均衡,允许的误差范围在2%以内

./redis-trib.rb rebalance db01:6380

检查集群状态是否正常

./redis-trib.rb check db01:6380

尝试修复有问题的集群,注意,不是万能的,但是可以给你提示哪个槽有问题

./redis-trib.rb fix db01:6380

使用工具扩容

使用工具添加新节点
前提条件:
1.新增加的节点必须为空,也就是没有数据
2.不能使用host解析的主机名,使用IP地址可以

1.创建2个新节点:

mkdir -p /opt/redis_cluster/redis_{6390,6391}/{conf,logs,pid}
mkdir -p /data/redis_cluster/redis_{6390,6391} 
cd /opt/redis_cluster/
cp redis_6380/conf/redis_6380.conf redis_6390/conf/redis_6390.conf
cp redis_6380/conf/redis_6380.conf redis_6391/conf/redis_6391.conf
sed -i 's#6380#6390#g' redis_6390/conf/redis_6390.conf
sed -i 's#6380#6391#g' redis_6391/conf/redis_6391.conf

2.启动新节点:

reids-server redis_6390/conf/redis_6390.conf
reids-server redis_6391/conf/redis_6391.conf

3.添加节点操作命令:

./redis-trib.rb add-node 10.0.0.51:6390 10.0.0.51:6380
./redis-trib.rb add-node 10.0.0.51:6391 10.0.0.51:6380

4.重新分配槽位:

./redis-trib.rb reshard 10.0.0.51:6381

第一次交互: 输入每个节点你要分配的槽位数量: 4096
第二次交互: 输入接收的节点ID,也就是新增加的机器的ID: 6390的ID
第三次交互: 输入从哪些节点发送槽位给新节点的ID: all
第四次交互: 输入:yes

5.迁移完成后检查

./redis-trib.rb check 10.0.0.51:6380 
./redis-trib.rb rebalance 10.0.0.51:6380

6.调整复制关系

redis-cli -c -h db01 -p 6391 
CLUSTER REPLICATE db01:6380的ID 

使用工具缩容

1.使用工具重新分配槽位

./redis-trib.rb reshard 10.0.0.51:6380

计算要下线的节点需要迁移给其他节点多少个槽位, 4096/3 ~= 1365
第一次交互: 输入要迁移多少个槽位: 1365
第二次交互: 输入需要接受的节点ID: db01:6380的ID
第三次交互: 输入需要下线的那个节点的ID: db01:6390的ID
第四次交互: 输入done
第五次交互: 输入yes

注意!
你有多少节点需要接受,就得重复执行多少次

重复上面的操作,知道所有的槽位全部都迁移完毕

2.下线已经没用的节点

./redis-trib.rb del-node 10.0.0.51:6390 6390的ID
./redis-trib.rb del-node 10.0.0.51:6391 6391的ID

3.检查已经忘记的节点是否安全关闭了

ps -ef|grep redis

4.检查集群状态是否正常

CLUSTER INFO 
CLUSTER NODES

5.调整主从复制关系

CLUSTER REPLICATE ID 

6.使用工具迁移单节点数据到集群

1.安装软件包和依赖包

cd /opt/redis_cluster/
git clone https://github.com/vipshop/redis-migrate-tool.git
cd redis-migrate-tool/
yum install libtool autoconf automake -y 
autoreconf -fvi
./configure
make && make install

2.编写配置文件

cat > 6379_to_6380.conf << EOF
[source]
type: single
servers:
- 10.0.0.51:6379

[target]
type: redis cluster
servers:
- 10.0.0.51:6380 

[common]
listen: 0.0.0.0:8888
source_safe: true
EOF

具体的可以登录github上,可以看到各种模式的说明

3.单节点生成测试数据

cat input_6379.sh 
#!/bin/bash
for i in $(seq 1 1000)
do
	redis-cli -c -h db01 -p 6379 set oldzhang_${i} oldzhang_${i}
	echo "set oldzhang_${i} is ok"
done

4.运行工具迁移单节点数据到集群

redis-migrate-tool -c redis_6379_to_6380.conf

5.运行工具验证数据是否迁移完成

redis-migrate-tool -c 6379_to_6380.conf -C redis_check

7.使用RDB文件迁移数据到集群

1.先把集群的RDB文件都收集起来

  • 在从节点上执行bgsave命令生成RDB文件
redis-cli -h db01 -p 6381 BGSAVE
redis-cli -h db02 -p 6381 BGSAVE
redis-cli -h db03 -p 6381 BGSAVE

2.把从节点生成的RDB文件拉取过来

mkdir rdb_backup
cd rdb_backup/
scp db01:/data/redis_cluster/redis_6381/redis_6381.rdb db01_6381.rdb
scp db02:/data/redis_cluster/redis_6381/redis_6381.rdb db02_6381.rdb
scp db03:/data/redis_cluster/redis_6381/redis_6381.rdb db03_6381.rdb

3.停掉所有的从节点

bash redis_shell stop 6381

4.停掉所有的主节点

bash redis_shell stop 6380

5.删除数据目录的RDB文件

rm -rf /data/redis_cluster/redis_6380/*.rdb
rm -rf /data/redis_cluster/redis_6381/*.rdb

6.启动所有节点

sh redis_shell.sh start 6380
sh redis_shell.sh start 6381

7.编写配置文件

[root@db-01 ~/rdb_backup]# cat rdb_to_cluter.conf 
[source]
type: rdb file
servers:
- /root/rdb_backup/db01_6381.rdb 
- /root/rdb_backup/db02_6381.rdb 
- /root/rdb_backup/db03_6381.rdb 

[target]
type: redis cluster
servers:
- 10.0.0.51:6380 

[common]
listen: 0.0.0.0:8888
source_safe: true

8.使用工具导入

redis-migrate-tool -c rdb_to_cluter.conf

案例一:使用工具分析key的大小

1.安装命令:

yum install python-pip gcc python-devel -y
cd /opt/
git clone https://github.com/sripathikrishnan/redis-rdb-tools
cd redis-rdb-tools
pip install python-lzf
python setup.py install

2.生成测试数据:

redis-cli -h db01 -p 6379 set txt $(cat txt.txt)

3.执行bgsave生成rdb文件

redis-cli -h db01 -p 6379 BGSAVE

4.使用工具分析:

cd /data/redis_cluster/redis_6379/
rdb -c memory redis_6379.rdb -f redis_6379.rdb.csv

5.过滤分析

awk -F"," '{print $4,$3}' redis_6379.rdb.csv |sort -r

6.将结果整理汇报给领导,询问开发这个key是否可以删除

第十章 redis的多API支持

1.python环境的安装

python为例
yum install -y python36 
python3 -V
yum install -y python36-pip
pip3 install redis 
pip3 install redis-py-cluster

2.对redis的单实例进行连接操作

~]# redis-server /data/6379/redis.conf 

python3
>>>import redis
>>>r = redis.StrictRedis(host='10.0.0.1', port=6379, db=0,password='123456')
>>>r.set('name', 'leo')
>>>r.get('name')

3.sentinel集群连接并操作

[root@db01 ~]# redis-server /data/6380/redis.conf
[root@db01 ~]# redis-server /data/6381/redis.conf
[root@db01 ~]# redis-server /data/6382/redis.conf 
[root@db01 ~]# redis-sentinel /data/26380/sentinel.conf &
--------------------------------
## 导入redis sentinel包
>>>from redis.sentinel import Sentinel  
##指定sentinel的地址和端口号
>>> sentinel = Sentinel([('localhost', 26380)], socket_timeout=0.1)  
##测试,获取以下主库和从库的信息
>>> sentinel.discover_master('mymaster')    
>>> sentinel.discover_slaves('mymaster')  

mymaster是哨兵集群的名称

# 配置读写分离
#写节点
>>> master = sentinel.master_for('mymaster', socket_timeout=0.1,password="123")  
#读节点
>>> slave = sentinel.slave_for('mymaster', socket_timeout=0.1,password="123")  
###读写分离测试   key     
>>> master.set('oldboy', '123')  
>>> slave.get('oldboy')  

4.python3连接rediscluster集群测试

>>> from rediscluster import. Rediscluster

>>> startup_nodes=[{"host":"10.0.0.1","port":6380},{"host":"10.0.0.2","port":6380},{"host":"10.0.0.3","port":6380}]

 ## Note:: dec ode responses must be set. to True when used with python3
>>> rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True)
>>> rc.set("foo","bar")
True
>>> print(rc.get("foo"))
'bar'

第十一章

缓存穿透

概念
访问一个不存在的key,缓存不起作用,请求会穿透到DB,流量大时DB会挂掉。

解决方案
采用布隆过滤器,使用一个足够大的bitmap,用于存储可能访问的key,不存在的key直接被过滤;
访问key未在DB查询到值,也将空值写进缓存,但可以设置较短过期时间。

缓存雪崩

概念
大量的key设置了相同的过期时间,导致在缓存在同一时刻全部失效,造成瞬时DB请求量大、压力骤增,引起雪崩。

解决方案
可以给缓存设置过期时间时加上一个随机值时间,使得每个key的过期时间分布开来,不会集中在同一时刻失效。

缓存击穿

概念
一个存在的key,在缓存过期的一刻,同时有大量的请求,这些请求都会击穿到DB,造成瞬时DB请求量大、压力骤增。
解决方案
在访问key之前,采用SETNX(set if not exists)来设置另一个短期key来锁住当前key的访问,访问结束再删除该短期key。
原文地址:https://www.cnblogs.com/dinghc/p/14849416.html