Redis笔记
准备
概念
- 字典结构的存储服务器
- 多个字典,对应关系型数据库的不同database
- 单线程
命令
启动、结束
redis-server #启动redis redid-cli shutdown #关闭Redis redis-cli #Redis命令行工具
全局命令
dbsize #获取redis中全部key的数量 keys * #获取全部key ping echo config set #设置Redis配置信息 config get * #获取Redis配置信息 select 1 #选择第一个数据库,Redis默认有16个,集群默认使用第一个(0号数据库)且只有一个
入门
String
- 定义
- 最大512M
- 命令
- 取值赋值
set
Mset
get
Mget
- 取值赋值
- 增加整数
incr
incrBy
incrByFloat
decr
decrBy
- 位操作
getBit
setBit
bitCount
bitOp
bitPos
- 其他
exists
del
strLen
append
(追加)
List
定义
- 字符串列表
- 基于双向链表
- 有序、不唯一
- 最多2^32 -1 头尾时间复杂度是O(1)
应用
- 新鲜事
- 日志
- 队列
命令
- 取值赋值
- 两端增加
LPUSH key ele[eles...]
rpush
- 两端弹出
LPOP key [count]
rpop
- 根据索引
LINDEX key index
(获取索引处值)LSET key index ele
(修改索引处值)RpopLpush source target
(转移元素)
- 两端增加
- 取值赋值
片段
- 获取片段
lrange 0 -1
(索引从0开始、正数从左边,负数从右边) - 保留片段
trim 0 -1
- 获取片段
删除指定值
LREM key count value
- count > 0 - 从左边开始删除count个value - count < 0 - 从右边开始删除count的绝对值个value - count = 0 - 删除全部的value
其他
llen
Set
- 定义
- 基于值为空的hash表
- 无序、唯一
- 最多2^32 -1
- 时间复杂度是O(1)
- 因为hash
- 命令
- 取值赋值
sadd
srem
smembers
SrandMember key count
count > 0 获取不重复的元素 count < 0 可能获取重复的元素spop
随机移除 - 集合计算
- 差集
sdiff
sdiffstore
- 交集
sinter
sinterstore
- 并集
sunion
sunionstore
- 差集
- 其他
sismember
(是否存在)scard
(数量)
- 取值赋值
ZSet
定义
- 基于哈希表和跳跃表
- 有序、唯一
- 关联一个分数权值,按从大到小排序
- 和List相比
- 同
- 都是有序的
- 都可以获取片段
- 异
- List基于链表,中级数据获取慢,ZSet获取每个位置都一样
- List不能调整某个元素的位置,ZSet可以(通过调整分数)
- ZSet更费内存
- 同
命令
取值赋值
zadd
zRem
(删除一个或多个)zRemRangeByRank key starts stop
(按照排名范围删除)zRemRangeByScore key starts stop
(按照分数范围删除)获取片段
ZRANGE key min max [withscores]
根据排名返回[min,max]
之间的元素 分数相同按字典顺序 从小到大ZrevRANGE key min max [withscores]
根据排名返回[min,max]
之间的元素 从大到小- zRangeByScore key min max limit offset count 根据分数返回
[min,max]
之间的元素,支持偏移 从小到大 - zRevRangeByScore key min max limit offset count 根据分数返回
[min,max]
之间的元素,支持偏移 从大到小
参数
- 负无穷(-inf)
- 正无穷(inf)
- 不包含(()
分数
zadd key score member
(修改分数)zscore key member(
获取分数)zIncrBy key increment member
(修改分数)
increment > 0 增加 increment < 0 减少集合计算
- 差集
zDiff
zDiffStore
- 交集
zInterStore
- 并集
zUnionStore
- 差集
其他
- sismember(是否存在)
- zRank(获取元素排名、分数最小为 0)
- zRevRank(获取元素排名、分数最大为 0)
- 数量
- zCard
- zCount(获取指定范围的元素数量)
- zLexCount
Hash
- 定义
- 最多2^32 -1
- 命令(针对字段)
- 取值赋值
hset
Mhset
hget
Mhget
hgetAll
hsetNX
存在不执行操作 不存在= hsethexists
hdel
- 增加整数
hincrby
- 只获取key、value
hkeys
hvals
- 其他
hlen
- 取值赋值
自定义类型
进阶
事务
- 好处
- 保证原子性
- 保证顺序性
- 错误处理
- 语法错误
- 全部不执行
- 运行错误
- 正确的执行,错误的不执行
- 语法错误
- 命令
multi
exec
watch
unWatch
过期时间
- 命令
- 设置过期时间
- expire key second
- pExpire key milliSecond
- expireAt key timestap
- pExpireAt key millisecond-timestap
- 清除过期时间
- persist
- set
- getset
- ttl
- 【Time To Live】生存时间
- -1永不过期
- -2键不存在
- 设置过期时间
- 缓存系统
- key过期时间不好确定
- 时间长-浪费内存
- 时间短-命中率低
- 设置最大内存
- 内存淘汰策略
- LRU
- 【List Recently Used】最近最少使用
- 随机取
maxmemory-samples
个,删除最少使用的
- 随机取
- 【List Recently Used】最近最少使用
- volatile-LRU
- 使用LRU删除设置了ttl的键
- allkeys-LRU
- 使用LRU删除全部键
- volatile-random
- 随机删除设置了ttl的键
- allkeys-random
- 随机删除全部键
- volatile-TTL
- 删除ttl最近的一个键
- 随机取
maxmemory-samples
个,删除ttl最近的
- 随机取
- 删除ttl最近的一个键
- noEviction
- 不删除键,只返回错误
- LRU
- key过期时间不好确定
排序
- sort
- alpha
- 默认转为double类型来排序
- desc
- 倒序
- limit
- 返回指定个数
- by
SORT tag:ruby:posts BY post:*->time
- 使用
tag:ruby:posts
的值替换 *,获取对应hash的time值进行排序
- get
- get # 返回元素本身的值
- store
- 保存后的键类型为List
- 通常结合 expire 缓存
- alpha
- 性能优化
- 时间复杂度
- O(n + mlog(m))
- n为需要排序的元素个数
- m为需要返回的元素个数
- n尽可能小
- m尽可能小
- 大数据量排序,记得缓存
- 时间复杂度
消息通知
- 消息队列
- 生产者
- 把消息存入队列
- 消费者
- 从队列中获取消息消费
- 好处
- 解耦合
- 降覆载
- 队列
- 普通队列
- Lpush
- Rpop
- 优先级队列
bRpop key [key...] timeout
- 优先监控key1,如果没有返回后面的key2,key3中的值,如意有先返回key1中的值
- 如果没有值会阻塞timeou时间,0表示一直阻塞
- 普通队列
- 发布\订阅
- publish
- subscribe
- unSubscribe
- pSubscribe
- pUnSubscribe
- 按照规则订阅
- 取消订阅是正则表达式必须完全匹配
- pUnSubscribe
- 生产者
管道
- 批量执行相互不依赖的命令
节省空间
- 精简键名和键值
- 内部编码优化
- String
- REDIS_ENCODING_RAW
- rwa
- REDIS_ENCODING_INT
- int
- REDIS_ENCODING_RAW
- List
- REDIS_ENCODING_ZIPLIST
- zipList
- REDIS_ENCODING_LINKEDLIST
- linkedList
- REDIS_ENCODING_ZIPLIST
- Set
- REDIS_ENCODING_HT
- hashTable
- REDIS_ENCODING_INTSET
- intSet
- REDIS_ENCODING_HT
- ZSet
- REDIS_ENCODING_SKIPLIST
- skipList
- REDIS_ENCODING_ZIPLIST
- zipList
- REDIS_ENCODING_SKIPLIST
- Hash
- REDIS_ENCODING_EMBSTR
- embStr
- REDIS_ENCODING_HT
- hashTable
- REDIS_ENCODING_EMBSTR
- String
持久化
RDB
- 符合条件时,将内存中的全部快照到硬盘
- 根据配置规则自动快照
- 每当M时间修改了大于N个键时快照
- save 900 1
- 900s内修改了大于1个键时快照
- 每当M时间修改了大于N个键时快照
- 执行SAVE、BGSAVE命令
- SAVE会阻塞所有来自客户端的请求
- BGSAVE异步进行快照
- 通过lastSave查看上次快照时间
- 执行FLUSHALL命令
- 依赖于自动快照条件
- 只要自动快照条件不为空,flushall就会快照
- 依赖于自动快照条件
- 执行复制(replication)时
- 没有定义自动快照条件也会快照
- 根据配置规则自动快照
- 原理
- 从当前进程(父进程)fork一份到子进程
- 父进程继续接受命令,子进程开始保存到磁盘的临时文件
- 子进程写完后,替换上次生成的dump.rdb文件
- 新的.rdb文件保存的是执行fork命令是的数据
- 如果异常退出,会丢失最后一次快照之后修改的数据
AOF(append only file)
- 将redis执行的每一条命令保存到硬盘
- 为了避免冗余,满足一定条件会自动重写AOF文件
- 自动重写
- auto-aof-rewrite-percentage
- 达到之前AOF文件的百分之多少重写
- auto-aof-rewrite-min-size
- 允许重写的最小AOF文件大小
- auto-aof-rewrite-percentage
- 手动重写
- bgRemWriteAOF
- 自动重写
- 需要跳过系统的磁盘缓存机制,写入AOF后主动从磁盘缓存同步硬盘
- appendFSync
- always
- 每次写入都同步
- everySec
- 每秒执行一次同步
- no
- 不跳过
- always
- appendFSync
- 区别
- AOF载入速度慢
- 重新执行AOF中保存的命令
集群
复制
- 主数据库
- 从数据库
- 一般是只读的
- 从数据库也可以有从数据库
- 乐观复制
- 需要一定时间内主从不一致
- 原理(复制初始化)
- 从数据库启动,向主数据库发送sync同步请求
- 主数据库接收到sync请求后,执行RDB持久化操作,同时缓存快照期间的命令
- 快照完成后,发送给从数据库
- 从数据库接收后,载入快照,执行收到的缓存的命令
- 优点
- 读写分离
- 主数据库写
- 从数据库读
- 持久化
- 主数据库关闭持久化
- 从数据库来持久化
- 故障
- 主数据库故障
- 提升从数据库为主数据库
- 重启数据库,并设置为从数据库
- 禁止自动重启
- 因为主数据库没有开启持久化,会清空全部数据,然后导致从数据库数据也清空
- 从数据库故障
- 自动同步主数据库数据
- 主数据库故障
- 读写分离
- 缺点
- 即使关闭主数据库的RDB快照,执行【复制初始化】依然会生成RDB文件
- 主数据下次启动会读取RDB文件,因为复制时间不确定,所以数据不确定
- 硬盘性能瓶颈
- 即使关闭主数据库的RDB快照,执行【复制初始化】依然会生成RDB文件
- 无硬盘复制
- 不持久化读写硬盘,之间通过网络发送个从数据库
- 增量复制
- 断线重连
- 原理
- 基础
- 从数据库保存主数据的run ID
- 复制同步阶段,主数据库把每一个传给从数据的命令保存到一个【积压队列】,同时记录命令偏移范围
- 复制同步阶段,从数据库接收命令时,保存命令偏移量
- 实现
- 从数据发送同步请求命令
- PSync 主数据ID 命令偏移量
- 主数据库判断ID是否一致
- 主数据库判断命令偏移量是否在【积压队列】
- 在,增量复制
- 不在,全量复制
- 从数据发送同步请求命令
- 基础
哨兵
- 独立的进程
- 监控主从数据库是否正常运行
- 主数据出现故障,自动将从数据库提升为主数据库
- 监控其他哨兵
- 和数据库建立两个连接
- 一个订阅数据库的哨兵频道
- 一个用来发送命令
- 和哨兵建立一个连接
- 发送PING命令
- 操作
- 每 10s 向主从数据库发送INFO信息
- 第一次,解析INFO,获取当前数据库信息
- 之后,向已知的数据库发送INFO,解析IFNO,更新数据库信息
- 每 2s 向从数据库哨兵频道发送自身信息
- 与其他哨兵同分享信息
- 每 1s 向主从数据库和其他哨兵发送PING信息
- 判断是否下线
- 每 10s 向主从数据库发送INFO信息
- 工作
- 判断下线
- 主观下线
- 一个哨兵发现了主数据库下线
- 向其他哨兵发送请求是否发现主数据库下线
- 一个哨兵发现了主数据库下线
- 客观下线
- 超过quorum的哨兵发现主数据库下线
- 主观下线
- 选举领头哨兵
- Raft算法
- 第一个发现下线的哨兵A要求其他哨兵选自己为领头哨兵
- 其他哨兵如果没有选过其他哨兵,则选A为领头哨兵
- 如果有半数并且> quorum的哨兵选择A,则A成为领头哨兵
- 如果没有选成功,等待一个随机时间重新选
- Raft算法
- 选取主数据库
- 选择优先级最高的
- 同优先级选择命令偏移量最大的
- 优先级、命令偏移量一样,选择ID最小的
- 判断下线
- 部署
- 每个节点设置一个哨兵
- 设置quorum = N /2 +1
- N为哨兵数量
集群
- 默认使用 0号数据库,且不能切换