Redis(数据类型/事务/持久化/集群)
2021-02-06 15:46:06 25 举报
AI智能生成
Redis
作者其他创作
大纲/内容
数据类型
基本类型
String:基本的字符串类型,set、get
可做简单的key-value缓存
实现计数器
List:有序列表,异步解耦
实现高性能分页
实现消息队列:例如到货通知、邮件发送
Set:无序集合,自动去重
利用交集查看共同粉丝列表
ZSet:有序集合,自动去重
写数据带分数,实现排行榜
Hash:Map集合
特别适合存储对象,可单独修改对象中的字段
特殊类型
Pipeline(管道)
管道就是打包多条无关命令批量执行,以减少多个命令分别执行消
耗的网络交互时间(TCP网络交互),可以显著提升Redis的性能
耗的网络交互时间(TCP网络交互),可以显著提升Redis的性能
Geospatial
地理空间,可以录入地理坐标并计算距离
底层实现原理是ZSet
Hyperlogglog
基数统计的算法,根据并集的数量来计数
占用的内存固定,只需要12kb的内存,有0.81%错误率
Bitmaps
位存储,使用二进制记录,只有0和1两种状态
可以用来统计用户信息、打卡,两个状态的都可以
常见问题
概念性
redis是什么?
基于内存的高性能nosql数据库
redis为什么有16个库?
在单个库中不允许存在重复key
用来区分不同的业务逻辑
单线程
redis是单线程吗?为什么?
这里的单线程是指Redis在处理网络请求的时候只有一个线程来处理
为什么单线程效率还很高?
redis采用IO多路复用原则,通过epoll去遍历,不会频繁的创建线程
数据结构
redis如何存放对象?
基于Json序列化存放
优点:阅读性强、可以跨语言
缺点:明文不安全
基于String的二进制存放
优点:比较安全
缺点:不支持跨语言、阅读性差
redis是c语言写的为什么String用SDS?
获取长度:c字符串并不记录自身长度,想获取只能遍历,sds直接获取len即可
缓冲区安全:c字符串容易造成缓冲区溢出,sds先检查空间,不够就扩容
内存分配:c字符串每次长度变化都会对数组进行内存重新分配,比较耗时
为什么zset使用跳跃表而不用红黑树?
跳跃表的时间复杂度和红黑树一样,而且实现起来更简单
在并发环境下红黑树在插入和删除时需要rebalance,性能不如跳跃表
缓存
缓存穿透
大量请求一个数据库不存在的数据
查询为空也暂时放入缓存
接口层增加校验
布隆过滤器
缓存击穿
热点key扛高并发,缓存失效的瞬间
热点数据不失效
互斥锁
缓存雪崩
缓存服务器宕机或者缓存集中失效
给缓存加随机因子,分散失效时间
对redis缓存做高可用,集群部署,增加抗风险能力(前)
设置本地缓存ehcache+限流hystrix,避免数据库被干掉(中)
利用redis的持久化机制,重启redis快速恢复缓存数据(后)
数据一致性
缓存双写一致性?
先删缓存再更新数据库,期间有查询呢?
先更新数据库再删缓存,缓存删除失败呢?
延迟双删:先删缓存再更新数据库,等几百毫秒
再删缓存 (延迟时间根据具体的业务耗时而定)
再删缓存 (延迟时间根据具体的业务耗时而定)
并发竞争?
分布式锁
set key value px milliseconds nx 或使用 jedis
注意点
value要具有唯一性,可用UUID.randomUUID().toString()方法生成
释放锁时使用lua脚本保证原子性,并验证value值,防止误解锁
存在的风险
如果存储锁对应key的那个节点挂了的话,就可能存在丢失锁
的风险,导致出现多个客户端持有锁的情况
的风险,导致出现多个客户端持有锁的情况
解决
redis官方提供了RedLock算法
Redisssion
大key
原生自带的bigkeys命令,找出来拆分或者删除
热点key
如何发现热点key?
凭借业务经验,进行预估哪些是热key
客户端收集,在操作redis前对数据进行统计
使用redis自带命令:redis-cli 时加上 –hotkeys
如何解决热点key?
备份热点key
热点Key+随机数,随机缓存至Redis其他节点中
分散一台redis服务器上的压力
利用多级缓存
添加本地缓存缓解redis压力
读写分离扩容
增加从节点增加读能力
设置永不过期
防止缓存击穿
事务
概念
Redis 事务的本质是一组命令的集合。事务支持一次执行多个命令,一个事务中所有命令都会被序列化
一句话:Redis 事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令
特点
没有隔离级别的概念
批量操作在事务提交前被放入缓存队列,并不会被实际执行
不保证原子性
Redis中单条命令是原子性执行的,但事务不保证原子性,且没有回滚
事务中任意命令执行失败,其余的命令仍会被执行
三阶段
开始事务、命令入队、执行事务
相关命令
watch key1 key2 ...:监视一或多个key,如果在事务执行前,被监视的key被其他命令改动,则事务执行失败
multi:标记一个事务块的开始
exec:执行所有事务块的命令(一旦执行exec后,不论成功与否,之前加的监控锁都会被取消掉)
discard:取消事务,放弃事务块中的所有命令
unwatch:取消watch对所有key的监控
常见问题
若在事务队列中存在「命令性错误」,则执行EXEC命令时,所有命令都不会执行
若在事务队列中存在「语法性错误」,则执行EXEC命令时,错误命令抛出异常,其他正确命令会被执行
持久化
RDB
原理
redis会单独创建(fork)一个与当前进程一模一样的子进程来进行持久化,
将数据写入到一个临时文件中,待持久化结束后替换上次持久化好的文件
将数据写入到一个临时文件中,待持久化结束后替换上次持久化好的文件
触发
redis.conf配置文件中有快照配置,例如 save 900 1(15分钟内有1次修改)
客户端执行shutdown正常退出时,如果没有开启aof会触发
执行save或bgsave命令(save命令会阻塞主进程一般不用,bgsave会fork子进程异步持久化)
优点
恢复的时候比较快,适合大规模的数据恢复,冷备
缺点
如遇突然宕机,丢失的数据比较多
如果生成的快照文件比较大也会影响redis性能
AOF
原理
redis所有的写命令会追加到 AOF 缓冲区中,根据对应的策略向硬盘进行同步操
作,随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的
作,随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的
触发
需手动开启:appendonly yes
只保留 save 900 1 减少fork子线程的次数(优化点)
写入策略:appendsync
no:等到缓冲区满了才写入磁盘,次数少,效率高,不安全
always:每次发生数据变更立即同步到磁盘,效率低,安全
everysec:每秒同步一次,效率高,可能会丢失1秒的数据【默认】
重写机制
参数设置
auto-aof-rewrite-min-size 5G(优化点)
备份文件大于该配置时重写
auto-aof-rewrite-percentage 100
这里指超过原大小的100%时开始重写
重写会fork子进程
优点
以append-only模式写入,没有磁盘寻址开销,写入性能高
相比于RDB,丢失的数据更少,不过建议与RDB同时开启
缺点
不适合冷备,恢复文件大,速度慢,恢复不稳定,容易bug
混合持久化
手动开启:aof-use-rdb-preamble yes
5.0以后默认开启
重写机制优化
重写后新的AOF文件前半段是RDB格式的全量数据,后半段是AOF格式的增量数据
优点
由于绝大部分都是RDB格式,加载速度快,同时结合AOF,增量的数据得以保存,数据更少丢失
缺点
兼容性差,4.0以前不识别该aof文件,可读性差
集群
主从复制
一主多从,读写分离
主负责写,写完同步到从节点,从负责读
可水平扩容,QPS再增加只需添加slave就ok了
主从复制产生短暂的数据延迟是允许的,保证最终一致性
数据同步
全量复制
增量复制
过期key处理
slave不会过期key,只会等待master过期通知
主从+哨兵
概念
哨兵是一个分布式系统,监控主从架构中的节点通过自动故障转移保证集群的高可用
哨兵也是一台redis服务器,只是不提供任何服务,推荐配置为单数
避免相同票
主要功能
监控
监控主节点和从节点是否正常运行
通知
检测到服务出现问题会通知其他哨兵
自动故障转移
当确认主节点宕机后,在从节点中选一个作为主节点,将
其他从节点连接到新的主节点上,通知客户端最新的地址
其他从节点连接到新的主节点上,通知客户端最新的地址
工作原理
发现master节点宕机
一台哨兵发现master宕机了,标记为sdown(主观下线),并通知其他哨兵
其他哨兵去查看,如果超过quorum数量的哨兵认为挂了就标记为odwon(客观下线)
选出一个哨兵去处理
每个哨兵作为参选者和投票者,向哨兵内网发送指令
指令中携带自己的竞选次数和runid,先收到谁的指令就投票给谁
哨兵从服务器列表中挑选master
先过滤掉不在线和响应慢的服务器
然后过滤掉与原master断开时间最久的
最后再比较优先级priority、偏移量offset、runid
新master诞生
哨兵向选举出的新master发送指令,断开与旧master的连接
把新master的ip地址同步到其他slave节点
redis cluster
为什么使用redis cluster
主从复制的缺点:master单点故障
主从+哨兵缺点:节点数据冗余
redis cluster
动态扩容和缩容,保证数据不冗余,且吞吐量更大
自动数据分片,每个master节点存放一部分数据
提供内置的高可用支持,允许部分master节点宕机
数据分片方案
客户端
客户端使用一致性哈希等算法决定键应当分布到哪个节点
中间层
将客户端请求发送到代理上,由代理转发请求到正确的节点上
国内豌豆荚的Codis
国外Twiter的twemproxy
服务器
hash slot 算法
Redis Cluster
元数据维护
集中式
将元数据(节点信息、故障)存储在某个节点上
优点:时效性好,同步快
缺点:更新压力和存储压力集中
gossip协议
去中心化
每个节点都持有一份元数据
优点:缓解了元数据更新和存储的压力
缺点:元数据更新延迟,集群操作滞后
通信机制
Meet:集群中的节点会向新的节点发送邀请,加入现有集群
Ping:节点向集群中的其他节点发送ping消息传递自己的节点信息
Pong:收到ping消息的节点会回复pong,消息中同样携带节点信息
Fail:ping不通某节点会向集群中的其他节点广播该节点挂掉的消息
redis cluster基于gossip协议的故障检测
节点间内部通信
采用gossip协议,每个节点都有一个专门用于节点间通信的
端口,就是自己提供服务的端口号+10000
端口,就是自己提供服务的端口号+10000
集群中的每个节点都会定期地向集群中的其他节点发送PING
消息,以此交换各个节点状态信息,检测各个节点状态
消息,以此交换各个节点状态信息,检测各个节点状态
高性能的主备切换
判断master宕机
PFAIL->超半数->FAIL
从节点过滤
过滤掉与master断开时间长的slave
master选举
slave发现自己的master的状态变为FAIL
将自己记录的选举轮次标记加1,并广播
通知给集群中其他节点
通知给集群中其他节点
其他节点收到该信息,只有master响应,
判断请求者的合法性,并发送结果
判断请求者的合法性,并发送结果
尝试选举的slave收集master返回的结果,
收到超过半数master的统一后变成新Master
收到超过半数master的统一后变成新Master
广播Pong消息通知其他集群节点
分布式寻址算法
hash算法
计算请求数据的hash值,并按照节点数量取模,再放入对应的master节
点中,如果某台master宕机了,由于master数量少了导致取模方式改变
点中,如果某台master宕机了,由于master数量少了导致取模方式改变
缺点:会造成大量缓存重建
一致性hash算法+虚拟节点
把请求数据的hash值对应在圆环的各个点上,然后顺时针寻找
离自己最近的master节点,如遇master宕机只会影响部分数据
离自己最近的master节点,如遇master宕机只会影响部分数据
基于上面的一致性hash算法,再在各个master节点之间创建均
匀分布的虚拟节点,如遇master宕机时就不会涌入同一个节点
匀分布的虚拟节点,如遇master宕机时就不会涌入同一个节点
优点:自动缓存迁移、自动负载均衡
hash slot算法
redis cluster有固定的16384个哈希槽,对每个key计算CRC16的值,
然后对16384取模计算卡槽位置,每个卡槽位置可以存放多个key
然后对16384取模计算卡槽位置,每个卡槽位置可以存放多个key
CRC16算法
为什么是16384
即使有任何一台机器宕机,其他master中的缓存是不受影响的,
失效的节点重新分配就可以了
失效的节点重新分配就可以了
0 条评论
下一页