Redis-5.x 第1章 关系型与非关系型 1 2 关系型: mysql oracle 非关系型:redis mongo ES
第2章 Redis重要特性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 1 .速度快 c 语言写的 代码优雅 单线程架构 2 .支持多种数据结构 字符串,哈希,列表,集合,有序集合,地理位置 3 .丰富的功能 天然计数器 健过期功能 消息队列 4 .支持客户端语言多 php,java,python 5 .数据持久化 所有的数据都运行在内存中 支持2 种格式持久化数据AOF RDB AOF &RDB 6 .自带多种高可用架构 主从 哨兵 集群
第3章 redis应用场景 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 1.缓存-键过期时间 把session会话存在redis,过期删除 缓存用户信息,缓存Mysql部分数据,用户先访问redis,redis没有再访问mysql,然后回写给redis 商城优惠卷过期时间 2.排行榜-列表&有序集合 热度/点击数排行榜 直播间礼物积分排行 3.计数器-天然支持计数器 帖子浏览数 视频播放数 评论数 点赞/踩 4.社交网络-集合 粉丝 共同好友 兴趣爱好 标签 5.消息队列-发布订阅 配合ELK缓存收集来的日志
第4章 Redis安装部署 1.redis官网
2.版本选择 1 2 3 4 2.x very old 3.x redis-cluster 4.x 混合持久化 5.x 新增加了流处理类型 最新稳定版
3.规划目录 1 2 3 /data /soft 下载目录 /opt/redis_6379/{conf,logs,pid} 安装目录,日志目录,pid目录,配置目录 /data /redis_6379/ 数据目录
4.安装命令 1 2 3 4 5 6 7 8 mkdir /data/soft -p cd /data/soft wget http: tar xf redis-5.0 .7 .tar.gz -C /opt/ ln -s /opt/redis-5.0 .7 /opt/redis cd /opt/redis make make install
5.配置文件 1 2 3 4 5 6 7 8 9 mkdir -p /opt/redis_6379/{conf,pid,logs} mkdir -p /data/redis_6379 cat >/opt/redis_6379/conf/redis_6379.conf<< EOF daemonize yes bind 127.0.0.1 10.0.0.51port 6379 pidfile /opt/redis_6379/pid/redis_6379.pid logfile /opt/redis_6379/logs/redis_6379.log EOF
6.启动命令 1 redis-server /opt/redis_6379/conf/redis_6379.conf
7.检查 1 2 ps -ef|grep redis netstat -lntup| grep 6379
8.连接redis终端 1 2 3 4 5 6 7 [root@db01 ~] # redis-cli 127.0 .0 .1 :6379 > 127.0 .0 .1 :6379 > set k1 v1 OK 127.0 .0 .1 :6379 > get k1 "v1 " 127.0 .0 .1 :6379 >
9.关闭命令 1 2 3 4 5 kill pkill redis-cli >SHUTDOWN - redis-cli shutdown
10.system启动配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 groupadd -g 1000 redis useradd -u 1000 -g 1000 -M -s /sbin/nologin chown -R redis:redis /data/redis* chown -R redis:redis /opt/redis* cat >/usr/lib/systemd/system/redis.service<<EOF [Unit ] Description=Redis persistent key-value database After=network.target After=network-online.target Wants=network-online.target [Service ] ExecStart=/usr/local/bin/redis /opt/redis_6379/conf/redis_6379.conf --supervised systemd ExecStop=/usr/local/bin/redis-cli -h $(ifconfig eth0|awk 'NR==2{print $2}' ) -p 6379 shutdown Type=notify User=redis Group=redis RuntimeDirectory=redis RuntimeDirectoryMode=0755 [Install ] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl start redis
第5章 Redis全局命令 全局命令是指对所有数据类型都通用的命令
0.redis数据格式
1.写入测试key 1 2 3 set k1 v1set k2 v2 set k3 v3
2.查看所有的key !!!危险命令!!!此操作未满30岁禁止请在家人的看管下执行
3.查看有多少个key
4.查看某个Key是否存在 1 2 3 4 5 6 EXISTS k1 状态码: 0 表示这个key不存在 1 表示这个key存在 N 表示存在N个key
5.删除key 1 2 3 4 5 6 7 DEL k1 DEL k1 k2 状态码: 0 表示这个key不存在 1 表示这个key存在,并且删除成功了 N 表示N个key存在,并且删除成功了N个key
6.键过期 设置过期时间
1 2 3 4 5 EXPIRE k1 10 状态码: 0 这个key不存在 1 这个key存在,并且设置过期时间成功
查看keys是否过期
1 2 3 4 5 6 TTL k1 状态码: -1 这个key存在,并且没有设定存活周期,永不过期 -2 这个key不存在 N 这个key存在,并且在N秒后过期
取消过期时间:
1 2 3 4 5 6 7 8 第一种方法: PERSIST k1 第二种方法: set k1 v1结论: 过期后的key会被直接删除
第6章 字符串操作 1.设置一个key
2.查看一个key
3.设置多个key 1 MSET k1 v1 k2 v2 k3 v3 k4 v4
4.查看多个key
5.天然计数器 1 2 3 4 5 6 7 8 9 10 11 12 13 加1: SET k1 1 INCR k1 GET k1 加N: INCRBY k1 100 减1: INCRBY k1 -1 减N: INCRBY k1 -100
第7章 列表操作 1.插入列表 1 2 LPUSH: 从列表左侧插入数据 RPUSH: 从列表右侧插入数据
2.查看列表长度
3.查看列表内容
4.删除列表元素 1 2 3 4 5 LPOP: 从列表左边删除一个元素 RPOP: 从列表右边删除一个元素 LPOP list1 RPOP list1
5.删除整个列表
第8章 hash操作 1.mysql数据如何缓存到redis 1 2 3 4 5 6 7 8 9 10 11 12 mysql 存储格式:user id name job age 1 bobo IT 28 2 json py 25 3 hao bug 26 hash 类型存储格式:key field value field value user :1 name bobo job IT age 28user :2 name json job py age 25user :3 name hao job bug age 26
2.创建一个Hash数据 1 2 3 HMSET user :1 name bobo job IT age 28HMSET user :2 name json job py age 29HMSET user :3 name hao job bug age 19
3.查看hash里指定的值 1 2 3 4 select name from user where id =1 ; HMGET user:1 name HMGET user:1 name job age
4.查看Hash里所有的值 1 2 3 select * from user where id =1 ;HGETALL user:1
第9章 集合操作 set 1.创建集合 1 2 SADD set1 1 2 3 SADD set2 1 3 5 7
2.查看集合成员 1 2 SMEMBERS set1 SMEMBERS set2
3.查看集合的交集 1 2 3 127.0 .0 .1 :6379 > SINTER set1 set2 1) "1" 2) "3"
4.查看集合的并集 1 2 3 4 5 6 127.0.0.1:6379> SUNION set1 set21 ) "1" 2 ) "2" 3 ) "3" 4 ) "5" 5 ) "7"
5.查看集合的差集 1 2 3 4 5 6 127.0 .0 .1 :6379 > SDIFF set1 set2 1) "2" 127.0 .0 .1 :6379 > SDIFF set2 set1 1) "5" 2) "7"
6.删除一个成员
6.注意
第10章 有序集合操作 1.添加成员 1 2 3 4 ZADD SZ3 100 json ZADD SZ3 90 bobo ZADD SZ3 99 xiaocancan ZADD SZ3 98 bughao
2.计算成员个数
3.计算某个成员分数
4.按照降序查看成员名次: 1 2 ZRANK SZ3 json ZRANK SZ3 bobo
5.按照升序查看成员名次: 1 2 ZREVRANK SZ3 json ZREVRANK SZ3 bobo
6.删除成员
7.增加成员分数 1 2 ZINCRBY SZ3 2 xiaocancan ZSCORE SZ3 xiaocancan
8.返回指定排名范围的成员 1 2 ZRANGE SZ3 0 3 ZRANGE SZ3 0 3 WITHSCORES
9.返回指定分数范围的成员 1 2 ZRANGEBYSCORE SZ3 95 100 ZRANGEBYSCORE SZ3 95 100 WITHSCORES
10.返回指定分数范围的成员的个数
第11章 持久化
RDB流程图
AOF流程图
1.RDB和AOF介绍 1 2 3 4 5 6 7 RDB:类似于快照的形式,当前内存里的状态持久化到硬盘里 优点:压缩格式/恢复速度快 缺点:不是实时的,可能会丢失数据,操作比较重 AOF:类似于mysql的binlog,可以设置为每秒/每次操作以追加的形式持久化 优点:安全,最多损失1秒的数据,可读 缺点:文件比较大,恢复速度慢
2.配置RDB 1 2 3 4 5 save 900 1 save 300 10 save 60 10000 dbfilename redis.rdb dir /data /redis_6379/
3.RDB结论 1 2 3 4 5 1.没有配置save参数时,shutdown不会持久化保存 2.没有配置save参数时,可以手动执行bgsave触发持久化 3.在配置了save参数后,shutdown,kill ,pkill都会自动触发bgsave 4.恢复的时候,rdb文件名要和配置文件里写的一样。 5.RDB高版本兼容低版本,低版本不兼容高版本
4.AOF配置 1 2 3 appendonly yes appendfilename "redis.aof" appendfsync everysec
5.AOF重写机制 1 2 3 4 5 6 7 8 执行的命令 aof记录 redis的数据 set k1 v1 set k1 k1 set k2 v2 set k2 k1 k2 set k3 v3 set k3 k1 k2 k3 del k1 del k1 k2 k3 del k2 del k2 k3 实际有意义的只有一条记录: set k3
6.aof和rdb实验 实验背景:
1 aof和rdb同时存在的时候,redis重启会读取哪一个数据?
实验步骤:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 set k1 v1set k2 v2 bgsave RDB k1 k2 mv redis.rdb /opt/ flushall set k3 v3set k4 v4AOF k3 k4 mv redis.aof /opt/ pkill redis rm -rf /data /redis_6379
结论:
1 当aof和rdb同时存在时,重启redis会优先读取aof的内容
7.如何选择是rdb还是aof 1 2 3 4 5 https: 1. 开启混合模式2. 开启aof3. 不开启rdb4. rdb采用定时任务的方式定时备份
8.aof文件故障模拟实验结论 1 2 3 1.aof 文件损坏之后,使用修复工具,一刀流,从aof 文件出错的地方开始到最后全部删掉 2.任何操作之前,先备份数据 3.aof 备份一般情况最多损失1秒的数据
9.实验:如果设置了过期时间,恢复数据会如何处理 1 2 3 1.aof 文件会记录下过期的时间 2.恢复的时候会去对比记录的过期时间和当前时间,如果超过了,就删除key 3.key 的过期时间不受备份恢复影响
第12章 redis用户认证 1.写入配置文件
2.使用密码登陆 第一种:
1 2 3 4 5 6 [root@db01 ~] # redis-cli 127.0 .0 .1 :6379 > AUTH cookzhang OK 127.0 .0 .1 :6379 > set k1 v1 OK
第二种:
1 redis-cli -a cookz get k1
3.为什么redis的密码认证这么简单? 1 2 1.redis 一般都部署在内网环境,默认是比较安全的环境 2.有同学担心密码写在配置文件里,开发不允许登陆到Linux 服务器上,但是可以连接到redis ,设个密码安全些
第13章 禁用或重命名危险命令 1.禁用危险命令 1 2 3 4 5 6 rename-command CONFIG "" rename-command KEYS "" rename-command SHUTDOWN "" rename-command FLUSHALL "" rename-command DEL "" rename-command FLUSHDB ""
2.来自json的灵魂拷问:shutdown禁用了 让后用kill? 1 2 3 4 5 6 rename-command CONFIG "" rename-command KEYS "" rename-command SHUTDOWN "qq526195417" rename-command FLUSHALL "" rename-command DEL "byebye" rename-command FLUSHDB ""
第14章 Redis主从复制 1.快速部署第二台服务器 1 2 3 4 5 6 rsync -avz 10.0 .0 .51 :/opt/* /opt/* mkdir /data/redis_6379/ -p cd /opt/redis make install sed -i 's#51#52#g' /opt/redis_6379/conf/redis_6379.conf redis-server /opt/redis_6379/conf/redis_6379.conf
2.db01插入测试命令 1 for i in {1..1000};do redis-cli -h 10.0.0.51 set ${i} ${i} ;done
3.配置主从复制 方法1:临时生效
1 redis-cli -h 10.0 .0 .52 slaveof 10.0 .0 .51 6379
方法2:写进配置文件
4.主从复制的流程 1.简单流程:
1 2 3 4 5 6 7 8 1.从节点发送同步请求到主节点 2.主节点接收到从节点的请求之后,做了如下操作 - 立即执行bgsave将当前内存里的数据持久化到磁盘上 - 持久化完成之后,将rdb文件发送给从节点 3.从节点从主节点接收到rdb文件之后,做了如下操作 - 清空自己的数据 - 载入从主节点接收的rdb文件到自己的内存里 4.后面的操作就是和主节点实时的了
5.取消复制
6.主从复制注意 1 2 3 4 5 6 7 8 9 10 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.从节点会清空自己原有的数据,如果同步的对象写错了,就会导致数据丢失 5.从库和主库后续的同步依靠的是redis的SYNC协议,而不是RDB文件,RDB文件只是第一次建立同步时使用。 6.从库也可以正常的持久化文件
7.安全的操作 无论是同步,无论是主节点还是从节点,请先备份一下数据
第15章 Redis哨兵
1.哨兵的作用 1 2 1.解决了主从复制故障需要人为干预的问题 2.提供了自动的高可用解决方案
2.目录和端口规划 1 2 redis节点: 6379 哨兵节点: 26379
3.部署3台redis单节点 db01操作: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 pkill redis cat >/opt/redis_6379/conf/redis_6379.conf <<EOF daemonize yes bind 127.0.0.1 10.0.0.51port 6379 pidfile "/opt/redis_6379/pid/redis_6379.pid" logfile "/opt/redis_6379/logs/redis_6379.log" dbfilename "redis.rdb" dir "/data/redis_6379" appendonly yes appendfilename "redis.aof" appendfsync everysec EOF systemctl start redis redis-cli
db02和db03的操作: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 pkill redis rm -rf /opt/redis* rsync -avz 10.0 .0 .51 :/usr/local/bin/redis-* /usr/local/bin rsync -avz 10.0 .0 .51 :/usr/lib/systemd/system/redis .service /usr/lib/systemd/system/ mkdir /opt/redis_6379/{conf,logs,pid} -p mkdir /data/redis_6379 -p cat >/opt/redis _6379/conf/redis_6379.conf <<EOF daemonize yes bind 127.0 .0 .1 $(ifconfig eth0 |awk 'NR==2{print $2}') port 6379 pidfile "/opt/redis_6379/pid/redis_6379.pid" logfile "/opt/redis_6379/logs/redis_6379.log" dbfilename "redis.rdb" dir "/data/redis_6379" appendonly yes appendfilename "redis.aof" appendfsync everysec EOF useradd redis -M -s /sbin/nologin chown -R redis:redis /opt/redis* chown -R redis:redis /data/redis* systemctl daemon-reload systemctl start redis redis-cli
4.配置主从复制 1 2 3 redis-cli -h 10.0 .0 .52 slaveof 10.0 .0 .51 6379redis-cli -h 10.0 .0 .53 slaveof 10.0 .0 .51 6379redis-cli -h 10.0 .0 .51 info Replication
5.部署哨兵节点-3台机器都操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 mkdir -p /data /redis_26379 mkdir -p /opt/redis_26379/{conf,pid,logs} cat >/opt/redis_26379/conf/redis_26379.conf << EOF bind $(ifconfig eth0|awk 'NR==2{print $2}' ) port 26379 daemonize yes logfile /opt/redis_26379/logs/redis_26379.log dir /data /redis_26379 sentinel monitor myredis 10.0 .0 .51 6379 2 sentinel down-after-milliseconds myredis 3000 sentinel parallel-syncs myredis 1 sentinel failover-timeout myredis 18000 EOF chown -R redis:redis /data /redis* chown -R redis:redis /opt/redis*
参数解释:
1 2 3 4 5 6 7 8 sentinel monitor mymaster 10.0.0.51 6379 2 sentinel down-after-milliseconds mymaster 3000 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 180000
6.编写哨兵system配置文件-3台机器都操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 cat >/usr/lib/systemd/system/redis-sentinel.service<<EOF [Unit ] Description=Redis persistent key-value database After=network.target After=network-online.target Wants=network-online.target [Service ] ExecStart=/usr/local/bin/redis-sentinel /opt/redis_26379/conf/redis_26379.conf --supervised systemd ExecStop=/usr/local/bin/redis-cli -h $(ifconfig eth0|awk 'NR==2{print $2}' ) -p 26379 shutdown Type=notify User=redis Group=redis RuntimeDirectory=redis RuntimeDirectoryMode=0755 [Install ] WantedBy=multi-user.target EOF systemctl daemon-reload
7.启动哨兵并检查 1 systemctl start redis-sentinel
8.验证主节点 1 2 3 redis-cli -h 10.0 .0 .51 -p 26379 Sentinel get-master-addr-by-name myredis redis-cli -h 10.0 .0 .52 -p 26379 Sentinel get-master-addr-by-name myredis redis-cli -h 10.0 .0 .53 -p 26379 Sentinel get-master-addr-by-name myredis
9.模拟故障转移 关闭主节点服务上的所有redis进程 观察其他2个节点会不会发生选举 查看配置文件里会不会自动更新 查看新的主节点能不能写入 查看从节点能否正常同步
10.模拟故障修复上线 启动单节点 启动哨兵
11.来自json的灵魂发问:能够给redis 节点加权 来确定优先备选主节点嘛? 流程说明: 设置其他节点的权重为0 手动发起重新选举 观察所有节点消息是否同步 观察切换结果是否符合预期
命令解释:
1 2 3 查询命令:CONFIG GET slave-priority 设置命令:CONFIG SET slave-priority 0 主动切换:sentinel failover myredis
操作命令:
1 2 3 redis-cli -h 10.0 .0 .52 -p 6379 CONFIG SET slave-priority 0redis-cli -h 10.0 .0 .53 -p 6379 CONFIG SET slave-priority 0redis-cli -h 10.0 .0 .51 -p 26379 sentinel failover myredis
验证选举结果:
1 redis-cli -h 10.0 .0 .51 -p 26379 Sentinel get-master-addr-by-name myredis
第16章 手动部署Redis集群
集群架构图1
集群架构图2
1.烧饼的不足 资源利用率不高 主库压力大 连接过程繁琐
2.集群重要概念 1 2 3 4 5 6 7 8 9 redis集群,无论有几个节点,一共只有16384个槽 所有的槽位都必须分配,哪怕有1个槽位不正常,整个集群都不能用 每个节点的槽的顺序不重要,重点是数量 hash 算法足够随机,足够平均每个槽被分配到数据的概率是相当的 集群的高可用依赖于主从复制 集群拥有自己的配置文件,动态更新,不要手欠修改 集群通讯会使用基础端口号+10000的端口,这个是自动创建的,不是配置文件配置的 集群槽位分配比例允许误差在%2之间
3.目录规划
4.db01的操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 ssh-keygen ssh-copy-id 10.0 .0 .52 ssh-copy-id 10.0 .0 .53 pkill 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/" appendonly yes appendfilename "redis.aof" appendfsync everysec 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 chown -R redis:redis /opt/redis_* chown -R redis:redis /data/redis_* cat >/usr/ lib/systemd/system/redis-master.service<<EOF [Unit] Description=Redis persistent key-value database After=network.target After=network-online.target Wants=network-online.target [Service] ExecStart=/usr/ local/bin/redis-server /opt/redis_6380/conf/redis_6380.conf --supervised systemd ExecStop=/usr/ local/bin/redis-cli -h $(ifconfig eth0|awk 'NR==2{print $2}' ) -p 6380 shutdown Type=notify User=redis Group=redis RuntimeDirectory=redis RuntimeDirectoryMode=0755 [Install] WantedBy=multi-user.target EOF cd /usr/lib/systemd/system/ cp redis-master.service redis-slave.service sed -i 's#6380#6381#g' redis-slave.service systemctl daemon-reload systemctl start redis-master systemctl start redis-slave ps -ef|grep redis rsync -avz /opt/redis_638* 10.0 .0 .52 :/opt/ rsync -avz /opt/redis_638* 10.0 .0 .53 :/opt/ rsync -avz /usr/lib/systemd/system/redis-*.service 10.0 .0 .52 :/usr/ lib/systemd/system/redis-master.service rsync -avz /usr/lib/systemd/system/redis-*.service 10.0 .0 .53 :/usr/ lib/systemd/system/redis-master.service
5.db02的操作 1 2 3 4 5 6 7 8 9 10 11 pkill redis find /opt/redis_638* -type f -name "*.conf" |xargs sed -i "/bind/s#51#52#g" cd /usr/lib/systemd/system/sed -i 's#51#52#g' redis-*.service mkdir –p /data/redis_{6380,6381} chown -R redis:redis /opt/redis_* chown -R redis:redis /data/redis_* systemctl daemon-reload systemctl start redis-master systemctl start redis-slave ps -ef|grep redis
6.db03的操作 1 2 3 4 5 6 7 8 9 10 11 pkill redis find /opt/redis_638* -type f -name "*.conf" |xargs sed -i "/bind/s#51#53#g" cd /usr/lib/systemd/system/sed -i 's#51#53#g' redis-*.service mkdir –p /data/redis_{6380,6381} chown -R redis:redis /opt/redis_* chown -R redis:redis /data/redis_* systemctl daemon-reload systemctl start redis-master systemctl start redis-slave ps -ef|grep redis
7.集群手动发现节点 1 2 3 4 5 6 redis-cli -h db01 -p 6380 CLUSTER MEET 10.0 .0 .52 6380redis-cli -h db01 -p 6380 CLUSTER MEET 10.0 .0 .53 6380redis-cli -h db01 -p 6380 CLUSTER MEET 10.0 .0 .51 6381redis-cli -h db01 -p 6380 CLUSTER MEET 10.0 .0 .52 6381redis-cli -h db01 -p 6380 CLUSTER MEET 10.0 .0 .53 6381redis-cli -h db01 -p 6380 CLUSTER NODES
8.集群手动分配槽位 1.槽位规划 1 2 3 db01 :6380 5461 0-5460 db02 :6380 5461 5461-10921 db03 :6380 5462 10922-16383
2.分配槽位 1 2 3 redis-cli -h db01 -p 6380 CLUSTER ADDSLOTS {0. .5460 } redis-cli -h db02 -p 6380 CLUSTER ADDSLOTS {5461. .10921 } redis-cli -h db03 -p 6380 CLUSTER ADDSLOTS {10922. .16383 }
3.查看集群状态 1 2 redis-cli -h db01 -p 6380 CLUSTER NODES redis-cli -h db01 -p 6380 CLUSTER INFO
9.手动部署复制关系 0.先获取集群节点信息 1 redis-cli -h db01 -p 6380 CLUSTER NODES
1.先删除所有6381的内容和不需要内容 1 2 3 6380的ID 10.0 .0 .51 6380的ID 10.0 .0 .53 6380的ID 10.0 .0 .52
2.画图 3.确定复制关系 1 2 3 redis-cli -h db01 -p 6381 CLUSTER REPLICATE 52 的6380 的ID redis-cli -h db02 -p 6381 CLUSTER REPLICATE 53 的6380 的ID redis-cli -h db03 -p 6381 CLUSTER REPLICATE 51 的6380 的ID
4.检查复制关系 1 redis-cli -h db01 -p 6380 CLUSTER NODES
10.集群插入数据 1.尝试插入一条数据发现报错 1 2 10.0 .0 .51 :6380 > set k1 v1 (error ) MOVED 12706 10.0 .0 .53 :6380
2.目前的现象 在db01的6380节点插入数据提示报错 报错内容提示应该移动到db03的6380上 在db03的6380上执行相同的插入命令可以插入成功 在db01的6380节点插入数据有时候可以,有时候不行 使用-c参数后,可以正常插入命令,并且节点切换到了提示的对应节点上
3.问题原因 因为集群模式有ASK路由规则,加入-c参数后,会自动跳转到目标节点处理 并且最后由目标节点返回信息
11.验证集群是否足够足迹足够平均 0.写入测试数据 1 for i in {1..10000};do redis-cli -c -h db01 -p 6380 set k_${i} v_${i} ;echo ${i} ;done
1.验证足够平均:
2.验证足够随机: 1 2 redis-cli -c -h db03 -p 6380 keys \* > keys_all.txt cat keys_all.txt |awk -F "_" '{print $2 }'|sort -rn
3.允许节点的key在2%误差的依据来源: 1 2 3 4 5 6 7 [root@db01 /opt/redis/src] # redis-cli --cluster rebalance 10.0 .0 .51 6380>>> Performing Cluster Check (using node 10.0 .0 .51 :6380) [OK] All nodes agree about slots configuration .>>> Check for open slots ... >>> Check slots coverage ... [OK] All 16384 slots covered .*** No rebalancing needed ! All nodes are within the 2.00 % threshold .
4.检查集群健康状态: 1 2 3 4 5 6 [root@db01 /opt/redis/src] 10.0.0.51:6380 (ccaa5dcb...) -> 3343 keys | 5461 slots | 1 slaves.10.0.0.53:6380 (a69e46ea...) -> 3343 keys | 5462 slots | 1 slaves.10.0.0.52:6380 (b2719c41...) -> 3314 keys | 5461 slots | 1 slaves.[OK] 10000 keys in 3 masters. 0 .61 keys per slot on average.
第17章 实战-槽位分配错误如何调整 1.故障背景 某日某豪接到任务,需要部署redis集群结果不小心无脑复制粘贴,把所有的槽都分配给了1个节点,还没发现,然后就交付使用了,过了1天才发现问题。
而此时,已经有不少数据写入了,如何在不丢失数据的情况下解决这个问题?
2.前提 数据不能丢,最好不中断业务
3.实验现象 1 2 3 4 5 6 [root@db01 ~] 10.0.0.51:6380 (ccaa5dcb...) -> 1000 keys | 16384 slots | 3 slaves.10.0.0.53:6380 (a69e46ea...) -> 0 keys | 0 slots | 0 slaves.10.0.0.52:6380 (b2719c41...) -> 0 keys | 0 slots | 0 slaves.[OK] 1000 keys in 3 masters. 0 .06 keys per slot on average.
解决思路1:备份数据,重做集群,导入数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 来自json的灵魂发问: redis.cof的数据 集群重做后 aof文件里面的数据能被hash嘛? 备份数据: redis-cli -c -h db01 -p 6380 db01:6380 > BGREWRITEAOF cp redis.aof redis.aof-1000. bak 重做集群: redis-cli -h db01 -p 6380 FLUSHALL redis-cli -h db02 -p 6380 FLUSHALL redis-cli -h db03 -p 6380 FLUSHALL redis-cli -h db01 -p 6380 CLUSTER RESET redis-cli -h db02 -p 6380 CLUSTER RESET redis-cli -h db03 -p 6380 CLUSTER RESET redis-cli -h db01 -p 6380 CLUSTER MEET 10.0 .0 .52 6380 redis-cli -h db01 -p 6380 CLUSTER MEET 10.0 .0 .53 6380 redis-cli -h db01 -p 6380 CLUSTER NODES redis-cli -h db01 -p 6380 CLUSTER ADDSLOTS {0. .5460 } redis-cli -h db02 -p 6380 CLUSTER ADDSLOTS {5461. .10921 } redis-cli -h db03 -p 6380 CLUSTER ADDSLOTS {10922. .16383 } redis-cli --cluster info 10.0 .0 .51 6380 实验结论: 重启后所有的数据还是在db01上。 db01重启后数据虽然可以写入,但是访问的时候还是按照正常的hash规则去分配的,所以db01的数据实际上是没用的。 所以这样的方法是不可行的。 相关日志: 16790 :M 12 Mar 2020 10 :08 :08.875 # I have keys for slot 5812 , but the slot is assigned to another node. Setting it to importing state.16790 :M 12 Mar 2020 10 :08 :08.875 # I have keys for slot 5821 , but the slot is assigned to another node. Setting it to importing state.16790 :M 12 Mar 2020 10 :08 :08.875 # I have keys for slot 5842 , but the slot is assigned to another node. Setting it to importing state.
解决思路2:获得所有key的名称,导出再导入 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 0.重新制作一个测试集群,槽位分布和线上出错的一样 1.将线上环境里的aof导出来 2.恢复到测试的集群里 3.收集所有的key redis-cli -c -h db01 -p 6380 keys \* > keys_all.txt 4.编写脚本遍历所有的key获取值 cat >get_key.sh<<EOF #!/bin/bash for key in $(cat keys_all.txt)do value=$(redis-cli -c -h 10.0.0.51 -p 6380 get ${key} ) echo redis-cli -c -h 10.0.0.51 -p 6380 set ${key} ${value} >> backup_all_key.txt done EOF 5.按照正常槽位分配去重新初始化集群 redis-cli -h db01 -p 6380 FLUSHALL redis-cli -h db02 -p 6380 FLUSHALL redis-cli -h db03 -p 6380 FLUSHALL redis-cli -h db01 -p 6380 CLUSTER RESET redis-cli -h db02 -p 6380 CLUSTER RESET redis-cli -h db03 -p 6380 CLUSTER RESET redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.52 6380 redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.53 6380 redis-cli -h db01 -p 6380 CLUSTER NODES redis-cli -h db01 -p 6380 CLUSTER ADDSLOTS {0..5460} redis-cli -h db02 -p 6380 CLUSTER ADDSLOTS {5461..10921} redis-cli -h db03 -p 6380 CLUSTER ADDSLOTS {10922..16383} redis-cli --cluster info 10.0.0.51 6380 6.执行导入脚本 bash backup_all_key.txt 7.检查是否导入成功 redis-cli --cluster info 10.0.0.51 6380 8.测试环境没问题之后再去生产环境操作
解决思路3: 流水线 pipline 1 2 3 4 5 6 7 8 9 10 前提条件: 1.了解aof 格式 2.了解新版本redis 默认是开启混合模式的 3.需要修改为普通的aof 格式并重启 4.恢复时使用-c 参数无效,需要在每一个节点都执行 命令: redis-cli -c -h 10.0 .0 .51 -p 6380 --pipe < redis .aof redis-cli -c -h 10.0 .0 .52 -p 6380 --pipe < redis .aof redis-cli -c -h 10.0 .0 .53 -p 6380 --pipe < redis .aof
解决思路4: 使用redis-cli工具重新分配槽位 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 重新分配槽位 redis-cli --cluster reshard 10.0.0.51:6380 第一次交互:输入迁出的槽的数量 How many slots do you want to move (from 1 to 16384)? 5461 第二次交互:输入接受的ID What is the receiving node ID? db02的6380的ID 第三次交互:输入发送者的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 Source node 第四次交互:YES! 重复上面的操作,知道所有的节点槽位都分配正确
解决思路5:直接使用工具在线导入 1 redis-cli --cluster import 10.0 .0 .51 :6380 --cluster-copy --cluster-replace --cluster-from 10.0 .0 .51 :6379
第18章 使用工具自动部署redis集群 1.恢复集群初始化 1 2 3 4 5 6 7 8 9 10 11 12 13 redis-cli -h db01 -p 6380 FLUSHALL redis-cli -h db02 -p 6380 FLUSHALL redis-cli -h db03 -p 6380 FLUSHALL redis-cli -h db01 -p 6381 FLUSHALL redis-cli -h db02 -p 6381 FLUSHALL redis-cli -h db03 -p 6381 FLUSHALL redis-cli -h db01 -p 6380 CLUSTER RESET redis-cli -h db02 -p 6380 CLUSTER RESET redis-cli -h db03 -p 6380 CLUSTER RESET redis-cli -h db01 -p 6381 CLUSTER RESET redis-cli -h db02 -p 6381 CLUSTER RESET redis-cli -h db03 -p 6381 CLUSTER RESET redis-cli -h db01 -p 6380 CLUSTER NODES
2.使用工具初始化 1 redis-cli --cluster create 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 --cluster-replicas 1
3.检查集群 1 2 3 redis-cli --cluster info 10.0 .0 .51 6380redis-cli -h db01 -p 6380 CLUSTER NODES redis-cli --cluster check 10.0 .0 .51 6380
第19章 使用工具扩容
1.来自json的灵魂发问: 迁移时候槽的数据咋办? 需要停库吗? 访问受影响吗? 从库呢?
2.如何设计实验验证数据是否受影响? 迁移的过程中 一个窗口不断的写数据 一个窗口不断的读数据 观察是否会中断
3.创建新节点 1 2 3 4 5 6 7 8 9 10 11 12 13 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
4.使用工具扩容步骤 1 2 3 4 5 6 7 8 9 10 11 12 13 14 重新分配槽位 redis-cli --cluster 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
第20章 使用工具缩容
1.操作命令 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 重新分配槽位 redis-cli --cluster reshard 10.0 .0 .51 :6380 第一次交互:需要迁移多少个槽位 How many slots do you want to move (from 1 to 16384 )? 1365 第二次交互:接受节点的ID是什么 What is the receiving node ID? db01的6380 的ID 第三次交互:哪些节点需要导出 Source node Source node 第四次交互:确认 Do you want to proceed with the proposed reshard plan (yes/no)? yes重复上面的操作,直到6390 所有的槽位都被分配出去了 检查集群状态,确认6390 没有槽位了 redis-cli --cluster info 10.0 .0 .51 :6380 使用工具删除节点了 redis-cli --cluster del-node 10.0 .0 .51 :6390 6390 的ID redis-cli --cluster del-node 10.0 .0 .51 :6391 6391 的ID
2.提问:公司先用的是哨兵然后在改集群 如何迁移数据 用槽位分配解决方法:
1 2 3 4 5 1.搭建好Redis集群并互相发现 2.把所有的key都分配到db01上 3.把哨兵里的数据AOF持久化 4.拷贝到db01上,启动集群节点 5.重新分配槽位迁移到其他2个节点
第21章 .验证集群高可用 1.提问:故障的主库修复后启动会变成备胎吗? 2.实验结论: 1 2 1.主库挂了,从库会自动接替主库的角色,集群恢复正常会受超时时间控制 2.老得主库修复上线后,会自动变成从库,同步新的主库
3.主动发起集群角色切换:
第22章 模拟分配时故障 1.模拟场景:迁移数据时人为中断了,导致槽的状态不对 1 2 [11213 -<-a69e46ea7560684a7061ddb6dc3f854a1ef3dbd4] 51 [11213 ->-ccaa5dcb0f0320332100594d629122b2702660d5] 53
2.使用工具修复: 1 redis-cli --cluster fix 10.0 .0 .51 :6380
3.手动修复: 1 CLUSTER SETSLOT <slot> STABLE
第23章 使用工具维护集群的好处 1 2 3 4 工具有很多判断条件,更加严谨,健壮性更好 删除槽,使用工具会判断,如果槽里有数据,就不执行 添加节点使用工具会判断,如果新增加的节点本身不为空,不允许加入到集群里 删除节点使用工具会判断,如果本删除节点本身还有槽,不允许删除
第24章 数据迁移 1.新版本直接使用工具迁移 不加copy参数相当于mv,老数据迁移成功就删掉了
1 redis-cli --cluster import 10.0 .0 .51 :6380 --cluster-from 10.0 .0 .51 :6379
添加copy参数相当于cp,老数据迁移成功后会保留
1 redis-cli --cluster import 10.0 .0 .51 :6380 --cluster-copy --cluster-from 10.0 .0 .51 :6379
添加replace参数会覆盖掉同名的数据,对新集群新增加的数据不受影响
1 redis-cli --cluster import 10.0 .0 .51 :6380 --cluster-copy --cluster-replace --cluster-from 10.0 .0 .51 :6379
验证迁移期间边写边导会不会影响: 同时开2个终端,一个写入key,
1 for i in {1..1000};do redis-cli set k_${i} v_${i} ;sleep 0.2;echo ${i} ;done
一个执行导入命令
1 redis-cli --cluster import 10.0 .0 .51 :6380 --cluster-copy --cluster-replace --cluster-from 10.0 .0 .51 :6379
得出结论:
1 只会导入当你执行导入命令那一刻时,当前被导入节点的所有数据,类似于快照,对于后面再写入的数据不会更新
第25章 分析key的大小 0.使用自带工具分析
1.使用第三方工具分析 1.安装命令 1 2 3 4 5 6 yum install python-pip gcc python-devel -y cd /opt/git clone https://github.com/sripathikrishnan/redis-rdb-tools cd redis-rdb-toolspip install python-lzf python setup.py install
2.生成测试数据 1 redis-cli -h db01 -p 6379 set txt $(cat txt.txt)
3.执行bgsave生成rdb文件 1 redis-cli -h db01 -p 6379 BGSAVE
4.使用工具分析 1 2 cd /data/redis_6379/rdb -c memory redis_6379.rdb -f redis_6379.rdb.csv
5.过滤分析 1 awk -F"," '{print $4 ,$3 }' redis_6379.rdb.csv |sort -r
6.汇报领导 将结果整理汇报给领导,询问开发这个key是否可以删除
第26章 redis的内存管理 1.设置最大内存限制
2.内存回收机制 生产上一定要限制redis的内存使用大小。
当达到内存使用限制之后redis会出发对应的控制策略
redis支持6种策略:
1 2 3 4 5 6 1.noevicition 默认策略,不会删除任务数据,拒绝所有写入操作并返回客户端错误信息,此时只响应读操作 2.volatile-lru 根据LRU 算法删除设置了超时属性的key ,指导腾出足够空间为止,如果没有可删除的key ,则退回到noevicition 策略 3.allkeys-lru 根据LRU 算法删除key ,不管数据有没有设置超时属性 4.allkeys-random 随机删除所有key 5.volatile-random 随机删除过期key 5.volatile-ttl 根据key 的ttl ,删除最近要过期的key
3.生产上redis限制多大内存 1 2 3 4 5 6 7 8 9 先空出来系统一半内存 48G 一共 24G 系统 24G redis redis先给8G内存 满了之后,分析结果告诉老大和开发,让他们排查一下是否所有的key都是必须的 redis再给到12G内存 满了之后,分析结果告诉老大和开发,让他们排查一下是否所有的key都是必须的 redis再给到16G内存 满了之后,分析结果告诉老大和开发,让他们排查一下是否所有的key都是必须的 等到24G都用完了之后,汇报领导,要考虑买内存了。 等到35G的时候,就要考虑是加内存,还是扩容机器。
第27章 性能测试 1 redis-benchmark -n 10000 -q
第28章 集群相关命令 1 2 3 4 5 6 7 8 9 10 11 12 13 redis-cli -h db01 -p 6380CLUSTER NODES CLUSTER MEET 10.0 .0 .52 6380CLUSTER INFO CLUSTER REPLICATE CLUSTER ADDSLOTS CLUSTER RESET CLUSTER FAILOVER CLUSTER SETSLOT <slot > STABLE redis-cli --cluster info 10.0 .0 .51 6380redis-cli --cluster rebalance 10.0 .0 .51 6380redis-cli --cluster del-node redis-cli --cluster fix 10.0 .0 .51 :6380
第29章 命令总结 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 1. 全局命令keys * DBSIZE EXISTS k1 EXPIRE k1 10 TTL k1 DEL k1 2. 字符串:set k1 v1get k1mset k1 v1 k2 v2 k3 v3 mget k1 k2 k3 incr k1 incrby k1 N 3. 列表:LPUSH RPUSH LPOP RPOP LLEN LRANGE list1 0 -1 HASH: HMSET HGET HMGET HGETALL 4. 集合:SADD SDIFF SINTER SUNION SREM 5. 有序集合:ZADD ZCARD ZSCORE ZRANK ZREVRANK ZRANGE ZRANGEBYSCORE ZINCRBY ZCOUNT
转自:简书张导https://www.jianshu.com/p/9622d5906bcf
老男孩-NoSQL