redis13123124

  • aof,一次复制,两个日志,aof日志缓冲,aof重写日志缓冲。重写进程重写完全部数据后,会把期间的新操作也记录

  • rdb,aof故障恢复时,需要逐行执行命令,比较缓慢。就与有了rdb内存快照,两个命令save和bgsave。通过cow写时复制,如果子进程写rdb期间主进程更改了键值对,会拷贝一份副本给子进程

  • 惰性更新(查询时再查看过期字典,过期则删除,节约cpu资源,浪费空间)、定期检查(从过期字典中抽查20个,若过期数量大于5(1/4),再次抽查)

  • 持久化过程中对过期值的处理策略
    rdb:生成阶段:已过期的键不会被写入rdb
    加载阶段:主,会进行过期检查,删除过期键
    从:不会处理过期键,因为和主同步时会全量更新
    aof:
    生成阶段:若为key未过期,会写入aof中,若过期了,会追加一条del命令
    aof重写阶段:
    会进行过期检查,已过期的key不会被写入aof中

  • 从服务器不会主动检测过期key,只被动的等待主服务器删除后会同步一条del指令

  • 延迟队列,zset
    ZADD delayQueue 1650000010 “task1”
    ZRANGEBYSCORE delayQueue -inf 1650000010
    ZREM delayQueue “task1”

  • 大Key问题
    会导致网络阻塞(结果传输内容过多)、客户端响应时间变长(操作大key比较耗时,redis 单线程回到值客户端响应变慢)、数据分配不均匀(大Key所在slot占比过大)、del操作会阻塞工作线程
    解决:
    redis-cli --bigkey(无法展示排名)
    删除问题
    除了释放内存外,需要维护空闲链表维护空闲内存块的关系,用于后续内存的分配
    怎么删
    分批删:对于list使用ltrim;对于hash,使用hscan(每次100)后通过hdel每次删一个键;对于打语音set,使用sscan,使用srem删;对于zset,使用zremrangebyrank删除topn
    异步删:redis4.0后,使用unlink代替del异步删除

  • 分布式锁
    setnx
    几个注意点:设置过期时间,避免客户端故障导致一直持有不释放。设定客户端唯一的标识,避免其他客户端误释放。
    问题:过期时间不好定(可以设置守护线程续期,但实现复杂);主节点挂了,还没有同步其他节点,选取新主之后回导致再次回去到锁

  • 底层数据结构

  1. string int(整数)和sds(字符串、非整数)
    单线程适合统计累计值,访问量点赞等 && 存session
  2. list 小于512字节,每个元素都小于64字节,是压缩列表;否则双向链表
    list实现消息队列
    要实现消息队列,要满足三个基本条件:消息保序、消息可靠性保证、避免重复消费
    消息保序,redis的list结构天然支持,有个问题:消费值需要一直循环rpop,占用资源,可以用brpop解决,等到list中有值时再pop
    避免重复消费要满足两点:生成全局唯一的id;消费者需要保存消费过的id;前者需要写入消息将唯一id写入value
    消息的可靠性,当一条消息从list取出后,就删除了,如果消费者故障会导致消息丢失。redis提供brpoplpush队列,取出的消息会存入备用队列。如果消费者故障,可以从备用队列中取出
    缺点:无法实现一条消息被多消费者消费,后来的stream支持
  3. hash:512,64以下压缩列表,否则hash。
    hash和string怎么选,如果属性变更频繁用hash,一般用string
    场景:购物车 && 缓存对象
  4. set:512 整数数组,否则hash
    Set 的差集、并集和交集的计算复杂度较高,在数据量较大的情况下,如果直接执行这些计算,会导致 Redis 实例阻塞。
    在主从集群中,为了避免主库因为 Set 做聚合计算(交集、差集、并集)时导致主库被阻塞,我们可以选择一个从库完成聚合统计,或者把数据返回给客户端,由客户端来完成聚合统计。
  5. zset
    小于128,64使用压缩列表,否则使用跳表
  6. bitmap
    首次签到:BITPOS uid:sign💯202206 1
    签到次数:bitcount uid:sign💯202206
    GETBIT、SETBIT
    统计连续x天签到人数:将日期设置为key,userid设置为offset,对多个bitmap与运算。结果落到一个bitmap,统计1的个数
  • 与操作
    BITOP AND destmap bitmap:01 bitmap:02 bitmap:03
  • 统计 bit 位 = 1 的个数
    BITCOUNT destmap
  1. HyperLogLog
    提供不精确的去重计数。
    百万级网页 UV 计数(0.81%)
  2. GEO
  3. Stream
    专门为消息队列设计的数据结构,XADD时会自动生成唯一id,通过pending list实现消息可靠,有ack机制,保证消费者消费的消息不丢失。支持消费者组消费
    **缺点:**消息丢失,消息堆积支持差(最终还是会导致消息丢失)
    消息丢失原因分析:
    消息队列分为三大部分
  4. 生产者发送消息给消息队列,没收到ack则重发,不存在消息丢失
  5. 消费者消费消息时,即使重启异常,可以查询消息队列的pending list,找到还未ack的消息执行,也不存在丢失
  6. 对于消息中间件本身:aof是每秒刷盘(有间隔),这个间隔时故障回导致消息丢失。主从同步是异步的,发生主从切换也会导致消息丢失
  7. 对于消息堆积,redis基于内存,若允许无限堆积会导致oom,所以redis设置了最大队列长度,超出则会丢弃部分数据也会导致消息丢失
    **总结:**像kafka等MQ中间件有多个节点(副本),保证消息可靠性,持久化也是落到磁盘,支持大量消息堆积
    如果场景简单,不存再大量消息堆积,且允许消息丢失,可使用redis作为消息中间件,否则用专业MQ
  • 发布订阅模式做消息队列(只适合用在及时通讯场景)
    不支持持久化,不依赖任何数据结构
    消费者重启后无法再次消费,不可靠
    消息挤压到达一定阈值,消费者会被强制断开
  • 过期策略和内存淘汰策略
    过期策略:(过期字典)惰性删除 + 定期清理
    内存淘汰策略:当内存达到配置最大值时,触发内存淘汰策略
    8种策略:不淘汰-直接报错;淘汰,在过期字典里选和在全量数据中选:random,lru,lfu

lru:传统了lru的实现使用链表结构,每次访问数据时将数据移到队列尾部,淘汰是删除头元素。但是当大量访问时需要频繁操作链表,影响性能。redis采用简易实现模式,通过一个字段标识最近访问时间,随机选择5个数淘汰掉最近访问时间最久远的。
但是会造成内存污染,若一次读取大量数据,只会访问一次。会导致持续占用内存

lfu:最近访问频率淘汰

  • 主从复制
    首次同步分三步:psync,Fullresync;主生成RDB,生成、传输、从加载期间的命令存入replicate buffer;缓存中的内容同步给从。

  • 增量同步
    通过repl_backlog_buffer、replication offset实现增量同步

repl backlog buffer 是在增量复制阶段出现,一个主节点只分配一个 repl backlog buffer;
replication buffer 是在全量复制阶段和增量复制阶段都会出现,主节点会给每个新连接的从节点,分配一个 replication buffer;

  • 主从复制数据丢失
    主节点还未同步从时断电,会丢失一部分数据。可以配置从节点最大响应时间,比如10s,一旦大于这个时间,redis返回客户端不可用。
    做降级处理,先写入mq或本地缓存,等恢复后尝试恢复
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值