redis基础
优点:存取速度快(内存存储)
缺点:主从、扩容
单线程处理I/O和读写 多路复用器处理并发请求 不能大于redis的最大连接数(config get maxclients)(一般用连接池解决)
常用命令
info Server Client Memory Persistence Stats Relication CPU Cluster KeySpace
1.redis数据结构
key为String
value有 String List set sortedSet Hash
scan渐进式获取大量key 相当于分页查询
2.redis存储
过时淘汰机制
实时淘汰 监控key,到期后立即删除 占用cpu
使用检查淘汰 有使用到key时,检查是否过期,过期再删除 内存中大量过期未删除key
定时批量淘汰 定时去检查一批key的过期时间,过期的批量删除
空间不足淘汰机制
最不常使用 LRU
最老淘汰 LFU
随机
在有过期时间的key中
2.1 redis持久化
rdb
每过一段时间将内存数据保存一个快照dump.rdb ,持久化到磁盘 优点:数据少、恢复快 缺点:持久化过程中宕机造成数据不一致
save 60 1000
bgsave cow写时复制 主线程fork子线程
aof
append-only file 将所有写操作写到一个文件里,数据从文件中恢复 优点:数据一致 缺点:文件大,恢复慢 默认持久化方式
appendonly yes
appendfsync always/everysec/no
auto-aof-rewrite-min-size 64M 文件超过64M重写
auto-aof-rewrite-percentage 100 文件超过100%重写
bgrewriteaof fork子线程重写
混合持久化
aof-use-rdb-preamble yes
3.redis事务
ACID 只能保证CI
命令错误,所有命令不执行;运行错误,正确命令会被执行
A 非原子性 中断正在执行的,已经执行的回滚不了?不支持回滚?
D AOF可以保证持久化
lua脚本实现事务原子性 死循环
4.redis集群
redis线程机制
文件事件处理器 组成构造为:socket I/O多路复用 文件分派器 事件处理器
redis主从机制
主从数据同步
slave连接到master后,发送PSYNC命令,master会fork子线程去生成rdb,slave会先保存再加载到内存;之后master同步增量命令操作,slave进行同步
断点续传
slave和master保存offset和master线程id,slave重新连接后,从offset开始增量同步,而不需要rdb全量同步,如果线程id已改,需要全量重新同步
主从复制风暴:解决办法是让slave从salve复制
读写分离
slave发送sync请求到master,第一次会全量生成快照,并将在持久化过程的写操作一并发给slave,之后接收到写命令,就同步一次
哨兵集群
sentinel
配置哨兵节点 先绑定redis主节点 超过一半哨兵认为主节点挂了会重新选举主节点,并在配置中切换主节点配置
每个哨兵节点元数据保存有所有redis主从节点信息和所有哨兵节点信息
客户端监听主节点变化?
客户端从哨兵获得主从节点信息后,会直接调用主从节点,不需要再经过哨兵
redis cluster
最少三个主节点master
cluster命令
cluster nodes create/add-node/del-node/reshard/check/call
reshard重新分片 将一部分hash槽分配给新的集群节点 总共16384个slot
数据槽定位:对key计算CRC16再取余
replicate 新增从节点
删除前需要转移hash槽,防止数据丢失
默认开启16379端口 进行gossip(节点间)通信
分布式寻址算法
hash
一致性hash
hash slot
水平扩展
服务器通过分配hash槽来实现数据的分片存储 多主多从
redis sharding
基于客户端的redis分片
代理服务器分片
redis分区
redis扩容
5.nosql比较
redis和mogodb
redis和memcached
二、redis应用
1.分布式锁
setnx
缓存和数据库双写的数据一致性
先更新数据库,再删除缓存
双删缓存(另开线程) 缓存删除重试
队列
读取binlog删除
读写锁保证写的原子,读的高并发
2.缓存设计
缓存穿透:缓存空值/布隆过滤器
缓存击穿:过期时间随机/热点数据永不过期
缓存雪崩:缓存层不可用(高并发场景下) 缓存高可用/后端限流熔断降级/提前演练
热点key重建优化:加锁单线程创建
开发规范
bigkey
String最大512M 不可大于10k
集合数据不可超过5000个
bigkey 增、查、删造成redis和客户端阻塞
连接池设置
qps和redis性能
maxTotal = maxIdle(理论需要) * 2
如何实现动态扩容 1.缓存:一致性hash 2.持久化:节点数量变化需要使用其他工具和redis集群模式
定期过期删除策略:设定每过一段时间在限定时间内循环,每次扫描特定数量的key;总共有6中策略选择
内存空间不足的key删除策略:所有keys上随机/lru/lfu 过期keys上随机/lru/lfu/最早过期
多使用散列表 从数据结构上分析?
redis事务:MULTI WATCH EXEC DISACRD UNWATCH 保证一致性,多个线程不能同时修改同一个数据;可用lua命令实现 运行错误不影响其他命令执行 或者中间变量标记
redis数据分片 数据分片后,每个分片有主从节点 redis cluster是服务端数据分片
基于客户端分片/基于中间代理服务做数据分片查改 预分片?
redis和memcached 除了字符串/二进制数据类型 持久化 事务 数据分片 内存使用率 多线程
不要使用keys,使用scan命令
zadd 时间戳为score实现延时队列
基础与拓展
基于内存的高速访问的缓存NoSql
同memeberCache的比较:数据类型、多线程、事务、
基础
redis特性和行为
数据类型/持久化/事务/LUA/集群/规范/应用
数据类型
String、List、Set、SortedSet、Hash
持久化
RDB/AOF
事务
CI(ACID)
watch/unwatch exec
LUA
ACID
线程模型
文件事件处理器
监听多个socket I/O多路复用 事件分发器 事件处理器
客户端操作生成文件事件并绑定具体的事件处理器
事件放入队列中,通过分发器分发给事件处理器处理
事件处理器
连接应答处理器 命令请求处理器 命令回复处理器
ACC_REDABLE 首先绑定连接应答处理器,连接成功后重新绑定到命令请求处理器
服务器处理完后生成ACC_WRITABLE命令,绑定命令回复处理器,传回客户端后删除命令和命令回复处理器绑定
单线程
单线程没有线程上下文切换 单线程多路复用程序只负责非阻塞监听socket,由事件处理器处理命令 内存执行
拓展
底层数据结构
集群
主从
哨兵
只有一个master提供服务,主备切换存在服务不可用问题,哨兵检测主节点宕机进行主备切换(瞬断) 性能 高可用
sentinel 哨兵leader进行故障转移
Redis Cluter
最少3个主节点 奇数个几点 槽位存储在客户端
动态?扩缩容 手动重新分配hash槽
reshard 手动重新分配 添加主节点:从哪些主节点分出hash,指定该节点分配多少个hash 删除主节点:指定全部hash迁移到哪个主节点上
从节点同步主节点,不需要指定hash槽
hash槽 16384
gossip 端口+10000 元数据交换 meet新节点 ping其他节点 是否健康 pong回复meet和ping fail
主节点宕机 等fail通知到集群后重新选举 从节点failover获取一半主节点ack后选为主节点
网络抖动 设置timout 防止频繁主备切换
脑裂数据丢失 无过半机制
应用
分布式锁
数据一致性问题
双写/读写
适合读多写少
先删redis再写库/双删/队列/canal同步
穿透
空值
布隆过滤器:
击穿
热点key 多个key
雪崩
多个应用同时 大批量缓存
缓存层失效 导致服务大量不可用
熔断 降级 hydrix和sentinel
redis队列使用
list: brpop rpopbpush两个队列保证数据一致性(推到新队列,处理完再删除) 无法广播,只能消费一次
set保证数据唯一 mq一个消息一个队列只有一个消费者? 多个消费者(ip) 一个队列
重推 而不需要mq堆积 推/拉 消息消费ack 高吞吐
流式处理
pubsub:channel 通配符消费(psubscribe) 订阅特殊队列消费keys或events(client命令) 不持久化(重启数据丢失),由redis服务器瞬时推送给消费者 背压机制? 不能削峰填谷、消息丢失(宕机或客户端消费能力(client buf堆积)不足)
stream:consumerGroup内一个消费者消费 维护一个last_deliver_id标识消费位点 广播给所有消费者 消息持久化(存在消息丢失 aof 每条语句立即fsync 以及主备切换数据不一致 备库半同步) 客户端拉取 空闲超时阻塞
消息至少被消费一次 消费端ack pengding状态可继续消费(或由同组其他消费) 消息投递一次(指定一个message_id 可由发送端自定义)
tair持久内存stream:
AEP存储 解决aof
半同步 主备切换
消费者组内 messageQueue有序 rocketMq
使用规范
不同业务使用不同redis实例
超大key 512M 10K 集合元素数量不超过5000个
bigKey识别 Strlen、scard等命令 redis-cli客户端 bigKeys、hotKeys等命令 tair客户端
bigKey拆分 hmget不用一次性全取出
大批量数据scan分批获取,分批处理
mget 批量取数
热点key 重建加互斥锁
设置最大内存 防止内存不足从磁盘随机读 lru淘汰
连接池 maxTotal=2*maxIndle minIndle 连接池预热 redis key预热
实践
数据高可用
redis不可用客户端降级保证可用 对应mysql主从数据分别存取
bloom filter优化
串长度、单位可变 适配热点及大数据量key