Redis(数据类型/事务/持久化/集群)
2021-02-06 15:46:06 25 举报
AI智能生成
登录查看完整内容
Redis
作者其他创作
大纲/内容
Redis
数据类型
基本类型
String:基本的字符串类型,set、get
可做简单的key-value缓存
实现计数器
List:有序列表,异步解耦
实现高性能分页
实现消息队列:例如到货通知、邮件发送
Set:无序集合,自动去重
利用交集查看共同粉丝列表
ZSet:有序集合,自动去重
写数据带分数,实现排行榜
Hash:Map集合
特别适合存储对象,可单独修改对象中的字段
特殊类型
Pipeline(管道)
管道就是打包多条无关命令批量执行,以减少多个命令分别执行消耗的网络交互时间(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 文件进行重写,达到压缩的目的
需手动开启: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单点故障
主从+哨兵缺点:节点数据冗余
动态扩容和缩容,保证数据不冗余,且吞吐量更大
自动数据分片,每个master节点存放一部分数据
提供内置的高可用支持,允许部分master节点宕机
数据分片方案
客户端
客户端使用一致性哈希等算法决定键应当分布到哪个节点
中间层
将客户端请求发送到代理上,由代理转发请求到正确的节点上
国内豌豆荚的Codis
国外Twiter的twemproxy
服务器
hash slot 算法
Redis Cluster
元数据维护
集中式
将元数据(节点信息、故障)存储在某个节点上
优点:时效性好,同步快
缺点:更新压力和存储压力集中
gossip协议
去中心化
每个节点都持有一份元数据
优点:缓解了元数据更新和存储的压力
缺点:元数据更新延迟,集群操作滞后
通信机制
Meet:集群中的节点会向新的节点发送邀请,加入现有集群
Ping:节点向集群中的其他节点发送ping消息传递自己的节点信息
Pong:收到ping消息的节点会回复pong,消息中同样携带节点信息
Fail:ping不通某节点会向集群中的其他节点广播该节点挂掉的消息
redis cluster基于gossip协议的故障检测
节点间内部通信
采用gossip协议,每个节点都有一个专门用于节点间通信的端口,就是自己提供服务的端口号+10000
集群中的每个节点都会定期地向集群中的其他节点发送PING消息,以此交换各个节点状态信息,检测各个节点状态
高性能的主备切换
判断master宕机
PFAIL->超半数->FAIL
从节点过滤
过滤掉与master断开时间长的slave
master选举
slave发现自己的master的状态变为FAIL
将自己记录的选举轮次标记加1,并广播通知给集群中其他节点
其他节点收到该信息,只有master响应,判断请求者的合法性,并发送结果
尝试选举的slave收集master返回的结果,收到超过半数master的统一后变成新Master
广播Pong消息通知其他集群节点
分布式寻址算法
hash算法
计算请求数据的hash值,并按照节点数量取模,再放入对应的master节点中,如果某台master宕机了,由于master数量少了导致取模方式改变
缺点:会造成大量缓存重建
一致性hash算法+虚拟节点
把请求数据的hash值对应在圆环的各个点上,然后顺时针寻找离自己最近的master节点,如遇master宕机只会影响部分数据
基于上面的一致性hash算法,再在各个master节点之间创建均匀分布的虚拟节点,如遇master宕机时就不会涌入同一个节点
优点:自动缓存迁移、自动负载均衡
hash slot算法
redis cluster有固定的16384个哈希槽,对每个key计算CRC16的值,然后对16384取模计算卡槽位置,每个卡槽位置可以存放多个key
CRC16算法
为什么是16384
即使有任何一台机器宕机,其他master中的缓存是不受影响的,失效的节点重新分配就可以了
0 条评论
回复 删除
下一页