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实现日志收集

redis安装部署

1.目录规划
/data/soft/ #redis下载目录
/opt/redis_{PORT}/{conf,logs,pid} #redis安装目录
/data/redis_{PORT}/redis_{PORT}.rdb #redis数据目录
/root/scripts/redis_shell.sh #redis运维脚本

2.安装命令

编辑hosts文件

[root@db01 ~]# tail -3 /etc/hosts
10.0.0.51 db01
10.0.0.52 db02
10.0.0.53 db03

yum install gcc -y
make distclean && make
mkdir -p /data/soft
mkdir -p /data/redis_6379
mkdir -p /opt/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/
ln -s /opt/redis-3.2.9/ /opt/redis
cd /opt/redis
make && make install

3.配置文件
cat >/opt/redis_6379/conf/redis_6379.conf <<EOF

以守护进程模式启动

daemonize yes

绑定的主机地址

bind 10.0.0.51

监听端口

port 6379

pid文件和log文件的保存地址

pidfile /opt/redis_6379/pid/redis_6379.pid
logfile /opt/redis_6379/logs/redis_6379.log

设置数据库的数量,默认数据库为0

databases 16

指定本地持久化文件的文件名,默认是dump.rdb

dbfilename redis_6379.rdb

本地数据库的目录

dir /data/redis_6379
EOF

4.启动redis
redis-server /opt/redis_6379/conf/redis_6379.conf

5.检查是否启动
ps -ef|grep redis
netstat -lntup|grep redis

6.进入redis
redis-cli

redis全局命令操作命令

0.写入key
set k1 v1
set k2 v2
set k3 v3

1.查看所有的key!线上禁止使用!
keys *

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

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 k1

状态码:
0: 表示这个key不存在
1: 表示这个key存在,并且设置过期时间成功

查看key是否过期
TTL k1

状态码:
-1 :这个key存在,并且永不过期
-2 :这个key不存在
N :这个key存在,并且在N秒后过期

过期后的key直接会被删除

字符串操作:

1.设置一个key
set k1 v1

2.查看一个key
get k1

3.设置多个key
MSET k1 v1 k2 v2 k3 v3

4.查看多个key
MGET k1 k2 k3

5.天然计数器
加1:
set k1 1
INCR k1
get k1

加N:
INCRBY k1 100

减1:
INCRBY k1 -1

减N:
INCRBY k1 -N

列表:

插入列表:
LPUSH:从列表左侧插入数据
RPUSH:从列表右侧插入数据

LPUSH list1 1
LPUSH list1 2
LPUSH list1 3
RPUSH list1 4
RPUSH list1 5
RPUSH list1 6

查看列表的长度:
LLEN list1

查看列表的内容:
127.0.0.1:6379> LRANGE list1 0 -1

  1. "3"
  2. "2"
  3. "1"
  4. "4"
  5. "5"
  6. "6"

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

LPOP list1
RPOP list1

删除列表内容:
DEL list1

哈希:

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

生成一个hash类型:
HMSET user:1 name xiaozhang job it age 28
HMSET user:2 name abc job it age 28
HMSET user:3 name def job it age 28

查看hash里的一个值
HMGET user:1 name

查看hash里的多个值
HMGET user:1 name age job

查看hash里的所有的值
HGETALL user:1

mysql数据和redis哈希对比:
user表

uid name job age
1 xiaozhang it 28
2 xiaoya it 28
3 yazhang it 28

mysql查询数据
select * from user where id = 3

redis缓存mysql数据
名字 key1 k1值 key2 k2的值 key3 k3的值
uid:1 name xiaozahng job it age 28
uid:2 name xiaoya job it age 28
uid:3 name yazahng job it age 28

集合

创建集合
db01:6379> SADD set1 1 2 3
(integer) 3
db01:6379> SADD set2 1 3 5 7
(integer) 4

查看集合的成员:
db01:6379> SMEMBERS set1

  1. "1"
  2. "2"
  3. "3"
    db01:6379> SMEMBERS set2
  4. "1"
  5. "3"
  6. "5"
  7. "7"

