线程模型
纯内存操作/非阻塞io多路复用/单线程避免多线程频繁上下文切换
基于Reactor模式开发了网络事件处理器:文件事件处理器,单线程的 io多路监听多个socket,据socket事件类型选择对应的处理器,高性能网络通信模型,可其他单线程对接 简单性
文件事件处理器:多个socket io多路复用 文件事件分派器 事件处理器
io多路复用监听多个socket,将socket放入队列排队,每次从队列中取出socket给事件分派器,给对应事件处理器,处理完,io多路复用将队列下一个socket给事件分派器
reactor
synchronous event demultiplexer:同步事件分离器,监听各种事件,调用方调用监听方法的时候会被阻塞 直到有事件发生
handler:文件描述符,简单理解一个一个事件
event handler:事件处理器,回调方法,事件发生 据handler调用对应的回调方法 自己实现方法
步骤:
高可用:
主从
哨兵:sentinel: 集群监控 消息通知 故障转移 配置中心
redis cluster :livu livechat中使用了
人家有槽slot 16384个呢 请求发送任意节点 该节点会将请求发送到正确节点上-相亲相爱
1.哈希的方式,将数据分片 每个节点均分存储一定哈希槽区间的数据
2.每份数据分片会存储在多个互为主从的多节点上
3.先写主节点再同步从节点
4.读取数据,当客户端操作的key没有分配在该节点,返回转向指令,指向正确节点
5.扩容时需要把旧节点的数据迁移一部分到新节点
6.每个redis放开两个端口,6379 16379,16379节点间通信,cluster bus,故障检测/转移
7.cluster bus用gossip二进制协议,节点间高效数据交换,占用更少的网络带宽和处理时间
优缺点:谁还能没点缺
无中心架构,支持动态扩容,对业务透明
自备sentinel监控和自动failover故障转移能力
高性能,直连redis服务 免去proxy损耗
有点缺:人无完人 redis无完美 怎么说:反正有缺点但是值得
运维复杂 数据迁移需要人工 只能使用0号数据库 不支持批量操作 分布式逻辑和存储模块耦合
redis sharding:你可以不看 让我自己卷
多redis实例集群,采用哈希算法将redis的key进行散列,映射到特定的redis节点
简单,服务端redis实例彼此独立,相互无关联,每个redis实例像单服务器一样 线性扩展
不支持动态删增节点,服务器redis实例群拓扑结构变化,每个客户更新调整 连接不共享
三大热门问题:
还行 咱家项目设计稳稳当当 上学的时候遇到过一次
缓存穿透:缓存 数据库都没有的数据,库短时间内承受大量请求
接口层校验,缓存取不到库中也没有,可key-null 短的过期时间,布隆过滤器bitmap中
缓存击穿:缓存中没有库中有,并发查同一条数据
热点永不过期,互斥锁
缓存雪崩:一瞬间大面积失效
设置随机过期时间/新增缓存标记是否失效/缓存预热/互斥锁
一致性:
写不太频繁:
1,操作缓存 设置过期标识 客户端读缓存过期则休眠再查redis
2,先删缓存,看他不顺眼直接删了!再写数据库,休眠 再删缓存
主从同步
1 从节点slaveof masterip port 保存主节点信息
2 从节点定时任务发现主节点,建立和主节点socket连接
3 从发送信号 主返回 互相私通 呸 互相私信,连接建立 主all数据发送给从
runid:每个redis节点启动生成唯一标识uuid
offset:主从各自维护自己的复制偏移量,主也写offset=offset+命令字节长度,从收到主发送命令后,增加自己的offset,把自己的offset发送给主节点,主节点同时保存自己的offset和从的,对比判断主从一致性数据
原理
repl_backlog_size:主节点上固定长度的先进先出队列1M
复制
全量复制:主节点bgsave命令fork子进程 rdb,消耗cpu 内存 硬盘id,主节点通网络rdb给从,从清空老数据 载入rdb(阻塞)
部分复制:执行复制的双方,分别维护offset,主内部维护固长 fifo复制积压缓存区队列,主offset差距大过缓存区长度,全量复制;服务器runid 主把自己的runid发送给从 从存 从重连时 据runid判断同步进度
runid同之前同步过 主尝试部分复制 ;不同全量复制
事务ACISD
单线程 watch监控key的情况
1,multi命令的执行(事务的开始),multi将客户端状态的flags=redis_multi
2,命令multi/exec/watch/discard会立即执行,否则将命令放入事务队列 客户端返回queue
其他命令 先检查格式 如果说来捣乱 服务器把客户端状态flags关闭redis_multi 返回错误 小黑屋了
队列说FIFO 先进先出讲规矩的队列
3,执行:
不支持回滚;
watch乐观锁为redis提供check-and-set(cas)监控多个键,有一个被修改则后面的事务不执行 监控持续到exec命令
multi开启事务,执行后客户端可持续向服务器发送任意多条命令,放入队列 exec被调 all命令执行
exec 执行事务块内命令,按命令执行先后顺序排列,操作被打断 返回空值null
调用discard客户端可清空事务队列,放弃执行事务
unwatch取消watch对所有key对监控
分布式锁
setnx+setex 设置超时时间失败,死锁
set(key,value,px)原子操作
redisson解决任务超时 锁自动释放 并发问题
数据结构
string
list
hash
set
sortedSet
bitmap
geohash:sortedSet
hyperLogLog
streams
缓存过期策略
定期过期:定时器清理 占大量CPU处理过期数据 缓存响应时间和吞吐量
惰性过期:先判断是否过期,过期删除,节省CPU资源 消耗内存
定期过期:每隔一段时间,扫描一定数量的数据库中expires字典中一定数量的key
淘汰算法
fifo:被存储时间 最远的先淘汰
LRU:最近最少使用,最近被使用的时间
LFU:最不经常使用,一段时间内 缓存被使用次数最少
缓存方案:
客户端缓存:页面 浏览器缓存 app h5 localStorage sessionStorage
CND缓存:内容存储 数据缓存 内容分发 负载均衡
nginx缓存:静态资源
服务端缓存:本地缓存 外部缓存
数据库缓存:持久层缓存 mybatis。hibernate多级缓存 mysql查询
操作系统缓存:page cache。 buffer cache
redis集群策略
主从:主可写读,和从数据同步,主从宕 客户端手动修改ip
哨兵模式:主库宕 哨兵从 从库选主 哨兵也可以集群 高可用 容量上的限制
cluster:多主多从 按key进行槽位分配 不同key分散不同主节点上
持久化
save命令,redis阻塞 直到rdb完成
bgsave,fork子进程 主进程在fork过程中短暂阻塞,子进程创建完主进程响应客户端请求
save m n:m秒内n隔键改变 自动触发持久化 bgsave进行 设置多个满足其一就触发
flushall:清空redis所有数据,flushdb清空当前redis所在库数据(0号库 rdb文件)
主动同步:全量同步自动触发bgsave命令
一个dump.rdb文件,方便持久化 容灾性好 方便备份 性能最大化 fork子进程完成写操作
数据安全性低,rdb间隔一段时间进行持久化,redis故障,数据丢失
aof:亲这边建议优先使用
日志形式记录服务器处理的每一个写 删除操作
aof缓存区据策略向硬盘同步操作,定期对aof文件重写 压缩的目的
每秒同步:异步完成 效率高,一秒数据会被丢失宕机时
每修改同步:同步持久化,每次发生数据变化 立即记录到磁盘 最多丢一条
不同步:操作系统控制 丢失更多数据
数据安全,redis-check-aof工具解决数据一致性问题
aof文件大 恢复慢 ;数据集大 rdb启动效率低,运行效率无rdb高