关系型: mysql oracle
非关系型:redis mongo ES
1.速度快
c语言写的
代码优雅
单线程架构
2.支持多种数据结构
字符串,哈希,列表,集合,有序集合,地理位置
3.丰富的功能
天然计数器
健过期功能
消息队列
4.支持客户端语言多
php,java,python
5.数据持久化
所有的数据都运行在内存中
支持2种格式持久化数据AOF RDB AOF&RDB
6.自带多种高可用架构
主从
哨兵
集群
1.缓存-键过期时间
把session会话存在redis,过期删除
缓存用户信息,缓存Mysql部分数据,用户先访问redis,redis没有再访问mysql,然后回写给redis
商城优惠卷过期时间
2.排行榜-列表&有序集合
热度/点击数排行榜
直播间礼物积分排行
3.计数器-天然支持计数器
帖子浏览数
视频播放数
评论数
点赞/踩
4.社交网络-集合
粉丝
共同好友
兴趣爱好
标签
5.消息队列-发布订阅
配合ELK缓存收集来的日志
https://redis.io/
2.x very old
3.x redis-cluster
4.x 混合持久化
5.x 新增加了流处理类型 最新稳定版
/data/soft 下载目录
/opt/redis_6379/{conf,logs,pid} 安装目录,日志目录,pid目录,配置目录
/data/redis_6379/ 数据目录
mkdir /data/soft -p
cd /data/soft
wget http://download.redis.io/releases/redis-5.0.7.tar.gz
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
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.51
port 6379
pidfile /opt/redis_6379/pid/redis_6379.pid
logfile /opt/redis_6379/logs/redis_6379.log
EOF
redis-server /opt/redis_6379/conf/redis_6379.conf
ps -ef|grep redis
netstat -lntup|grep 6379
[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>
kill
pkill
redis-cli
SHUTDOWN
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<
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
全局命令是指对所有数据类型都通用的命令
key:value
键:值
set k1 v1
set k2 v2
set k3 v3
!!!危险命令!!!此操作未满30岁禁止请在家人的看管下执行
keys *
DBSIZE
EXISTS k1
状态码:
0 表示这个key不存在
1 表示这个key存在
N 表示存在N个key
DEL k1
DEL k1 k2
状态码:
0 表示这个key不存在
1 表示这个key存在,并且删除成功了
N 表示N个key存在,并且删除成功了N个key
设置过期时间
EXPIRE k1 10
状态码:
0 这个key不存在
1 这个key存在,并且设置过期时间成功
查看keys是否过期
TTL k1
状态码:
-1 这个key存在,并且没有设定存活周期,永不过期
-2 这个key不存在
N 这个key存在,并且在N秒后过期
取消过期时间:
第一种方法:
PERSIST k1
第二种方法:
set k1 v1
结论:
过期后的key会被直接删除
set k1 v1
get k1
MSET k1 v1 k2 v2 k3 v3 k4 v4
MGET k1 k2 k3 k4
加1:
SET k1 1
INCR k1
GET k1
加N:
INCRBY k1 100
减1:
INCRBY k1 -1
减N:
INCRBY k1 -100
LPUSH: 从列表左侧插入数据
RPUSH: 从列表右侧插入数据
LLEN list1
LRANGE list1 0 -1
LPOP: 从列表左边删除一个元素
RPOP: 从列表右边删除一个元素
LPOP list1
RPOP list1
DEL list1
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 28
user:2 name json job py age 25
user:3 name hao job bug age 26
HMSET user:1 name bobo job IT age 28
HMSET user:2 name json job py age 29
HMSET user:3 name hao job bug age 19
select name from user where id =1 ;
HMGET user:1 name
HMGET user:1 name job age
select * from user where id =1 ;
HGETALL user:1
SADD set1 1 2 3
SADD set2 1 3 5 7
SMEMBERS set1
SMEMBERS set2
127.0.0.1:6379> SINTER set1 set2
127.0.0.1:6379> SUNION set1 set2
127.0.0.1:6379> SDIFF set1 set2
127.0.0.1:6379> SDIFF set2 set1
SREM set1 1
集合不允许出现重复的值,自动去重
ZADD SZ3 100 json
ZADD SZ3 90 bobo
ZADD SZ3 99 xiaocancan
ZADD SZ3 98 bughao
ZCARD SZ3
ZSCORE SZ3 json
ZRANK SZ3 json
ZRANK SZ3 bobo
ZREVRANK SZ3 json
ZREVRANK SZ3 bobo
ZREM SZ3 json
ZINCRBY SZ3 2 xiaocancan
ZSCORE SZ3 xiaocancan
ZRANGE SZ3 0 3
ZRANGE SZ3 0 3 WITHSCORES
ZRANGEBYSCORE SZ3 95 100
ZRANGEBYSCORE SZ3 95 100 WITHSCORES
ZCOUNT SZ3 90 110
RDB:类似于快照的形式,当前内存里的状态持久化到硬盘里
优点:压缩格式/恢复速度快
缺点:不是实时的,可能会丢失数据,操作比较重
AOF:类似于mysql的binlog,可以设置为每秒/每次操作以追加的形式持久化
优点:安全,最多损失1秒的数据,可读
缺点:文件比较大,恢复速度慢
save 900 1
save 300 10
save 60 10000
dbfilename redis.rdb
dir /data/redis_6379/
1.没有配置save参数时,shutdown不会持久化保存
2.没有配置save参数时,可以手动执行bgsave触发持久化
3.在配置了save参数后,shutdown,kill,pkill都会自动触发bgsave
4.恢复的时候,rdb文件名要和配置文件里写的一样。
5.RDB高版本兼容低版本,低版本不兼容高版本
appendonly yes
appendfilename “redis.aof”
appendfsync everysec
执行的命令 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
实验背景:
aof和rdb同时存在的时候,redis重启会读取哪一个数据?
实验步骤:
set k1 v1
set k2 v2
bgsave
RDB k1 k2
mv redis.rdb /opt/
flushall
set k3 v3
set k4 v4
AOF k3 k4
mv redis.aof /opt/
pkill redis
rm -rf /data/redis_6379/*
mv /opt/redis.rdb .
mv /opt/redis.aof .
redis-server /opt/redis_6379/conf/redis.conf
redis-cli
keys *
结论:
当aof和rdb同时存在时,重启redis会优先读取aof的内容
https://redis.io/topics/persistence
1.开启混合模式
2.开启aof
3.不开启rdb
4.rdb采用定时任务的方式定时备份
1.aof文件损坏之后,使用修复工具,一刀流,从aof文件出错的地方开始到最后全部删掉
2.任何操作之前,先备份数据
3.aof备份一般情况最多损失1秒的数据
1.aof文件会记录下过期的时间
2.恢复的时候会去对比记录的过期时间和当前时间,如果超过了,就删除key
3.key的过期时间不受备份恢复影响
requirepass cookzhang
第一种:
[root@db01 ~]# redis-cli
127.0.0.1:6379> AUTH cookzhang
OK
127.0.0.1:6379> set k1 v1
OK
第二种:
redis-cli -a cookz get k1
1.redis一般都部署在内网环境,默认是比较安全的环境
2.有同学担心密码写在配置文件里,开发不允许登陆到Linux服务器上,但是可以连接到redis,设个密码安全些
rename-command CONFIG “”
rename-command KEYS “”
rename-command SHUTDOWN “”
rename-command FLUSHALL “”
rename-command DEL “”
rename-command FLUSHDB “”
rename-command CONFIG “”
rename-command KEYS “”
rename-command SHUTDOWN “qq526195417”
rename-command FLUSHALL “”
rename-command DEL “byebye”
rename-command FLUSHDB “”
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
for i in {1…1000};do redis-cli -h 10.0.0.51 set ${i} ${i};done
方法1:临时生效
redis-cli -h 10.0.0.52 slaveof 10.0.0.51 6379
方法2:写进配置文件
slaveof 10.0.0.51 6379
1.简单流程:
1.从节点发送同步请求到主节点
2.主节点接收到从节点的请求之后,做了如下操作
SLAVEOF no one
1.从节点只读不可写
2.从节点不会自动故障转移,它会一直同步主节点
10.0.0.52:6379> set k1 v1
(error) READONLY You can’t write against a read only slave.
3.主从复制故障转移需要人工介入
无论是同步,无论是主节点还是从节点,请先备份一下数据
1.解决了主从复制故障需要人为干预的问题
2.提供了自动的高可用解决方案
redis节点: 6379
哨兵节点: 26379
pkill redis
cat >/opt/redis_6379/conf/redis_6379.conf <
bind 127.0.0.1 10.0.0.51
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
systemctl start redis
redis-cli
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 <
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
redis-cli -h 10.0.0.52 slaveof 10.0.0.51 6379
redis-cli -h 10.0.0.53 slaveof 10.0.0.51 6379
redis-cli -h 10.0.0.51 info Replication
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*
参数解释:
sentinel monitor mymaster 10.0.0.51 6379 2
#mymaster 主节点别名 主节点 ip 和端口, 判断主节点失败, 两个 sentinel 节点同意
sentinel down-after-milliseconds mymaster 3000
#选项指定了 Sentinel 认为服务器已经断线所需的毫秒数。
sentinel parallel-syncs mymaster 1
#向新的主节点发起复制操作的从节点个数, 1 轮询发起复制
sentinel failover-timeout mymaster 180000
#故障转移超时时间
cat >/usr/lib/systemd/system/redis-sentinel.service<
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
systemctl start redis-sentinel
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
关闭主节点服务上的所有redis进程
观察其他2个节点会不会发生选举
查看配置文件里会不会自动更新
查看新的主节点能不能写入
查看从节点能否正常同步
启动单节点
启动哨兵
流程说明:
设置其他节点的权重为0
手动发起重新选举
观察所有节点消息是否同步
观察切换结果是否符合预期
命令解释:
查询命令:CONFIG GET slave-priority
设置命令:CONFIG SET slave-priority 0
主动切换:sentinel failover myredis
操作命令:
redis-cli -h 10.0.0.52 -p 6379 CONFIG SET slave-priority 0
redis-cli -h 10.0.0.53 -p 6379 CONFIG SET slave-priority 0
redis-cli -h 10.0.0.51 -p 26379 sentinel failover myredis
验证选举结果:
redis-cli -h 10.0.0.51 -p 26379 Sentinel get-master-addr-by-name myredis
资源利用率不高
主库压力大
连接过程繁琐
redis集群,无论有几个节点,一共只有16384个槽
所有的槽位都必须分配,哪怕有1个槽位不正常,整个集群都不能用
每个节点的槽的顺序不重要,重点是数量
hash算法足够随机,足够平均
每个槽被分配到数据的概率是相当的
集群的高可用依赖于主从复制
集群拥有自己的配置文件,动态更新,不要手欠修改
集群通讯会使用基础端口号+10000的端口,这个是自动创建的,不是配置文件配置的
集群槽位分配比例允许误差在%2之间
主节点 6380
从节点 6381
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<
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<
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
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
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
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 MEET 10.0.0.51 6381
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 6381
redis-cli -h db01 -p 6380 CLUSTER NODES
db01:6380 5461 0-5460
db02:6380 5461 5461-10921
db03:6380 5462 10922-16383
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 -h db01 -p 6380 CLUSTER NODES
redis-cli -h db01 -p 6380 CLUSTER INFO
redis-cli -h db01 -p 6380 CLUSTER NODES
6380的ID 10.0.0.51
6380的ID 10.0.0.53
6380的ID 10.0.0.52
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
redis-cli -h db01 -p 6380 CLUSTER NODES
10.0.0.51:6380> set k1 v1
(error) MOVED 12706 10.0.0.53:6380
在db01的6380节点插入数据提示报错
报错内容提示应该移动到db03的6380上
在db03的6380上执行相同的插入命令可以插入成功
在db01的6380节点插入数据有时候可以,有时候不行
使用-c参数后,可以正常插入命令,并且节点切换到了提示的对应节点上
因为集群模式有ASK路由规则,加入-c参数后,会自动跳转到目标节点处理
并且最后由目标节点返回信息
for i in {1…10000};do redis-cli -c -h db01 -p 6380 set k_KaTeX parse error: Expected group after '_' at position 6: {i} v_̲{i};echo ${i};done
DBSIZE
redis-cli -c -h db03 -p 6380 keys * > keys_all.txt
cat keys_all.txt |awk -F “_” ‘{print $2}’|sort -rn
[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.
[root@db01 /opt/redis/src]# redis-cli --cluster info 10.0.0.51 6380
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.
某日某豪接到任务,需要部署redis集群结果不小心无脑复制粘贴,把所有的槽都分配给了1个节点,还没发现,然后就交付使用了,过了1天才发现问题。
而此时,已经有不少数据写入了,如何在不丢失数据的情况下解决这个问题?
数据不能丢,最好不中断业务
[root@db01 ~]# redis-cli --cluster info 10.0.0.51 6380
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.
来自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.
0.重新制作一个测试集群,槽位分布和线上出错的一样
1.将线上环境里的aof导出来
2.恢复到测试的集群里
3.收集所有的key
redis-cli -c -h db01 -p 6380 keys * > keys_all.txt
4.编写脚本遍历所有的key获取值
cat >get_key.sh<
for key in ( c a t k e y s a l l . t x t ) d o v a l u e = (cat keys_all.txt) do value= (catkeysall.txt)dovalue=(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.测试环境没问题之后再去生产环境操作
前提条件:
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
重新分配槽位
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 #1: db01的6390的ID
Source node #2: done
第四次交互:YES!
重复上面的操作,知道所有的节点槽位都分配正确
redis-cli --cluster import 10.0.0.51:6380 --cluster-copy --cluster-replace --cluster-from 10.0.0.51:6379
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
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
redis-cli --cluster info 10.0.0.51 6380
redis-cli -h db01 -p 6380 CLUSTER NODES
redis-cli --cluster check 10.0.0.51 6380
迁移时候槽的数据咋办?
需要停库吗?
访问受影响吗?
从库呢?
迁移的过程中
一个窗口不断的写数据
一个窗口不断的读数据
观察是否会中断
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
重新分配槽位
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
重新分配槽位
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 #1: db01的6390的ID
Source node #2: done
第四次交互:确认
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
用槽位分配解决方法:
1.搭建好Redis集群并互相发现
2.把所有的key都分配到db01上
3.把哨兵里的数据AOF持久化
4.拷贝到db01上,启动集群节点
5.重新分配槽位迁移到其他2个节点
1.主库挂了,从库会自动接替主库的角色,集群恢复正常会受超时时间控制
2.老得主库修复上线后,会自动变成从库,同步新的主库
CLUSTER FAILOVER
[11213-<-a69e46ea7560684a7061ddb6dc3f854a1ef3dbd4] 51
[11213->-ccaa5dcb0f0320332100594d629122b2702660d5] 53
redis-cli --cluster fix 10.0.0.51:6380
CLUSTER SETSLOT STABLE
工具有很多判断条件,更加严谨,健壮性更好
删除槽,使用工具会判断,如果槽里有数据,就不执行
添加节点使用工具会判断,如果新增加的节点本身不为空,不允许加入到集群里
删除节点使用工具会判断,如果本删除节点本身还有槽,不允许删除
不加copy参数相当于mv,老数据迁移成功就删掉了
redis-cli --cluster import 10.0.0.51:6380 --cluster-from 10.0.0.51:6379
添加copy参数相当于cp,老数据迁移成功后会保留
redis-cli --cluster import 10.0.0.51:6380 --cluster-copy --cluster-from 10.0.0.51:6379
添加replace参数会覆盖掉同名的数据,对新集群新增加的数据不受影响
redis-cli --cluster import 10.0.0.51:6380 --cluster-copy --cluster-replace --cluster-from 10.0.0.51:6379
验证迁移期间边写边导会不会影响: 同时开2个终端,一个写入key,
for i in {1…1000};do redis-cli set k_KaTeX parse error: Expected group after '_' at position 6: {i} v_̲{i};sleep 0.2;echo ${i};done
一个执行导入命令
redis-cli --cluster import 10.0.0.51:6380 --cluster-copy --cluster-replace --cluster-from 10.0.0.51:6379
得出结论:
只会导入当你执行导入命令那一刻时,当前被导入节点的所有数据,类似于快照,对于后面再写入的数据不会更新
redis-cli --bigkeys
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
redis-cli -h db01 -p 6379 set txt $(cat txt.txt)
redis-cli -h db01 -p 6379 BGSAVE
cd /data/redis_6379/
rdb -c memory redis_6379.rdb -f redis_6379.rdb.csv
awk -F"," ‘{print $4,$3}’ redis_6379.rdb.csv |sort -r
将结果整理汇报给领导,询问开发这个key是否可以删除
config set maxmemory 2G
生产上一定要限制redis的内存使用大小。
当达到内存使用限制之后redis会出发对应的控制策略
redis支持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
先空出来系统一半内存
48G 一共
24G 系统
24G redis
redis先给8G内存 满了之后,分析结果告诉老大和开发,让他们排查一下是否所有的key都是必须的
redis再给到12G内存 满了之后,分析结果告诉老大和开发,让他们排查一下是否所有的key都是必须的
redis再给到16G内存 满了之后,分析结果告诉老大和开发,让他们排查一下是否所有的key都是必须的
等到24G都用完了之后,汇报领导,要考虑买内存了。
等到35G的时候,就要考虑是加内存,还是扩容机器。
redis-benchmark -n 10000 -q
redis-cli -h db01 -p 6380
CLUSTER NODES
CLUSTER MEET 10.0.0.52 6380
CLUSTER INFO
CLUSTER REPLICATE
CLUSTER ADDSLOTS
CLUSTER RESET
CLUSTER FAILOVER
CLUSTER SETSLOT STABLE
redis-cli --cluster info 10.0.0.51 6380
redis-cli --cluster rebalance 10.0.0.51 6380
redis-cli --cluster del-node
redis-cli --cluster fix 10.0.0.51:6380
1.全局命令
keys *
DBSIZE
EXISTS k1
EXPIRE k1 10
TTL k1
DEL k1
2.字符串:
set k1 v1
get k1
mset 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