查看集合的差集,以前面一个集合为基准对比后面的,前面有,后面没有则选出来
db01:6379> SDIFF set1 set2

  1. "2"
    db01:6379> SDIFF set2 set1
  2. "7"

查看集合的交集
db01:6379> SINTER set1 set2

  1. "1"
  2. "3"
  3. "5"

查看集合的并集
db01:6379> SUNION set1 set2

  1. "1"
  2. "2"
  3. "3"
  4. "5"
  5. "7"
    db01:6379> SUNION set1 set2 set3
  6. "1"
  7. "2"
  8. "3"
  9. "5"
  10. "7"
  11. "9"

集合不允许出现重复的值

Redis持久化

1.RDB和AOF优缺点
RDB: 快照,把当前内存里的状态快照到磁盘上
优点: 恢复速度快
缺点: 可能会丢失数据

AOF: 类似于mysql的binlog,重写,1秒写一次
优点: 安全,有可能会丢失1秒的数据
缺点: 文件比较大,恢复速度慢

2.配置RDB
save 900 1
save 300 10
save 60 10000
dir /data/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触发持久化保存

常用命令:
ll /data/redis_6379/
cat /opt/redis_6379/conf/redis_6379.conf
vim /opt/redis_6379/conf/redis_6379.conf
pkill redis
redis-server /opt/redis_cluster/redis_6379/conf/redis_6379.conf
redis-cli -h db01
redis-cli -h db01 shutdown
bash for.sh

3.配置AOF
appendfilename "redis_6379.aof"
appendonly yes
appendfsync everysec

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

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

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

Redis用户认证

1.配置文件
requirepass 123456

2.使用密码登录
两种方式:
第一种:
redis-cli -h db01
AUTH 123456

第二种:
redis-cli -h db01 -a 123456 get k_1

主从复制命令:

方法1:临时生效
SLAVEOF 10.0.0.51 6379

方法2:写入配置文件
SLAVEOF 10.0.0.51 6379

取消同步命令:
SLAVEOF no one

主从复制流程:
从库发起同步请求
11:55:12.686 * Connecting to MASTER 10.0.0.51:6379
11:55:12.687 * MASTER <-> SLAVE sync started
11:55:12.687 * Non blocking connect for SYNC fired the event.
11:55:12.687 * Master replied to PING, replication can continue...
11:55:12.688 * Partial resynchronization not possible (no cached master)
11:55:12.690 * Full resync from master: c63b80909e49adfa3880dcc87ccffb89d148a564:436

主库接收请求
11:55:12.694 * Slave 10.0.0.52:6379 asks for synchronization
11:55:12.694 * Full resync requested by slave 10.0.0.52:6379

主库开始BGSAVE
11:55:12.694 * Starting BGSAVE for SYNC with target: disk
11:55:12.695 * Background saving started by pid 13009
11:55:12.700 * DB saved on disk
11:55:12.700 * RDB: 6 MB of memory used by copy-on-write

从库接收主库的数据,清空自己的数据,然后将主库发送过来的RDB文件加载到内存中
11:55:12.780 * MASTER <-> SLAVE sync: receiving 12887 bytes from master
11:55:12.781 * MASTER <-> SLAVE sync: Flushing old data
11:55:12.781 * MASTER <-> SLAVE sync: Loading DB in memory
11:55:12.782 * MASTER <-> SLAVE sync: Finished with success

主库接收从库消息,主从复制成功
11:55:12.786 * Background saving terminated with success
11:55:12.786 * Synchronization with slave 10.0.0.52:6379 succeeded

Redis主从复制

