一句话:基于内存的KV键值对内存数据库
应用与功能:
1.分布式缓存,挡在mysql数据库之前的带刀护卫
2.内存存储和持久化,redis支持异步将内存中的数据写在硬盘上,同时不影响继续服务
3.高可用架构搭配(单机、主从、哨兵、集群)
4.缓存穿透、击穿、雪崩
5.分布式锁
6.队列
7.排行榜+点赞
8。。。。
优势:
1.性能极高——Redis读写的速度是110000次/秒,写的速度是81000/秒。
2.Redis数据类型丰富,不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
3.Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
4.Redis支持数据的备份,即master-slave模式的数据备份。
cd /usr/local/bin
redis-cli -h 192.168.197.128 -p 6379
#进入后输入redis密码
AUTH redis密码
redis是一个key-value的数据库,key一般是String类型,不过value的类型多种多样
string类型是二进制安全的(支持序列化),一个redis的value最多可以是512M
KEYS [pattern]:查看符合模板的所有Key
keys *
DEL [key...]:原子删除指定的key,返回值为删除的数量
del k3
UNLINK [key...]:非阻塞删除,仅仅将keys从keyspace元数据中删除,真正的删除会在后序的异步中操作解决了del bigkey会阻塞的问题
unlink k2
EXISTS [key...]:查看key是否存在
exists k1
exists k1 k2 k3//返回k1、k2、k3中有几个
EXPIRE key second:给一个key设置有效期,有效期到期时key会被自动删除
expire k1 5
TTL key:查看一个KEY的剩余有效期
ttl k1 //-1永不过期,-2已经过期
PERSIST key 移除键的过期时间
persist k1
TYPE [key]:查看key的类型
type k1
MOVE [key] [0-15]:将当前数据库的key移动到给定的数据库db当中
move k1 2
SELECT [0-15]:切换数据库
select 3
DBSIZE:查看当前数据库key的数量
FLUSHDB:清空当前库
FLUSHALL:通杀全部库
HELP@类型:查看类型的帮助
SET k1 v1
GET k1
SET k1 v1 NX //不存在时才创建
SET k1 v1 XX //存在时才创建
SET k1 v2 GET//先get当前值,再把k1设置成v2
SET k1 v1 EX 10//k1 10s后过期
SET k1 v1 EXAT 1669298229//设置时间戳过期
SET k1 v2 KEEPTTL//在给k1设置过期时间后,修改k1值时保留过期时间
SETEX k1 10 v1 //设置k1为v1,过期时间为10秒钟
SETNX k1 v1 //没有时才创建
MSET k1 v1 k2 v2 //批set
MGET k1 k2 k3 //批get
MSETNX k1 v1 k4 v4 //作为整体,k1有,k4无,但依然设置失败
GETRANGE k1 0 2//获取k1中0-2中的值
SETRANGE k1 1 xxyy//将k1中v1的第2个字符倒第6个字符起覆盖为xxyy
INCR k1//将k1加1
INCRBY k1 3//将k1加3
DECR k1//将k1减1
DECRBY k1 3 //将k1减3
STRLEN k1//查询k1的长度
APPEND k1 xxxx//将xxxx放到k1后面
redis的分布式锁机制:
setnx key value
setex键秒值/setnx(set if not exist)
应用场景:
1.抖音无限点赞某个视频或者商品,点一下加一次
2.是否喜欢的文章
最多可以存2^32-1个键值对
KV模式不变,但V是一个键值对Map
HSET test:user:1 age 22
HSET test:user:1 name zyj
HGET test:user:1 name
HMSET test:user:2 name zyj age 22
HMGET testLuser:2 name age
HGETALL test:user:1
HDEL test:user:1 age
HLEN test:user:1 //获取某个key内的全部数量下·
HEXISTS test:user:1 name //查看test:user:1中是否有name
HKEYS/HVALS test:user:1 //单独列出hash map的keys或者values
HINCRBY test:user:1 age 1 //将age加1和user加0.5
HINCRBYFLOAT test:user:1 socre 0.5//将score加0.5
HSETNX
HSETEX
应用场景:JD购物车早期,目前已经不再使用,当前中小厂可用
LPUSH list1 1 2 3 4 5
RPUSH list2 11 22 33 44 55
LRANGE list1 0 -1 //全部遍历,从左到右遍历
LPOP list1 //从左边pop
RPOP list1 //从右边pop
LINDEX list1 0//左边第0个元素
LLEN list1 //列表元素个数
LREM key 数字N 给定值v1 //删除N个值等于v1的元素
LTRIM list1 开始index 结束index //使list1只保持区间[开始index,结束index]内的数
RPOPLPUSH 源列表 目的列表 //将源列表RPOP,然后LPUSH到目的列表中
BRPOPLPUSH 源列表 目的列表 //如果源列表为空,则阻塞
LSET list1 1 mysql //将list1的1号元素设置为mysql
LINSERT list1 BEFORE mysql java //在list1的mysql前面插入java
应用场景:微信公众号订阅消息
单值多value,无序无重复
Redis的Set集合是通过哈希表实现,所以添加,删除,查找的复杂度都是O(1)
集合的最大的成员数2^32-1
SADD key [member...] //添加元素,自动去重
SMEMBERS key //查看set中的所有元素
SISMEMBER key value //查看value是否在key中
SREM key value //删除key中的value
SCARD key //获取集合里面的元素个数
SRANDMEMBER key [数字]//随机展现集合中的一个元素,元素不删除
SPOP key //从集合中随机弹出一个元素,出一个删一个
SMOVE key1 key2 value1 //将key1中已存在的value1赋值给key2
SDIFF key [key2...] //求集合key与集合key2...的差集
SUNION key [key2...] //求集合key与集合key2...的并集
SINTER key [key2...]//即集合key与集合key2...的交集
SINTERCARD numkeys key [key...][LIMIT limit]//它不返回结果集,而只返回结果的基数。返回由所有给定集合的交集产生的集合的基数,numkeys代表集合数
SDIFFSTORE dest-key key-name [key-name ...]//将那些存在于第一个集合但并不存在于其他集合中的元素存储到dest-key中
SINTERSTORE dest-key key-name [key-name ...]//将集合的交集存到dest-key中
SUNIONSTORE dest-key key-name [key-name ...]//将集合的并存到dest-key中
应用场景:
1.微信抽奖小程序
2.微信朋友圈点赞查看同赞朋友
3.QQ内推可能认识的人
SDIFF
简称Zset,和set一样也是string类型的元素集合
每个元素都会关联一个double类型的分数
ZADD z1 60 v1 70 v2 80 v3 90 v4 100 v5
ZRANGE z1 0 -1
ZRANGE z1 0 -1 WITHSCORES //从小到大输出z1
ZREVRANGE z1 0 -1 WITHSCORES //从大到小输出z1
ZRANGEBYSCORE z1 60 100 WITHSCORES //选出分数在[60,100]之间的数据
ZRANGEBYSCORE z1 60 100 WITHSCORES //选出分数在(60,100]之间的数据
ZRANGEBYSCORE z1 60 100 WITHSCORES LIMIT 0 1 //选出分数在[60,100]之间的数据,从偏移0开始选出1个
ZSCORE z1 v5 //获取z1中v5的分数
ZCARD z1 //获取z1中的数据数目
ZREM z1 v5 //删除z1中的v5
ZINCRBY z1 3 v1 //对z1中的v1增加三分
ZOUNT z1 60 100//[60,100]中的元素个数
ZMPOP 1 z1 MIN COUNT 1 //把z1中键值对最小的1个元素的1个键值弹出
ZRANK z1 v2 //获得z1中v2的正序排名
ZREVRANK z1 v2//获得z1中v2的逆序排名
应用场景:根据商品销售对商品进行排序显示
GEO主要用于存储地理位置信息,并对存储的信息进行操作,包括:
1.添加地理位置的坐标
2.获取地理位置的坐标
3.计算两个位置之间的距离
4.根据用户给定的经纬度坐标来获取指定范围内的地理位置集合。
redis中文乱码问题的解决:
redis-cli -a 111111 --raw
GEO是SortedSet类型,可以用其对应相关命令
GEOADD KEY [longitude latitude member...]
//GEOADD用于存储指定的空间位置,longtitude为经度,latitude为纬度,member是位置名称
例:GEOADD city 116.403963 39.915119 "天安门" 116.403414 39.924091 "故宫"
GEOPOS KEY [member...] //返回经纬度
GEOHASH KEY [member...]//返回坐标的geohash表示
GEODIST KEY member1 member2 km//返回member1和member2的距离,单位km
GEORADIUS KEY longtitude latitude radius m|km|ft|mi ...//以半径为中心,查找附近的XXX
例:GEORADIUS city 116.418017 39.914402 10 km withdist/withcoord count 10 withhash desc//当前经纬度(116.418017,39.914402)附近10km以内距离、经纬度一致返回,限制返回的记录数最多为10
GEORADIUSBYMEMBER city 天安门 10km withdist withcoord count 10 withhash
//GEORADIUSBYMEMBER 找出位于指定范围内的元素,中心点是由给定的位置元素决定
应用场景:
1.美团地图位置附近的酒店推送
2.高德地图附近的核酸检查点
一句话:用于统计一个集合中不重复的元素个数,就是对集合去重复后剩余元素的计算
HyperLogLog是用来做基数统计的算法,HyperLogLog的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定且是很小的。
在Redis里面,每个HyperLogLog键只需要花费12KB内存,就可以计算接近2^64个不同元素的基数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
但是,因为HyperLogLog只会根据输入元素来计算基数,而不会储存输入元素本身,所以HyperLogLog不能像集合那样,返回输入的各个元素。
PFADD H1 1 2 3 3 4 5
PFADD H2 2 3 4 5
PFCOUNT H1 //计数时自动去重
PFMERGE result H1 H2//将H1和H2合并后的结果放入result
应用场景:
1.统计某个网站的UV、统计某个文章的UV(Unique Visitor,独立访客,一般理解为客户端IP,需要去重考虑)
2.用户搜索网站关键词的数量
3.统计用户每天搜索不同词条个数
bitmap:用String类型作为底层数据结构实现的一种统计二值状态的数据类型,位图的本质是数组,它是基于String数据类型的按位的操作。该数组由多个二进制位组成,每个二进制位都对应一个偏移量。
每一个格子里面只能放1或者0,用它来判断Y/N状态
bitfield:
通过bitfield命令可以一次性操作多个比特位域(指的是连续的多个比特位),它会执行一系列操作并返回一个响应数组,这个数组中的元素对应参数列表中的相应操作的执行结果。说白了就是通过bitfield命令我们可以一次性对多个比特位域进行操作。
Bitmap:
SETBIT KEY OFFSET VALUE //VALUE只能是0或1
GETBIT KEY OFFSET //获取KEY的OFFSET位的值
STRLEN KEY//统计字节数占用多少
BITCOUNT KEY//全部键里面含有1的有多少个
BITOP OPEARTION DESTKEY KEY//对不同的二进制存储数据进行位运算(AND、OR、NOT、XOR)
例如:BITOP AND k3 20230101 20230102//求20230101和20230102两天都签到的用户
BITCOUNT k3
应用场景:
1.用户是否登陆过Y、N,比如京东每日签到送京豆
2.电影、广告是否被点击播放过
3.钉钉打卡上下班,签到统计
Redis Stream主要用于消息队列(MQ,Message Queue),Redis本身是有一个Redis发布订阅(pub/sub)来实现消息队列的功能,但它有个缺点就是消息无法持久化,如果出现网络断开、Redis宕机等,消息就会被丢弃。
简单来说发布订阅(pub/sub)可以分发消息,但无法记录历史消息。
而Redis Stream提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每一个客户端的访问位置,还能保证消息不丢失。
SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern …]] [ASC | DESC] [ALPHA] [STORE destination]
返回或保存给定列表、集合、有序集合 key 中经过排序的元素。
排序默认以数字作为对象,值被解释为双精度浮点数,然后进行比较
LPUSH today_cost 30 1.5 10 8
SORT today_cost
1) "1.5"
2) "8"
3) "10"
4) "30"
SORT today_cost DESC
1) "30"
2) "10"
3) "8"
4) "1.5"
LPUSH website "www.reddit.com"
LPUSH website "www.slashdot.com"
LPUSH website "www.infoq.com"
SORT website
1) "www.infoq.com"
2) "www.slashdot.com"
3) "www.reddit.com"
SORT website ALPHA
1) "www.infoq.com"
2) "www.reddit.com"
3) "www.slashdot.com"
OFFSET和Count 选取排序后范围内的值
RPUSH rank 1 3 5 7 9
RPUSH rank 2 4 6 8 10
SORT rank LIMIT 0 5
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
使用外部key进行排序
LPUSH uid 1
SET user_name_1 admin
LPUSH uid 2
SET user_name_2 jack
LPUSH uid 3
SET user_name_3 peter
LPUSH uid 4
SET user_name_4 mary
SORT uid BY user_name_*
1) "2" # jack , level = 10
2) "3" # peter, level = 25
3) "4" # mary, level = 70
4) "1" # admin, level = 9999
使用 GET 选项,可以根据排序的结果来取出相应的键值。
比如说, 以下代码先排序 uid , 再取出键 user_name_{uid} 的值:
SORT uid GET user_name_*
1) "admin"
2) "jack"
3) "peter"
4) "mary"
组合使用BY和GET
通过组合使用 BY 和 GET , 可以让排序结果以更直观的方式显示出来。
比如说, 以下代码先按 user_level_{uid} 来排序 uid 列表, 再取出相应的 user_name_{uid} 的值:
SORT uid BY user_level_* GET user_name_*
1) "jack" # level = 10
2) "peter" # level = 25
3) "mary" # level = 70
4) "admin" # level = 999
获取多个外部键
可以同时使用多个 GET 选项, 获取多个外部键的值。
以下代码就按 uid 分别获取 user_level_{uid} 和 user_name_{uid} :
SORT uid GET user_level_* GET user_name_*
1) "9999" # level
2) "admin" # name
3) "10"
4) "jack"
5) "25"
6) "peter"
7) "70"
8) "mary"
通过哈希表作为GET和BY的参数
HMSET user_info_1 name admin level 9999
HMSET user_info_2 name jack level 10
HMSET user_info_3 name peter level 25
HMSET user_info_4 name mary level 70
SORT uid BY user_info_*->level GET user_info_*->name
1) "jack"
2) "peter"
3) "mary"
4) "admin"
STORE保存排序后的结果
SORT numbers STORE sorted-numbers
#把numbers排序后的结果放入到sorted-numbers
触发RDB快照的场景:
1.配置文件中的默认的快照配置
2.手动save/bgsave命令
3.执行flushall/flushdb命令也会产生dump.rdb文件,但里面是空的,无意义
4.执行shutdown且没有设置开启AOF持久化
5.主从复制时,主节点自动触发
RDB:RDB持久化是以指定的时间间隔执行数据集的时间点快照
1.实现类似照片记录效果的方式,就是把某一时刻的数据和状态以文件的形式写到磁盘上,也就是快照。这样一来即使故障宕机,快照文件也不会丢失,数据的可靠性也就得到了保证。这个快照文件就称为RDB(dump.rdb),其中,RDB就是Redis DataBase的缩写
2.在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot内存快照,它恢复时再将硬盘快照文件直接读回到内存里
3.Redis的数据都在内存中,保存备份时它执行的是全量快照,也就是说,把内存中的所有数据都记录到磁盘中
按照redis.conf里配置的save 来确定自动触发备份的频率,几秒改变几次触发
CONFIG GET requirepass //查找密码
CONFIG GET PORT//查看端口号
CONFIG GET dir//rdb保存的文件路径
redis.conf中其它的配置参数:
stop-writes-on-bgsave-error yes
如果配置成no,表示你不在乎数据不一致或者有其他的手段发现和控制这种不一致,那么在快照写入失败时,也能确保redis继续接受新的写请求。
rdbcompression yes
对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是的话,redis会采用LZF算法进行压缩。如果你不想消耗CPU来进行压缩的话,可以设置为关闭此功能
rdbchecksum yes
在存储快照后,还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能
rdb-del-sync-files:在没有持久性的情况下删除复制中使用的RDB文件启用。默认情况下no,此选项是禁用的。
如何恢复?
将备份文件(dump.rdb)移动到redis安装目录并启动服务即可
备份成功后故意用flushdb清空redis,看看是否可以恢复数据(答案:没有)
物理恢复,一定服务和备份分机隔离
使用SHUTDOWN命令模拟redis宕机时,redis会自动生成一个dump.rdb文件记录最后的快照
物理恢复:备份文件dump.rdb和生产redis服务器放在同一台机器,必须分开各自存储,以防生产机物理损坏后备份文件清空
redis提供了两个命令来生成RDB文件,分别是save和bgsave:
Save:在主程序执行会阻塞当前redis服务器,直到持久化工作完成执行save命令期间,Redis不能处理其他命令,线上禁止使用。
BgSave:Redis会在后台异步进行快照操作,不阻塞快照同时还可以响应客户端请求,该触发方式会fork一个子进程由子进程复制持久化过程。
fork的理解:
1.github的fork,将代码复制一份到自己的仓库
2.在linux程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于频率考虑,尽量避免膨胀。
还可以通过lastsave命令获取最后一次成功执行快照的时间
优点:
1.RDB是Redis数据的一个非常紧凑的单文件时间点表示,RDB非常适合备份。例如:您可能希望在最近24小时内每小时归档一次RDB文件,并在30天内每天保存一个RDB快照。这使您可以在发送灾难时轻松恢复不同版本的数据集。
2.RDB非常适合灾难恢复,它是一个可以传输到远程数据中心或Amazon S3的压缩文件。
3.RDB最大限度地提高了Redis的性能,因为Redis父进程为了持久化而需要做的唯一工作就是派生一个将完成所有其余工作的子进程。父进程永远不会执行磁盘I/O或类似操作。
4.与AOF相比,RDB允许使用最大数据集更快地重启。
5.在副本上,RDB支持重启和故障转移后的部分重新同步。
RDB适合于:
1.大规模的数据恢复
2.按照业务定时备份
3.对数据完整性和一致性要求不高
4.RDB文件在内存中的加载速度要比AOF快得多
缺点:
1.在一定间隔时间做一次备份,所以如果redis意外down掉的话,就会丢失从当前至最近一次快照期间的数据,快照之间的数据会丢失
2.内存数据的全量同步,如果数据量太大会导致I/0严重影响服务器性能
3.RDB依赖于主进程的fork,在更大的数据集中,这可能会导致服务请求的瞬间延迟。fork的时候内存中的数据被克隆了一份,大致2倍的膨胀性,需要考虑
修复和检查RDB文件:
RDB文件在写入或者迁移的时候有可能会发送破损。可以通过命令修复破损的RDB文件
redis-check-rdb dump.rdb
1.以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作
2.默认情况下,redis是没有开启AOF(append only file)的。
3.开启AOF功能需要设置配置:appendonly yes
工作流程:
三种写回策略:在conf文件的appendfsync当中,默认是everysec
1.always:同步写回,每个写命令执行完立刻同步地将日志写回磁盘
2.everysec:每秒写回,每个写命令执行完,只是先把日志写到AOF文件的缓存区,每隔1秒把缓存区中的内容写入磁盘
3.no:操作系统控制的写回,每个写命令执行完,只是先把日志写到AOF文件的内存,由操作系统决定何时将缓冲区内容写回磁盘
redis7以前AOF文件有且仅有一个
redis7以后,指定:
aof的文件路径设置为conf中的:
appenddirname “appendonlydir”
aof的文件名设置为conf中的:
appendfilename “appendonly.aof”
MP-AOF就是将原来的AOF文件拆分为多个AOF文件。在MP-AOF中,我们将AOF分为三种类型,分别为:
BASE:表示为基础AOF,它一般由子进程通过重写产生,该文件最多只有一个。
INCR:表示增量AOF,它一般会在AOFRW开始执行时被创建,该文件可能存在多个。
HISTORY:表示历史AOF,它由BASE和INCR AOF变化而来,每次AOFRW成功完成时,本次AOFRW之前对应的BASE和INCR AOF都将变为HISTORY,HISTORY类型的AOF会被Redis自动删除
为了管理这些AOF文件,我们引入了一个manifest(清单)文件来跟踪、管理这些AOF。同时,为了便于AOF备份和拷贝,我们将所有的AOF文件和manifest文件和manifest文件放入一个单独的文件目录中,目录名由appenddirname配置。
故障或乱写AOF文件会导致redis无法正常启动,因为redis重启时会自动进行AOF文件的载入。
异常修复命令:
redis-check-aof --fix AOF文件
由于AOF持久化是Redis不断将写命令记录到AOF文件中,随着Redis不断的进行,AOF的文件会越来越大,文件越大,占用服务器内存越大以及AOF恢复要求时间越长。
为了解决这个问题,Redis新增了重写机制,当AOF文件的大小超过所设定的峰值时,Redis就会自动启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集。
步骤:
1.在重写开始前,redis会创建一个“重写子进程”,这个子进程会读取现有的AOF文件,并将其包含的指令进行分析压缩并写入到一个临时文件中。
2.与此同时,主进程会将新接收到的写指令一边累积到内存缓冲区中,一边继续写入到原有的AOF文件中,这样做是保证原有的AOF文件的可用性,避免在重写过程中出现意外。
3.当“重写子进程”完成重写工作后,它会给父进程发一个信号,父进程收到信号后就会将内存中缓存的写指令追加到新AOF文件中
4.当追加结束后,redis就会用新AOF文件来代替旧AOF文件,之后再有新的写指令,就都会追加到新的AOF文件中
5.重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似
自动触发:满足配置文件中的选项后,Redis会记录上次重写时的AOF大小,
默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时
默认的配置在conf中的:
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
手动触发:客户端向服务器发送bgrewriteaof命令
优点:更好的保护数据不丢失、性能高、可做紧急恢复
1.使用AOF Redis 更加持久,您可以有不同的fsync策略:根本不fsync、每秒fsync、每次查询时fsync。使用每秒fsync的默认策略,写性能仍然很棒。fsync是使用后台线程执行的,当没有fsync 正在进行时,主线程将努力执行写入,因此您只能丢失一秒钟的写入。
2.AOF日志是一个仅附加日志,因此不会出现寻道问题,也不会在断电时出现损坏问题。即使由于某种原因(磁盘已满或其他原因)日志以写一半的命令结尾,redis-check-aof 工具也能够轻松修复它。
3.AOF变得太大时,Redis能够在后台自动重写AOF。重写是完全安全的,因为当Redis继续附加到旧文件时,会使用创建当前数据集所需的最少操作集生成一个全新的文件,一旦第二个文件准备就绪,Redis 就会切换两者并开始附加到新的那一个。
4.AOF以易于理解和解析的格式依次包含所有操作的日志。您甚至可以轻松导出 AOF 文件。例如,即使您不小心使用该FLUSHALL命令刷新了所有内容,只要在此期间没有执行日志重写,您仍然可以通过停止服务器、删除最新命令并重新启动Redis来保存您的数据集.
劣势:
1.相同数据集的数据而言AOF文件要远大于RDB文件,恢复速度慢于RDB。
2.AOF运行效率要慢于RDB,每秒同步策略效率较好,不同步效率和RDB相同。
如果同时开启RDB和AOF持久化时,重启时只会加载AOF文件,不会加载RDB文件。AOF优先级高于RDB
rdb和aof混合持久化的相关配置在conf中:
aof-use-rdb-preamble的值为yes yes表示开启混合方式,设置为no表示禁用
RDB和AOF混合方式---->RDB镜像做全量初始化,AOF做增量初始化
先使用RDB进行快照存储,然后使用AOF持久化记录所有的写操作,当重写策略满足或手动触发重写的时候,将最新的数据存储为新的RDB记录。这样的话,重启服务的时候会从RDB和AOF两部分恢复数据,既保证了数据完整性,又提高了恢复数据的性能。
简单来说:混合持久化方式产生的文件一部分是RDB格式,一部分是AOF格式。---->AOF包括了RDB头部+AOF混写
是什么?
可以一次执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞
能干嘛?
一个队列中,一次性、顺序性、排他性的执行一系列命令
Redis事务VS数据库事务
特性 | 解释 |
---|---|
1.单独的隔离操作 | Redis的事务仅仅是保证事务里的操作会被连续独占的执行,redis命令执行是单线程架构,在执行完事务内所有指令前是不可能再去同时执行其他客户端的请求的 |
2.没有隔离级别的概念 | 因为事务提交前任何指令都不会被实际执行,也就不存在"事务内的查询要看到事务里的更新,在事务外查询不能看到"这种问题了 |
3.不保证原子性 | Redis的事务不保证原子性,也就是不保证所有指令同时成功或同时失败,只有决定是否开始执行全部指令的能力,没有执行到一半进行回滚的能力 |
4.排它性 | Redis会保证一个事务内的命令依次执行,而不会被其它命令插入 |
MULTI
set k1 v1
set k2 v2
set k3 v3
INCR count
EXEC
情形2:放弃事务
MULTI
set k1 v1
set k2 v2
DISCARD
情形3:全体连坐
MULTI
set k1 v1
set k2 v2
set k3
EXEC //命令输入有误,事务EXEC会全不执行
情形4:怨头债主
MULTI
set k1 v1
set k2 v2
INCR email //email是string,不能INCR
set k3 v3
EXEC //只有错误的那一条不起作用
情形5:watch监控
redis使用watch来提供乐观锁定,类似于CAS(Check-and-Set)
悲观锁(Pessimistic Lock),顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。
乐观锁(Optimistic Lock),顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据。
乐观锁:提交版本必须大于记录当前版本才能执行更新
watch:初始化k1和balance两个key,先监控再开启multi,保证两key变动在同一个事务内,有加塞篡改
第一个客户端:
set k1 v1
set balance 100
watch balance
MULTI
set k1 v2
set balance 110
EXEC //执行后set balance 110没有成功,被其它客户端捷足先登了
另一个客户端:
set balance 300//这一步在第一个客户端set balance 110之前执行
unwatch:放弃监控
一旦执行了exec之前加的监控锁都会被取消掉了
当客户端连接丢失的时候(比如退出链接)所有东西都会被取消监视
问题的由来:
Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。
一个请求会遵循以下步骤:
1.客户端向服务端发送命令分四步(发送命令->命令排队->命令执行->返回结果),并监听Socket返回,通常以阻塞模式等待服务端响应。
2.服务端处理命令,并将结果返回给客户端。
上述两步称为: Round Trip Time(简称RTT,数据包往返于两端的时间)
如果同时需要执行大量的命令,那么就要等待上一条命令应答后再执行,这中间不仅仅多了RTT(Round Time Trip),而且还频繁调用系统IO,发送网络请求,同时需要redis调用多次read()和write()系统方法,系统方法会将数据从用户态转移到内核态,这样就会对进程上下文有比较大的影响了,性能不太好,o(T_T)o
Pipeline是为了解决RTT往返回时,仅仅是将命令打包一次性发送,对整个Redis的执行不造成其它任何影响。
批处理命令变种优化措施,类似Redis的原生批命令(mget和mse)
管道实操:
cmd.txt
set k1 v1
set k2 v2
hset h1 name zyj
hset h1 age 23
lpush list1 1 2 3 4 5
执行管道:
cat cmd.txt | redis-cli -a 密码 --pipe
管道与原生批量命令对比:
1.原生批量命令是原子性(例如:mset, mget),pipeline是非原子性
2.原生批量命令一次只能执行一种命令,pipeline支持批量执行不同命令
3.原生批命令是服务端实现,而pipeline需要服务端与客户端共同完成
管道与事务对比:
1.事务具有原子性,管道不具有原子性
2.管道一次性将多条命令发送到服务器,事务是一条一条的发,事务只有在接收到exec命令后才会执行,管道不会
3.执行事务时会阻塞其他命令的执行,而执行管道中的命令时不会
管道使用的注意事项:
1.pipeline缓冲的指令只是会依次执行,不保证原子性,如果执行中指令发生异常,将会继续执行后续的指令
2.使用pipeline组装的命令个数不能太多,不然数据量过大客户端阻塞的时间可能过久,同时服务端此时也被迫回复一个队列答复,占用很多内存
go语言使用管道的代码
func main() {
client = redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%s", Addr, Port),
})
ctx := context.Background()
if err := client.Ping(ctx).Err(); err != nil {
panic(err)
}
pipeline := client.Pipeline()
pipeline.Set(ctx, "s1", "v1", -1)
pipeline.Set(ctx, "s2", "v2", -1)
pipeline.Exec(ctx)
}
主从复制:master以写为主,Slave以读为主。当master数据变化的时候,自动将新的数据异步同步到其它slave数据库。
作用:
1.读写分离
2.容灾恢复
3.数据备份
4.水平扩容支撑高并发
怎么玩?
1.配从(库)不配主(库)
2.权限细节,重要
master如果配置了requirepass参数,需要密码登陆
那么slave就要配置masterauth来设置校验密码,否则的话master会拒绝slave的访问请求
3.基本操作命令
info replication //可以查看复制节点的主从关系和配置信息
replicaof 主库IP 主库端口 //一般写入进redis.conf配置文件内
slaveof 主库IP 主库端口
//每次与master断开之后,都需要重新连接,除非你配置进redis.conf文件
//在运行期间修改slave节点的信息,如果该数据库已经是某个主数据库的从数据库,那么会停止
//和原主数据库的同步关系转而和新的主数据库同步,重新拜码头
slaveof no one //使当前数据库停止与其它数据库的同步,转成主数据库,自立为王
1.将redis.conf中的daemonize修改为yes
2.注释掉bind 127.0.0.1
3.protected-mode no
4.指定端口 port
5.指定当前的工作目录 dir
6.pid文件名字,pidfile
7.log文件名字,logfile设置log文件夹
8.requirepass 设置连接密码
9.dump.rdb名字dbfilename
10.aof文件,appendfilename
11.从机访问主机的通行密码masterauth以及replicaof 主机IP 端口号,必须(主机不用)
12.先master再slave启动
问题:
1.slave能否执行写操作? 否
2.slave从头复制还是从切入点复制?首次一锅端,后续跟随,master写,slave跟。
3.主机shutdown后,从机会上位吗?依然待命等待master的回归,从机数据依然正常使用
4.主机shutdown后,重启后主从关系还在吗?从机还能否顺利复制?一切正常
5.某台主机down后,master继续,从机重启后它还能跟上大部队吗? 能
一主二仆:
配置文件启动:
仆启动:
redis-cli -a 密码 -p 端口 //因为conf中修改了端口,所以不是默认的6379了
info replication//查看主从配置信息
set k1 v1 //设置失败,从机不能写
操作命令手动指定:
仆:
SLAVEOF 从机ip 从机端口
薪火相传:
1.上一个slave可以是下一个slave的master,slave同样可以接收其他slaves的连接和同步请求,那么该slave作为了链条中下一个的master,可以有效减轻主master的写压力
2.中途变更转向:会清除之前的数据,重新建立拷贝最新的
3.slaveof 新主库IP 新主库端口(这个主机可以是别的master的slave,该slave还是无法写)
反客为主:
SLAVEOF no one //使当前数据库停止与其它数据库的主仆关系
1.slave启动,同步初请。
slave启动成功之后连接到master后会发生一个sync命令
slave首次全新连接master,一次完全同步(全量复制)将被自动执行,slave自身原有数据会被
master数据覆盖清洗掉
2.首次连接,全量复制
master节点收到sync命令后开始在后台保存快照(即RDB持久化,主从复制时会触发RDB),
同时收集所有接收到的用于修改数据集命令缓存起来,master节点执行完RDB持久化完后,
master将rdb快照文件和所有缓存的命令发送到所有slave,以完成一次完全同步
而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中,从而完成复制初始化
3.心跳持续,保持通信
master发出PING包的周期,默认是10s,可以通过修改conf中的
repl-ping-replica-period 10
来改变
4.进入平稳,增量复制
master继续将新的所有收集到的修改命令自动依次传给slave,完成同步
5.从机下线,重连续传
master会检查backlog里面的offset,master和slave都会保存一个复制的offset还有一个masterId,
offset是保存在backlog中的。Master只会把已经复制的offset后面的数据复制给Slave,类似于断点续传。
主从复制的缺点:
1.复制延迟,信号衰减
由于所有的写操作都是先在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave
机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问
题更加严重
2.master挂了不会重新选举,slave会一直等待。每次都得人工干预
是什么?
吹哨人巡查监控后台master主机是否故障,如果故障了根据投票数自动将柴一个从库转换为新主库,继续对外服务
作用:无人值守运维
能干嘛?
主从监控:监控主从redis库运行是否正常
消息通知:哨兵可以将故障转移的结果发送给客户端
故障转移:如果Master异常,则会进行主从切换,将其中一个Slave作为新Master
配置中心:客户端通过连接哨兵来获得当前Redis服务的主节点地址
Redis Sentinel架构,前提说明:
3个哨兵 自动监控和维护集群,不存放数据
1主2从 用于数据读取和存放
bind 0.0.0.0//服务监听地址,用于客户端连接,默认本机地址
daemonize yes//是否以后台daemon方式运行
protected-mode no//安全保护模式
port 26379//端口,哨兵的端口号和redis的端口号不是一回事
logfile "/myredis/sentine126379.log"//日志文件路径
pidfile /var/run/redis-sentine126379//pid文件路径
dir myredis//工作目录
sentinel monitor mymaster 192.168.111.169 6379 2
<master-name><ip><redis-port><quorum>
设置要监控的master服务器,quorum表示最少有几个哨兵认可客观下线,同意故障迁移的法定票数
sentinel auth-pass mymaster 111111
<master-name> <password>
master设置了密码,连接master服务的密码
2.每台主机的conf中的masterauth密码都必须一致
3.启动主从复制的redis
4.启动哨兵
redis-sentinel sentinelxxx.conf --sentinel
我们知道,网络是不可靠的,有时候一个sentinel会因为网络堵塞而误以为一个master redis已经死掉了,在sentinel集群环境下需要多个sentinel互相沟通来确认某个master是否真的死了,quorum这个参数是进行客观下线的一个依据,意思是至少有quorum个sentinel认为这个master有故障,才会对这个master进行下线以及故障转移。因为有的时候,某个sentinel节点可能因为自身网络原因,导致无法连接master,而此时master并没有出现故障,所以,这就需要多个sentinel都一致认为该master有问题,才可以进行下一步操作,这就保证了公平性和高可用。
问题:
1.两台从机数据是否OK? ok
2.是否会从剩下的2台机器上选出新的master?是
3.之前down的master机器重启回来,还会是老大吗?否
4.之前down的master机器重启回来,将是什么身份?slave
文件的内容,在运行期间会被sentinel动态进行更改
Master-Slave切换后,master_redis.conf、slave_redis.conf和sentinel.conf的内容都会发生改变,即master_redis.conf中会多一行slaveof的配置,sentinel.conf的监控目标会随之调换
1.主观下线SDOWN:down-after-milliseconds 设置哨兵判断master主观下线的时长,默认30秒。当超过这个时间没有收到master的心跳,就会主观认为master下线。
2.客观下线ODOWN:当多个哨兵对某个master下线达成一致性意见时才能认为master客观已经宕机了。quorum参数就是进行判断客观下线的一个依据。
3.选举出领导者哨兵(哨兵中选出兵王):当主节点被判断为客观下线以后,各个哨兵节点会进行协商,先选举出一个领导者哨兵节点(兵王)并由该领导者节点,也即被选举出的兵王进行failover(故障转移)
4.由兵王开始推动故障切换流程并选出一个新master
兵王是如何选举出来的?
Raft算法:监视该主节点的所有哨兵都有可能被选为领导者,选举使用的算法是Raft算法;Raft算法的基本思路是先到先得:即在一轮选举中,哨兵A向B发送成为领导者的申请,如果B没有同意过其他哨兵,则会同意A成为领导
如何推动故障切换流程并选出一个新master
1.新主登基:
1.某个Slave被选中成为新Master
2.选出新master的规则,剩余slave节点健康前提下
首选redis.conf中的优先级slave-priority或者replica-priproty最高 节点(数字越小越高)
其次,优先级一样时,再看复制偏移位置offset最大的节点
最后,偏移量相等时,选取Run ID最小的从节点
执行slaveof no one命令让选出的从节点成为新主节点,并通过slaveof命令让其它节点成为从节点
1.Sentinel leader会对选举出的新master执行slaveof no one操作,将其提升为master节点
2.Sentinel leader向其它slave发送命令,让剩余的slave成为新的master节点的slave
3.旧主拜服
1.将之前已下线的老master设置为新选出的新master的从节点,当老master重新上线后,它会成为新master的从节点
2.Sentinel leader会让原来的master降级为slave并恢复正常工作
使用建议:
1.哨兵节点的数量应为多个,哨兵本身应该集群,保证高可用
2.哨兵节点的数量应该是奇数
3.各个哨兵节点的配置性能应该一致
4.如果哨兵节点部署在Docker等容器里面,尤其是注意端口的正确映射
5.哨兵集群+主从复制,并不能保证数据零丢失
什么是集群?
Redis集群是一个提供在多个Redis节点间共享数据的程序集
Redis集群可以支持多个Master
1.Redis集群支持多个Master,每个Master又可以挂载多个Slave(读写分离、数据高可用、海量
数据的读写存储)
2.由于Cluster自带Sentinel的故障转移机制,内置了高可用的支持,无需再去使用哨兵功能
3.客户端与Redis的节点连接,不再需要连接集群中所有的节点,只需要任意连接集群中的一个即可
4.槽位slot负责分配到各个物理服务节点,由对应的集群来负责维护节点、插槽和数据之间的关系
注意:
Redis集群不保证强一致性,这意味着在特定的条件下,Redis集群可能会丢掉一些被系统收到的写入请求命令
什么是redis集群的槽位?
redis集群没有使用一致性hash,而是引入了哈希槽的概念
Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽。集群的每个节点负责一部分hash槽。举个例子,比如当前集群有3个节点
什么是分片?
1.使用Redis集群时我们会将存储的数据分散到多台redis机器上,这称为分片。简言之,集群中的每个Redis实例都被认为是整个数据的一个分片。
2.为了找到给定key的分片,我们对key进行CRC16(key)算法处理并通过对总分片数量取模。然后,使用确定性哈希函数,这意味着给定的key将多次始终映射到同一个分片,我们可以推断将来读取特定key的位置。
最大的优势:
这种结构很容易添加或者则除节点,比如果我想新添加个节点D,我需要从节点A,B,C中得部分槽到D上。如果我想移除节点A需要将A中的槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可。由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态。
2亿条记录就是2亿个k,v,我们单机不行必须要分布式多机,假设有3台机器构成一个集群,用户每次
读写操作都是根据公式:hash(key) %N个机器台数,计算出哈希值,用来决定数据映射到哪一个节点上。
优点:简单粗暴,直接有效,只需要预估好数据规划好节点,例如3台、8台、10台,就能保证
一段时间的数据支撑。使用Hash算法让固定的一部分请落到同一台服务器上,这样每台服务器固定处
理一部分请求(并维护这些请求的信息)起到负载均衡+分而治之的作用。
缺点:原来规划好的节点,进行扩容或者缩容就比较麻烦了,不管扩缩,每次数措变动导致节点有变
动,映射关系需要重新进行计算,在服务器个数固定不变时没有问题,如果需要弹性扩容或故障停机的
情况下,原来的取模公式就会发生变化:Hash(key)/3会变成Hash(key)/?,此时地址经过取余运算
的结果将发生很大变化,根据公式获取的服务器也会变得不可控。
某个redis机器宕机了,由于台数数量变化,会导致hash取余全部数据重新洗牌。
提出一致性Hash解决方案。目的是当服务器个数发生变动时,尽量减少影响客户端到服务器的映射关系。
3大步骤:
1.算法构建一致性哈希环
2.redis服务器IP节点映射
3.key落到Redis服务器的落键规则
一致性哈希环:一致性哈希算法必然有个hash函数并按照算法产生hash值,这个算法的所有可能哈希值会构成一个全量集,这个集合可以成为一个hash空间[0:2^32-1]
这个是一个线性空间,但是在算法中,我们通过适当的逻辑控制将它首尾期连(O= 2^32),这样让它逻辑上形成了一个环形空间。
IP节点映射:将集群中各个IP节点映射到环上的某一个位置。
将各个服务器使用Hash进行一个哈希,具体可以选择服务器的IP或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置。假如4个节点NodeA、B、C、D,经过IP地址的哈希函数计算(hash(ip)),使用IP地址哈希后在环空间的位置如下:
Key落到Redis服务器的落键规则:当我们需要存储一个kv键值对时,首先计算key的hash值,hash(key),将这个key使用相同的函数Hash计算出哈希值并确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该位到的服务器,并将该键值对存储在该节点上。
优点:
1.容错性
2.扩展性
缺点:
数据倾斜
容错性:
假设Node C宕机,可以看到此时对象A、B、D不会受到影响。一般的,在一致性Hash算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器〈即沿着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。简单说,就是C挂了,受到影响的只是B、C之间的数据且这些数据会转移到D进行存储。
扩展性:
数据量增加了,需要增加一台节点NodeX,X的位置在A和B之间,那受到影响的也就是A到X之间的数据,重新把A到X的数据录入到X上即可,不会导致hash取余全部数据重新洗牌。
数据倾斜:
一致性Hash算法在服务节点太少时,容易因为节点分布不均匀而造成数据倾斜(被缓存的对象大部分集中缓存在某一台服务器上)问题,
例如系统中只有两台服务器:
为了解决一致性哈希算法的数据倾斜的问题,哈希槽实质就是一个数组,数组以[0,2^14-1]形成hash slot空间。
解决了均匀分配的问题,在数据和节点之间又加入了一层,把这层称为哈希槽(slot),用于管理数据和节点之间的关系,现在就相当于节点上放的是槽,槽里放的是数据。
槽解决的是粒度问题,相当于把粒度变大了,这样便于数据移动。哈希解决的是映射问题,使用key的哈希值来计算所在的槽,便于数据分配。
一个集群只能有16384个槽,编号0-16383,(0-2^14-1)。这些槽会分配给集群中的所有主节点,分配策略没有要求。
集群会记录节点和槽的对应关系,解决了节点和槽的关系后,接下来就需要对key求哈希值,然后对16384取模,余数是几key就落入对应的槽里HASH_SLOT = CRC16(key) mod 16384。以槽为单位移动数据,因为槽的数目是固定的,处理起来比较容易,这样数据移动问题就解决了。
作者原回复翻译:正常的心跳数据包带有节点的完整配置,可以用幂等方式用旧的节点替换旧节点,以便更新旧的配置。
这意味着它们包含原始节点的插槽配置,该节点使用2k的空间和16k的插槽,但是会使用8k的空间(使用65k的插槽)。
同时,由于其他设计折衷,Redis集群不太可能扩展到1000个以上的主节点。
因此16k处于正确的范围内,以确保每个主机具有足够的插槽,最多可容纳1000个矩阵
但数量足够少,可以轻松地将插槽配置作为原始位图传播。请注意,在小型群集中,位图将难以压缩,因为当N较小时,位图将设置的slot /N位占设置位的很大百分比。
1.如果槽位是65536,发送心跳消息的消息头达8k,发送的心跳包过于庞大
在消息头中最占空间的是myslots[CLUSTER_SLOTS/8]。当槽位为65536时,这块的大小是:65536÷8÷1024=8kb
在消息头中最占空间的是myslots[CLUSTER_SLOTS/8]。当槽位为16384时,这块的大小是:16384∶8÷1024=2kb
因为每秒钟,redis节点需要发送一定数量的ping消息作为心跳包,如果槽位为65536,这个ping
消息的消息头太大了,浪费带宽。
2.redis的集群主节点数量基本不可能超过1000个
集群节点越多,心跳包的消息体内携带的数据越多。如果节点过1000个,也会导致网络拥堵。
因此redis作者不建议redis cluster节点数最超过1000个。那么,对于节点数在1000以内的
redis cluster集群,16384个槽位够用了。没有必要拓展到65536个。
3.槽位越小,节点少的情况下,压缩比高,容易传输
Redis主节点的配置信息中它所负责的哈希槽是通过一张bitmap的形式来保存的,在传输过程中
会对bitmap进行压缩,但是如果bitmap的填充率slots/N很高的话(N表示节点数),bitmap的压缩
率就很低。如果节点数很少,而哈希槽数量很多的话,bitmap的压缩率就很低。
1.配置文件的编写
bind 0.0.0.0//服务监听地址,用于客户端连接,默认本机地址
daemonize yes//是否以后台daemon方式运行
protected-mode no//安全保护模式
port 6381//端口,哨兵的端口号和redis的端口号不是一回事
logfile "/myredis/sentine126379.log"//日志文件路径
pidfile /var/run/redis-sentine126379//pid文件路径
dir myredis/cluster//工作目录
dbfilename dump6381.rdb
appendonly yes
appendfilename "appendonly6381.aof"
requirepass 111111
masterauth 111111
cluster-enabled yes
cluster-config-file node-6381.conf
cluster-node-timeout 5000
2.启动6台redis主机实例
redis-server /myredis/cluster/redisCluster6381.conf
3.通过redis-cli命令为6台机器构建集群关系
构建主从关系
redis-cli -a 111111 --cluster create --cluster-replicas 1 192.168.111.175:6381 192.168.111.175:6382 192.168.111.172:6383 192.168.111.172:6384 192.168.111.174:6385 192.168.111.174:6386
//--cluster create以集群方式创建
//--cluster-replicas 1为每个master创建一个slave
4.查看并检验集群的状态
redis-cli -a 111111 -p 6381
info replication
cluster info
cluster nodes
5.以路由的方式使用redis客户端连接
会把不属于该节点的数据重定向到应该收到该数据的节点
redis-cli -a 111111 -p 6381 -c
CLUSTER KEYSLOT k1 //会查看k1的槽位号
6.节点从属调整
CLUSTER FAILOVER//节点从属关系就变了,主变从,从变主
7.集群扩容
加入集群:
redis-cli -a 111111 --cluster add-node 192.168.111.174:6387 192.168.111.175:6381
槽位重新分配:
redis-cli -a 111111 --cluster reshard 192.168.111.185:6381//新节点是之前的节点匀过来的,不是连续的槽号,6381是集群内的一个节点
然后选择移过去多少槽
选择节点ID
为主节点增加从节点
redis-cli -a 111111 --cluster add-note 主节点ip:端口 从节点ip:端口 --cluster-slave --cluster-master-id 主节点的ID
检查集群的情况
redis-cli -a 111111 --cluster check 192.168.111.175:6381
8.集群缩容
先清除从节点
redis-cli -a 密码 --cluster check 从节点的ip和端口号,目的是找到从节点ID
redis-cli -a 密码 --cluster del-node ip:slave端口号 从节点ID//从集群中删除从节点
redis-cli -a 密码 --cluster reshard 集群中的一个节点ip和端口号
redis-cli -a 密码 --cluster del-node ip:master端口号 主节点ID//从集群中删除主节点
清出来的槽号重新分配给集群剩余的节点
删除主节点
恢复清除之后的集群
其它:
不在同一个槽位下的键值无法使用mset、mget等多键操作
解决:
mset k1{z} z1 k2{z} z2 k3{z} z3 //将key打包后就会存到一个主机上
mget k1{z} k2{z} k3{z}
常用配置:
cluster-require-full-coverage //集群是否完整才能对外提供服务,默认是yes。
CLUSTER COUNTKEYSINSLOT 槽位数字编号 //查看某个槽位是否被占用
CLUSTER KEYSLOT 键名称 //该键应该存在哪个槽位上