Redis
2021-11-03 10:21:09 0 举报
AI智能生成
Redis知识图谱
作者其他创作
大纲/内容
Redis基础介绍
C语言开发
Redis中所有的key都存在一个很大的字典中,这个字典结构和Java中的HashMap一样,scan指令返回的游标就是一维数组的位置索引,我们将这个位置索引称为slot(槽)
大key扫描
在集群环境下,如果某个key太大,会导致数据迁移卡顿
在内存分配上,如果key太大,当他需要扩容时,会一次性申请更大的一块内存,也会造成卡顿
当大key被删除,内存被一次性回收也会产生卡顿
Redis原理
线程IO模型
Redis是用单线程处理用户请求的,所以对于时间复杂度为O(n)的指令要谨慎使用,否则一不小心就会造成Redis卡顿
非阻塞IO
多路复用(select)
多路复用(epoll)
通信协议RESP
Redis Serialization Protocol的缩写
是一种直观的文本协议,实现过程异常简单,解析性能极好
持久化
RDB
一次全量备份
内存数据的二进制序列化形式,在存储上非常紧凑
使用操纵系统的多进程COW(copy on write)机质来实现快照持久化
AOF
连续的增量备份,只记录对内存进行修改的指令记录
Redis在收到客户端的修改指令后,进行参数校验,逻辑处理,没问题再将该指令文本存储到AOF日志中
AOF日志瘦身,记录内存数据修改的指令记录文本,AOF日志在长期的运行过程中会变得无比庞大,需要定期进行AOF重写,给AOF日志瘦身
数据库重启时需要进行AOF重放
fsync
混合持久化
将rdb文件的内容和增量的AOF日志文件存在一起,这里的AOF日志是自持久化开始到持久化结束这段时间发生的增量AOF日志,通常这部分AOF日志很小
管道
事务
常用指令
watch
multi
exec
discard
所有指令在exec之前不执行,而是缓存在服务器的一个事务队列中,服务器一旦受到exec指令,才开始执行整个事务队列,因为redis是单线程的,可以保证事务中的命令得到“原子性”执行,但其实,指令失败后,后续的指令还是会执行。所以Redis事务其实不具备原子性,而是仅仅满足了事务的隔离性
watch是一种乐观锁,当exec指令执行时,会检查watch中的变量是否修改,如果修改了会返回Null,客户端可以选择重试
小对象压缩
内存回收机质
redis将内存分配的细节交给了第三方内存分配库去实现
google的tcmalloc
facebook的jemalloc
Redis并不总是将空闲内存立即归还给操作系统
集群
CAP
Consistent:一致性
Availability:可用性
Partition tolerance:分区容忍性
最终一致性
主从同步
增量同步
buffer环
偏移量
快照同步
快照同步死循环
无盘复制
wait指令
从从同步
增加从节点
快照同步
增量同步
可用性
Sentinel
监控主从节点的健康
挂掉的主节点恢复后不会抢主
无法保证该消息完全不丢失
min-slaves-to-write 1
min-slaves-max-lag 10
默认端口是26379
集群方案
Codis
特点
中国人开发
Go语言开发
使用Redis协议对外提供服务
只是一个转发代理中间件,是无状态的
分片原理
默认将key划分为1024个槽位,槽位信息存储在zk或者etcd中
crc32算法
不同Codis实例之间槽位关系同步
zookeeper
etcd
扩容
SLOTSSCAN
自动均衡
Codis的代价
不能再支持事务了
rename操作可能无法正确完成
单个key对应的value不宜过大
因为增加了Proxy作为中转层,所以在网络开销上比单个Redis大
增加了zookeeper运维的代价
Codis的优点
设计上比Redis Cluster官方集群方案简单,因为将分布式的问题交给了zookeeper或etcd去负责
Codis的缺点
因为不是Redis的官方项目,它总要被官方Redis牵着鼻子走
mget指令操作
将key按照所分配的实例打散分组,然后依次对每个实例调用mget方法,最后将结果汇总为一个返回给客户端
Redis Cluster
Redis的亲儿子
通过特殊的二进制协议交互集群信息
去中心化,分为16384个槽位,槽位信息存储于每个节点中
Redis Cluster的客户端来连接集群时,会得到一份集群的槽位配置信息。当客户端要查找某个key时,可以直接定位到目标节点
纠正机质
crc16算法
允许用户强制把某个key挂在特定的槽位上,通过key字符串里面嵌入tag标记
跳转,当客户端像一个错误的节点发出了指令后,该节点会发现指令key所在的槽位并不归自己管理,这事它会向客户端发送一个特殊的跳转指令携带目标操作的节点地址,告诉客户端去连接这个节点以获取数据
-MOVED 3999 127.0.0.1:6381
迁移,Redis Cluster提供了工具redis-trib,可以让运维人员手动调整槽位的分布情况,也提供了自动化平移槽位工具
节点状态
源节点的状态为migrating
中间过渡状态
目标节点的状态为importing
迁移过程中,客户端访问流程
容错,Redis Cluster可以为每个主节点设置若干个从节点,当主节点发生故障时,集群会自动将某个从节点提升为主节点
如果某个主节点没有从节点,那么当他发生故障时,集群将完全处于不可用状态
如果某个主节点没有从节点,那么当他发生故障时,集群将完全处于不可用状态
网络抖动
可能下线PFail与确定下线Fail
不支持事务,mget方法比redis慢很多,rename方法不再是原子的,因为要将数据从源节点转移到目标节点
集群变更感知
数据结构
String 字符串
内部表示是一个字符数组,类似于Java的ArrayList
采用预分配冗余空间的方式来减少内存的频繁分配
字符串长度小于1MB时,加倍扩容,超过1MB时,一次增加1MB,最大支持512MB
常用命令
set
mset
get
mget
exists
setnx
incr
incrby
decr
list 列表
相当于Java语言中的LinkedList,是链表而不是数组,插入删除快,查找慢
底层数据结构是“快速链表”
常用命令
rpush
lpush
rpop
lpop
llen
lindex
ltrim
hash 字典
相当于Java语言中的HashMap,是无序字典,结构上也是数组+链表实现
采用渐进式rehash策略
常用命令
hset
hmset
hgetall
hlen
hincrby
set 集合
相当于Java语言里面的HashSet,内部键值对是无序唯一的,内部实现相当于一个特殊的字典,字典中所有的value都是Null
常用命令
sadd
smembers
sismember
scard
spop
zset有序列表
类似于Java语言中的SortedSet和HashMap的集合体,可以给每个value赋予一个score,代表这个value的排序权重
内部实现是“跳跃列表”
常用命令
zadd
zrange
zrevrange
zcard
zscore
zrank
zrangebyscore
zrem
bitmap位图
最小的单位bit,每个bit的值只能是0或1
零存整取
整存零取
常用命令
bitcount
bitpos
bitfield
get
set
incrby
HyperLogLog
提供不精确的去重计数方案,标准误差是0.81%
在计数比较小的时候,采用稀疏矩阵存储,当占用空间超过阈值时,会一次性转变为稠密矩阵,占用12kb的存储空间
记录低位连续零位的最大长度K,通过这个K值估算出随机数的数量N
常用命令
pfadd
pfcount
pfmerge
Bloom Filter布隆过滤器
用来解决去重问题的,在起到去重作用的同时,在空间上还能节省90%以上,有一定的误判概率
可以理解为一个不怎么精确的set结构
布隆说某个值存在,可能不存在
布隆说某个值不存在,一定不存在
Redis4.0之后才出现,作为一个插件加载到Redis Server中
常用命令
bf.add
bf.exists
bff.madd
bf.mexists
使用前可以通过bf.reserve创建,需要三个参数,key,错误率和初始size
底层实现是一个大型的位数组和几个不一样的无偏hash函数
当用户来查询某个row时,先通过布隆过滤器过滤掉大量不存在的row请求,然后在再去磁盘中进行查询
Redis-Cell限流模块
采用漏斗算法
cl.throttle
cl.throttle k 15 30 60 1
返回允许或者拒绝,漏洞容量,漏斗剩余容量,需要多久再次重试,过多久完全空出来
GeoHash模块
3.2版本后增加
常用命令
geoadd
geodist
georadiusbymember
georadius
存储结构上使用的是zset,意味着我们可以使用zset相关的指令来操作Geo数据
scan
2.8版本后增加
时间复杂度是O(n),但它是通过游标分步进行的,不会阻塞线程
服务器不需要要位游标保存状态,游标的唯一状态就是scan返回给客户端的游标整数
返回的结果可能会重复,需要客户端去重
单次的结果是空并不意味着遍历结束,而是要看返回的游标值是否为零
scan 0 match key99* count 1000
采用高位进位加法,防止扩容和缩容时槽位遍历重复和遗漏
分布式锁
分布式锁的本质上要实现在Redis中占一个坑,一般使用指令setnx加锁,执行完再调用del释放锁
在锁上加上过期时间,set k v ex time nx
0 条评论
下一页