Redis

Redis

数据类型

  • String:最大512M,内容过大可以存入MonoDB或CDN缓存。序列化操作。
    • 应用:缓存,计数器
  • Hash,单个value过大可以拆分,使用multiGet获取。可以部分更新。
    • 应用:代替String,优化存储。对象的各种属性不设置单独的key,而是存储到散列表中。
  • set:集合
    • 去重
  • zset:有序的集合,跳表,时间复杂度O(logN)
    • 排行榜
  • List:队列
    • 社区应用
  • HyperLogLog:基数统计,比如UV统计。
  • Geo:存储地理位置信息。

常见命令

  • keys:查询指定模式的key列表(会阻塞线程)
  • scan:无阻塞,在客户端去重,整体花费的时间较长
  • setnx:设置
  • experie:设置过期时间(秒)
  • persist:永久有效

高可用

  • 哨兵:监控:检查主服务器是否运行正常;提醒:发送故障通知;自动故障迁移:主从切换。脑裂:配置从机数量与延迟时间。
  • 集群:数据分散存储。
  • 一致性Hash算法(沿着hash环顺时针定位到服务器)解决节点的动态增减导致数据缓存大量减少问题虚拟节点解决数据倾斜问题
  • hash槽:redis cluster集群中,key通过CRC16校验对16384(集群的最大节点个数)取模来决定放置在哪个槽。master节点写入数据,slave节点同步数据。master节点挂掉,slave节点会通过选举机制选出新的master节点。

持久化策略

  • RDB持久化:保存某个时间点的全量数据快照。

    • 优点:fork子进程完成写操作,主进程继续处理命令,保证了redis的高性能。
    • 缺点:安全性低,持久化期间redis故障数据会丢失。
  • AOF持久化:保存除了查询以外更新数据库状态的指令。

    • 优点:

      • 数据安全,AOF持久化配置appendfsync为always,每进行一次命令操作就记录到AOF文件中一次。
      • 通过append写文件,中途服务器宕机,也可以通过redis-check-aof工具解决数据一致性问题。
      • AOF的rewrite模式。AOF没有被rewrite之前,可以删除其中的某些指令。
  • 缺点:

    • 文件大,恢复慢,数据集较大时启动效率低。

同步策略

  • 主从同步:初始化阶段全量同步,初始化之后增量同步(可以随时发起全量同步);
  • 快照同步:将内存数据映射到硬盘,恢复较快。

过期策略

  • 定时删除:创建定时器
  • 惰性删除:获取键时检查键是否过期,过期则删除。
  • 定期删除:每隔一段时间定期检查,删除过期键。

淘汰机制

  • volatile-lru:从已设置过期时间的数据集中淘汰最近最少使用的数据。
  • volatile-ttl:从已设置过期时间的数据集中淘汰即将过期的数据。
  • volatile-random:从已经设置过期时间的数据集中随机淘汰数据。
  • allkeys-lru:从数据集中选择最近最少使用的数据淘汰。
  • allkeys-random:从数据集中随机淘汰数据。
  • no-enviction:禁止驱逐数据,永不回收。
  • 使用策略的规则:
    • 如果数据呈现幂律分布(部分数据访问频率高),使用allkeys-lru
    • 如果数据呈现平等分布,使用allkeys-random

PipeLine的好处

  • 如果pipeline执行的指令之间没有因果相关性,可以将多次IO往返的时间缩短为1次。

多路IO复用

  • 基于react设计模式监听IO事件。

Redis是单线程还是多线程的

  • 文件事件处理器=多个套接字+IO复用程序+文件事件分派器(单线程)+事件处理器
  • Redis的瓶颈不在CPU,而在于内存和网络,通过搭建多个Redis实例解决。
  • Redis 6.0在网络IO的处理方面上了多线程,核心的模块还是单线程的。

Redis为什么快

  • 完全基于内存,查找数据的时间复杂度是O(1)
  • 数据结构简单
  • 单线程,避免线程上下文切换,锁的竞争,死锁
  • 多路复用IO,非阻塞IO

保证缓存与数据库双写的一致性

  • Cache aside pattern::先读缓存,再读数据库,更新缓存;:先更新数据库,再删除缓存。
  • 最初的缓存不一致问题:更新数据库,删除缓存(存在一致性问题)-->删除缓存,更新数据库(容易产生脏数据)。
  • 高并发场景:一个队列对应一个工作线程,每个工作线程串行拿到对应的操作,然后一条一条的执行;完成数据库的修改之后更新缓存。
  • 优化:可过滤多个在一起的缓存更新操作;读操作等待时间过长,直接从数据库读取旧的值。

缓存穿透、缓存击穿、缓存雪崩

  • 缓存穿透:缓存和数据库中都没有的数据;解决方案:key与空值放入,设置较短的失效时间。布隆过滤器,多个无偏Hash函数得到位置。
  • 缓存雪崩:缓存服务挂掉;解决方案:服务限流降级,多级缓存,预热。
  • 缓存击穿:缓存中没有,数据库中有;解决方案:分布式锁,key不存在时进行set操作。

Redis做异步队列

  • list结构作为队列,lpush生产消息,rpop消费消息。
  • blpop,没有消息时阻塞直到消息到来。
  • pub/sub主题订阅模式,通过subscribe和publish实现1:N的消息队列。消费者下线时,生产的消息会丢失,可以使用专业的消息队列。
  • 实现延时队列:使用zset,时间戳作为score,消息内容作为key,zrangebyscore轮询时间戳在某个区间内的数据。

Redis做分布式锁

  • setnx抢锁,抢锁之后expire给锁加过期时间防止锁忘记释放。
  • 两者之间进程crash:通过setnx设置分布式锁时可以增加过期时间。
posted @ 2020-08-02 09:34  樱空废宅  阅读(144)  评论(0)    收藏  举报