快速创建第二台redis节点命令:
rsync -avz /opt/* db02:/opt/
rsync -avz /data db02:/
cd /opt/redis
make install
sed -i 's#51#52#g' /opt/redis_6379/conf/redis_6379.conf
rm -rf /data/redis_6379/*
redis-server /opt/redis_6379/conf/redis_6379.conf

配置方法:
方法1: 临时生效
[root@db-02 ~]# redis-cli -h 10.0.1.52
10.0.0.52:6379> SLAVEOF 10.0.1.51 6379
OK

方法2: 写入配置文件
SLAVEOF 10.0.1.51 6379

主从复制流程:
1.从节点发送同步请求到主节点
2.主节点接收到从节点的请求之后,做了如下操作

  • 立即执行bgsave将当前内存里的数据持久化到磁盘上
  • 持久化完成之后,将rdb文件发送给从节点
    3.从节点从主节点接收到rdb文件之后,做了如下操作
  • 清空自己的数据
  • 载入从主节点接收的rdb文件到自己的内存里
    4.后面的操作就是和主节点实时的了

取消主从复制
SLAVEOF no one

注意!!!
1.从节点只读不可写
2.从节点不会自动故障转移,它会一直同步主
10.0.1.52:6379> set k1 v1
(error) READONLY You can't write against a read only slave.
3.主从复制故障转移需要人工介入

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

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

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

Redis哨兵

哨兵操作
1.快速安装3个redis节点
rsync -avz 10.0.0.51:/opt/* /opt/
mkdir /data/redis_6379 -p
cd /opt/redis
make install
sed -i 's#51#53#g' /opt/redis_6379/conf/redis_6379.conf
rm -rf /data/redis_6379/*
redis-server /opt/redis_6379/conf/redis_6379.conf
redis-cli

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

!!!!注意!!!!
三个节点的bind IP修改为自己的IP地址
===========================
mkdir -p /data/redis_26379
mkdir -p /opt/redis_26379/{conf,pid,logs}

3.配置哨兵的配置文件
db01的配置:
cat >/opt/redis_26379/conf/redis_26379.conf << EOF
bind 10.0.0.51
port 26379
daemonize yes
logfile /opt/redis_26379/logs/redis_26379.log
dir /data/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
EOF

db02的配置:
cat >/opt/redis_26379/conf/redis_26379.conf << EOF
bind 10.0.0.52
port 26379
daemonize yes
logfile /opt/redis_26379/logs/redis_26379.log
dir /data/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
EOF

db03的配置:
cat >/opt/redis_26379/conf/redis_26379.conf << EOF
bind 10.0.0.53
port 26379
daemonize yes
logfile /opt/redis_26379/logs/redis_26379.log
dir /data/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
EOF

4.启动所有的单节点
redis-server /opt/redis_6379/conf/redis_6379.conf

5.配置主从复制
redis-cli -h db02 slaveof 10.0.0.51 6379
redis-cli -h db03 slaveof 10.0.0.51 6379

6.启动哨兵
redis-sentinel /opt/redis_26379/conf/redis_26379.conf

7.验证主节点
redis-cli -h db01 -p 26379 Sentinel get-master-addr-by-name mymaster
redis-cli -h db02 -p 26379 Sentinel get-master-addr-by-name mymaster
redis-cli -h db03 -p 26379 Sentinel get-master-addr-by-name mymaster

8.模拟故障转移

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

9.模拟故障修复上线

  • 启动单节点
  • 启动哨兵

10.模拟权重选举

  • 设置其他节点的权重为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
哨兵节点常用命令
Info Sentinel
Sentinel masters
Sentinel master <master name>
Sentinel slaves <master name>
Sentinel sentinels <master name>
Sentinel get-master-addr-by-name <master name>
Sentinel failover <master name>
Sentinel flushconfig

Redis哨兵+主从+密码

主从密码配置文件里添加2行参数:
requirepass "123456"
masterauth "123456"

哨兵配置文件添加一行参数:
sentinel auth-pass mymaster 123456

基于密码认证的哨兵配置文件
db01的单节点配置:
cat >/opt/redis_6379/conf/redis_6379.conf <<EOF
daemonize yes
bind 10.0.0.51 127.0.0.1
port 6379
pidfile /opt/redis_6379/pid/redis_6379.pid
logfile /opt/redis_6379/logs/redis_6379.log
databases 16
dir /data/redis_6379
dbfilename redis_6379.rdb
requirepass "123456"
masterauth "123456"
EOF

db02的单节点配置:
cat >/opt/redis_6379/conf/redis_6379.conf <<EOF
daemonize yes
bind 10.0.0.52 127.0.0.1
port 6379
pidfile /opt/redis_6379/pid/redis_6379.pid
logfile /opt/redis_6379/logs/redis_6379.log
databases 16
dir /data/redis_6379
dbfilename redis_6379.rdb
requirepass "123456"
masterauth "123456"
EOF

db03的单节点配置:
cat >/opt/redis_6379/conf/redis_6379.conf <<EOF
daemonize yes
bind 10.0.0.53 127.0.0.1
port 6379
pidfile /opt/redis_6379/pid/redis_6379.pid
logfile /opt/redis_6379/logs/redis_6379.log
databases 16
dir /data/redis_6379
dbfilename redis_6379.rdb
requirepass "123456"
masterauth "123456"
EOF

db01的配置:
cat >/opt/redis_26379/conf/redis_26379.conf << EOF
bind 10.0.0.51
port 26379
daemonize yes
logfile /opt/redis_26379/logs/redis_26379.log
dir /data/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 123456
EOF

db02的配置:
cat >/opt/redis_26379/conf/redis_26379.conf << EOF
bind 10.0.0.52
port 26379
daemonize yes
logfile /opt/redis_26379/logs/redis_26379.log
dir /data/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 123456
EOF

db03的配置:
cat >/opt/redis_26379/conf/redis_26379.conf << EOF
bind 10.0.0.53
port 26379
daemonize yes
logfile /opt/redis_26379/logs/redis_26379.log
dir /data/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 123456
EOF

停止redis进程
pkill redis

启动单节点
redis-server /opt/redis_6379/conf/redis_6379.conf

配置主从复制
redis-cli -h 10.0.0.52 -p 6379 -a 123456 slaveof 10.0.0.51 6379

redis-cli -h 10.0.0.53 -p 6379 -a 123456 slaveof 10.0.0.51 6379

启动哨兵
redis-sentinel /opt/redis_26379/conf/redis_26379.conf

Redis哨兵设置权重手动故障转移

1.查看权重
CONFIG GET slave-priority

2.设置权重
在其他节点把权重设为0
CONFIG SET slave-priority 0

3.主动发起重新选举
sentinel failover mymaster

4.恢复默认的权重
CONFIG SET slave-priority 100

CLUSTER MEET 10.0.0.51 6381
CLUSTER NODES
CLUSTER INFO
CLUSTER ADDSLOTS {0..5460}
CLUSTER REPLICATE 节点ID
CLUSTER FAILOVER

for i in {1..10000};do redis-cli -c -h 10.0.0.51 -p 6380 set {i}{i};echo "${i}";done

redis集群安装部署

0.重要概念
每个槽分配到的key的概率足够随机,足够平均
redis集群一共有16384个槽位
只要有一个槽不正常,整个集群不可用
平均分配到每个槽位的概率是大致一样的
重要的是槽的数量,而不是连不连续

0.所有节点删除前面实验的数据
pkill redis
rm -rf /opt/redis_*
rm -rf /data/redis_*

1.目录规划
主节点 6380
从节点 6381

2.db01创建命令
pkill redis
rm -rf /opt/redis_*
rm -rf /data/redis_*
mkdir -p /opt/redis_{6380,6381}/{conf,logs,pid}
mkdir -p /data/redis_{6380,6381}
cat >/opt/redis_6380/conf/redis_6380.conf<<EOF
bind 10.0.0.51
port 6380
daemonize yes
pidfile "/opt/redis_6380/pid/redis_6380.pid"
logfile "/opt/redis_6380/logs/redis_6380.log"
dbfilename "redis_6380.rdb"
dir "/data/redis_6380/"
cluster-enabled yes
cluster-config-file nodes_6380.conf
cluster-node-timeout 15000
EOF
cd /opt/
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_638* db02:/opt/
rsync -avz /opt/redis_638* db03:/opt/
redis-server /opt/redis_6380/conf/redis_6380.conf
redis-server /opt/redis_6381/conf/redis_6381.conf
ps -ef|grep redis

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

4.db03操作命令
find /opt/redis_638* -type f -name "*.conf"|xargs sed -i "/bind/s#51#53#g"
mkdir –p /data/redis_{6380,6381}
redis-server /opt/redis_6380/conf/redis_6380.conf
redis-server /opt/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
redis-cli -h db01 -p 6380 CLUSTER NODES
redis-cli -h db01 -p 6380 CLUSTER INFO

手动分配槽位

0.前提条件
无论集群有几个节点,都平均分配16384个槽

1.槽位规划
db01:6380 0-5460
db02:6380 5461-10921
db03:6380 10922-16383

2.分配槽位
redis-cli -h db01 -p 6380 CLUSTER ADDSLOTS {0..5460}
redis-cli -h db02 -p 6380 CLUSTER ADDSLOTS {5461..10922}
redis-cli -h db03 -p 6380 CLUSTER ADDSLOTS {10923..16383}
如果10922添加不了,进redis-cli -h db02 -p 6380
执行CLUSTER ADDSLOTS 10922
3.查看集群状态
redis-cli -h db01 -p 6380 CLUSTER info

手动部署复制关系

1.将集群节点信息保存在文本里,删除不必要的信息,删除81的信息
redis-cli -h 10.0.0.51 -p 6381 CLUSTER NODES
#db01的6380的ID 10.0.0.51:6380
#db02的6380的ID 10.0.0.52:6380
#db03的6380的ID 10.0.0.53:6380

2.操作其他节点
redis-cli -h 10.0.0.51 -p 6381 CLUSTER REPLICATE #db02的6380的ID
redis-cli -h 10.0.0.52 -p 6381 CLUSTER REPLICATE #db03的6380的ID
redis-cli -h 10.0.0.53 -p 6381 CLUSTER REPLICATE #db01的6380的ID

测试集群

1.尝试插入一条数据发现报错
10.0.1.51:6380> set k1 v1
(error) MOVED 12706 10.0.1.53:6380

2.目前的现象

  • 在db01的6380节点插入数据提示报错
  • 报错内容提示应该移动到db03的6380上
  • 在db03的6380上执行相同的插入命令可以插入成功
  • 在db01的6380节点插入数据有时候可以,有时候不行
  • 使用-c参数后,可以正常插入命令,并且节点切换到了提示的对应节点上

3.问题原因
因为集群模式又ASK路由规则,加入-c参数后,会自动跳转到目标节点处理
并且最后由目标节点返回信息

4.测试足够随机足够平均

 #!/bin/bash
for i in $(seq 1 1000)
 do
redis-cli -c -h db01 -p 6380 set k_${i} v_${i} && echo "set 
k_${i} is ok"
 done

使用工具搭建部署Redis Cluster

1.安装依赖-只要在db01上操作
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

2.还原环境-所有节点都执行!!!
pkill redis
rm -rf /data/redis_6380/*
rm -rf /data/redis_6381/*

3.启动集群节点-所有节点都执行
redis-server /opt/redis_6380/conf/redis_6380.conf
redis-server /opt/redis_6381/conf/redis_6381.conf
ps -ef|grep redis

4.使用工具搭建部署Redis
cd /opt/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

5.检查集群完整性
./redis-trib.rb check 10.0.0.51:6380

6.检查集群负载是否合规
./redis-trib.rb rebalance 10.0.0.51:6380

使用工具扩容节点

1.创建新节点-db01操作
mkdir -p /opt/redis_{6390,6391}/{conf,logs,pid}
mkdir -p /data/redis_{6390,6391}
cd /opt/
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
redis-server /opt/redis_6390/conf/redis_6390.conf
redis-server /opt/redis_6391/conf/redis_6391.conf
ps -ef|grep redis
redis-cli -c -h db01 -p 6380 cluster meet 10.0.0.51 6390
redis-cli -c -h db01 -p 6380 cluster meet 10.0.0.51 6391
redis-cli -c -h db01 -p 6380 cluster nodes

2.使用工具扩容步骤
cd /opt/redis/src/
./redis-trib.rb reshard 10.0.0.51:6380

第一次交互:每个节点保留多少个槽位
How many slots do you want to move (from 1 to 16384)? 4096

第二次交互:接收节点的ID是什么
What is the receiving node ID? 6390的ID

第三次交互:哪个节点需要导出
Source node #1: all

第四次交互:确认是否执行分配
Do you want to proceed with the proposed reshard plan (yes/no)? yes

3.检查集群完整性
./redis-trib.rb check 10.0.0.51:6380

4.检查集群负载是否合规
./redis-trib.rb rebalance 10.0.0.51:6380

5.调整复制顺序
redis-cli -h 10.0.0.53 -p 6381 CLUSTER REPLICATE 51-6390的ID
redis-cli -h 10.0.0.51 -p 6391 CLUSTER REPLICATE 51-6380的ID

6.测试写入脚本
[root@db01 ~]# cat for.sh

!/bin/bash

for i in (seq 1 100000) do redis-cli -c -h db01 -p 6380 set k_{i} v_{i} && echo "set k_{i} is ok"
done

7.测试读脚本

[root@db03 ~]# cat du.sh

 #!/bin/bash 

 for i in $(seq 1 100000)
do
redis-cli -c -h db01 -p 6380 get k_${i}
sleep 0.1 
done

使用工具收缩节点

1.使用工具收缩节点
cd /opt/redis/src/
./redis-trib.rb reshard 10.0.0.51:6380

2.第一次交互: 要迁移多少个
How many slots do you want to move (from 1 to 16384)? 1365

3.第二次交互: 输入第一个需要接收节点的ID
What is the receiving node ID? db01的6380的ID

4.第三次交互: 输入需要导出的节点的ID
Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes for the hash slots.
Type 'done' once you entered all the source nodes IDs.
Source node #1: db01的6390的ID
Source node #2: done

5.第四次交互: 确认
Do you want to proceed with the proposed reshard plan (yes/no)? yes

6.继续重复的操作,直到6390所有的槽位都分配给了其他主节点

7.确认集群状态是否正常,确认6390槽位是否都迁移走了

8.忘记以及下线节点
./redis-trib.rb del-node 10.0.0.51:6390 baf9585a780d9f6e731972613a94b6f3e6d3fb5e
./redis-trib.rb del-node 10.0.0.51:6391 e54a79cca258eb76fb74fc12dafab5ebac26ed90
CLUSTER SETSLOT 941 STABLE 恢复槽位的栏杆
集群快速从做(没有数据情况)
redis-cli -h 10.0.0.51 -p 6380 CLUSTER RESET
redis-cli -h 10.0.0.51 -p 6381 CLUSTER RESET
redis-cli -h 10.0.0.52 -p 6380 CLUSTER RESET
redis-cli -h 10.0.0.52 -p 6381 CLUSTER RESET
redis-cli -h 10.0.0.53 -p 6380 CLUSTER RESET
redis-cli -h 10.0.0.53 -p 6381 CLUSTER RESET

redis-cli -h 10.0.0.51 -p 6380 CLUSTER meet 10.0.0.51 6381
redis-cli -h 10.0.0.51 -p 6380 CLUSTER meet 10.0.0.52 6380
redis-cli -h 10.0.0.51 -p 6380 CLUSTER meet 10.0.0.52 6381
redis-cli -h 10.0.0.51 -p 6380 CLUSTER meet 10.0.0.53 6380
redis-cli -h 10.0.0.51 -p 6380 CLUSTER meet 10.0.0.53 6381
redis-cli -h 10.0.0.51 -p 6380 cluster nodes

redis-cli -h 10.0.0.51 -p 6380 cluster addslots {0..5460}
redis-cli -h 10.0.0.52 -p 6380 cluster addslots {5461..10922}
redis-cli -h 10.0.0.53 -p 6380 cluster addslots {10923..16383}
redis-cli -h 10.0.0.51 -p 6380 cluster info

数据迁移

1.安装工具
yum install libtool autoconf automake -y
cd /opt/
git clone https://github.com/vipshop/redis-migrate-tool.git
cd redis-migrate-tool/
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

3.单节点生成测试数据
mkdir -p /data/redis_6379
mkdir -p /opt/redis_6379/{conf,pid,logs}
cat >/opt/redis_6379/conf/redis_6379.conf <<EOF
daemonize yes
bind 10.0.0.51 127.0.0.1
port 6379
pidfile /opt/redis_6379/pid/redis_6379.pid
logfile /opt/redis_6379/logs/redis_6379.log
databases 16
dir /data/redis_6379
dbfilename redis_6379.rdb
EOF
redis-server /opt/redis_6379/conf/redis_6379.conf

cat >input_6379.sh <<EOF

!/bin/bash

for i in {1..1000}
do
redis-cli -c -h db01 -p 6379 set oldzhang_${i} oldzhang_${i}
echo "set oldzhang_${i} is ok"
done
EOF

4.运行工具迁移单节点数据到集群
redis-migrate-tool -c 6379_to_6380.conf

5.运行工具验证数据是否迁移完成
redis-migrate-tool -c 6379_to_6380.conf
redis-migrate-tool -c 6379_to_6380.conf -C redis_check

第七章 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_6381/redis_6381.rdb db01_6381.rdb
scp db02:/data/redis_6381/redis_6381.rdb db02_6381.rdb
scp db03:/data/redis_6381/redis_6381.rdb db03_6381.rdb

3.清空所有节点的数据
redis-cli -h db01 -p 6380 FLUSHALL
redis-cli -h db02 -p 6380 FLUSHALL
redis-cli -h db03 -p 6380 FLUSHALL

4.编写配置文件
cat >rdb_to_cluter.conf<<EOF
[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
EOF

8.使用工具导入
redis-migrate-tool -c rdb_to_cluter.conf

使用工具分析key的大小

0.需求背景
redis的内存使用太大键值太多,不知道哪些键值占用的容量比较大,而且在线分析会影响性能.

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

3.使用工具分析:
cd /data/redis_6379/
rdb -c memory redis_6379.rdb -f redis_6379.rdb.csv

4.过滤分析
awk -F"," '{print 4,3}' redis_6379.rdb.csv |sort -r

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

生产注意:

1.一定要限制内存最大使用
maxmemory <bytes>

2.限制内存多少
redis本身使用了5G 系统内存为32G
10G用满后 分析一下键值大小
16G用满后 分析一下键值大小
最多给到24G 剩下的内存给系统和持久化时候用
24G用满后

maxmemory-policy noeviction

3.硬盘用SSD

4.集群注意
数据迁移或者主从关系发生改变,尽量在业务低峰期操作
一定要等集群状态稳定之后,在操作下一步

5.集群下线节点
先下线从节点,在下线主节点

6.禁止使用keys *
替代方案使用scan

7.故障转移时间不要调太短

8.RDB持久化可以在从节点上操作

9.如果同时需要RDB和AOF
挂载2块SSD
通过配置,AOF和RDB保存在不同的磁盘上

10.redis的机器上不要跑其他的服务,专机专用

11.网卡要快

12.监控要跟上

13.不要使用swap分区

故障案例

问题背景:
使用工具执行槽位迁移的时候,迁移过程中中断了

问题现象:

1.使用工具check的时候提示941槽的状态为import导入状态
[ERR] Nodes don't agree about c onfigu ration !
5P Check for open sLots
[WARNING] Node 10.0.0.51:6390 has slots in inporting state (941).

2.登录到不同节点查看集群节点信息发现不同的节点,显示的槽位不一样
6390显示 941 槽在 6380身上
6380显示 941 槽在 6390身上

3.登录到6380上查看槽位显示一切正常
登录到6390显示槽位不正常,有一个导入的符号941<节点ID
941<节点ID

排查步骤:
1.使用工具fix,行不通,报错
2.登录到有问题的节点6390身上,执行恢复槽位状态的命令,执行完之后,槽位状态显示正常
CLUSTER SETSLOT 941 STABLE
3.再次尝试使用fix,还是行不通,依然报错
4.尝试登陆6390,删除941槽位
CLUSTER DELSLOTS 941
5.再次尝试使用fix,还是行不通,依然报错
6.尝试登陆6380,删除941槽位
7.再次尝试使用fix,不报错了
8.尝试使用check,不报错
9.重新分配槽位


QQ图片20191203152748.png
槽位.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容