• Redis整理


    目录

    一. Redis使用

    1. 特性

    2.三大问题

    2. 缓存一致性

    a)缓存模式

    b)几种读写方案

    c)最佳方案

    3. Redis内存分配策略

    a)淘汰策略

    b)过期键的删除策略

    4. Redis持久化

    二. Redis高可用1. 集群模式

    a)Redis主从模式

    b)Redis Sentinel(哨兵模式)

    c)Redis Cluster

    2. Redis Cluster 核心概念

    a)哈希槽

    b)集群节点间通讯

    c)故障检测

    d)故障转移

    e)选举新的主节点

    f)集群节点宕机

    二. Redis底层实现

    1.5种数据类型

    2.Redis数据应用

    三. Redis应用

    1.订阅发布

    2.分布式锁

    3.RedLock


    一. Redis使用

    1. 特性

    • 性能:Redis能读的速度是110000次/s,写的速度是81000次/s ;
    • 基于内存;
    • 单线程实现:避免线程切换、锁资源争用;
    • IO多路复用模型。

    2.三大问题

    问题定义解决方案
    缓存穿透指查询一条数据库和缓存都没有的一条数据,就会一直查询数据库,对数据库的访问压力就会增大

    1、缓存空对象:使用空对象进行缓存,为空对象缓存增加失效时间;

    2、布隆过滤器:由一个很长的二进制向量和一系列随机映射函数构成的概率型数据结构;

    缓存击穿大并发查询单一条数据(热点数据),数据不存在或过期,对数据库瞬间高访问压力;查询数据库时加分布式锁锁;
    缓存雪崩缓存集中过期失效,对数据库瞬间高访问压力;设置不同的过期时间,防止同一时间内大量的key失效;

    2. 缓存一致性

    a)缓存模式

    • Cache-Aside Pattern:旁路缓存模式
      • 读操作的流程:查询的数据是否在缓存上;如果存在(Cache hit),从缓存上查询出数据,直接返回;如果不存在(Cache miss),则从数据库中检索数据,并存入缓存中,返回结果数据;
      • 写操作的流程:先更新数据库(增、删、改),然后直接删除缓存;
      • 缺点:会出现缓存和数据库双写不一致;
    • Read Through Cache Pattern:读穿透模式
      • 缓存服务自己来加载;
    • Write Through Cache Pattern:写穿透模式
      • 每次向缓存中写数据时,缓存会把数据持久化到对应的数据库中去,且这两个操作在一个事务中完成;
    • Write Behind Pattern:又叫Write Back,异步缓存写入模式
      • 会在一段时间之后(或是被其他方式触发)把数据一起写入数据库;

    b)几种读写方案

    方案问题问题出现概率推荐程度
    更新缓存 -> 更新数据为了保证数据准确性,数据必须以数据库更新结果为准,所以该方案绝不可行不推荐
    更新数据库 -> 更新缓存并发更新数据库场景下,会将脏数据刷到缓存并发写场景,概率一般写请求较多时会出现不一致问题,不推荐使用。
    删除缓存 -> 更新数据更新数据库之前,若有查询请求,会将脏数据刷到缓存并发读场景,概率较大读请求较多时会出现不一致问题,不推荐使用
    更新数据库 -> 删除缓存在更新数据库之前有查询请求,并且缓存失效了,会查询数据库,然后更新缓存。如果在查询数据库和更新缓存之间进行了数据库更新的操作,那么就会把脏数据刷到缓存并发读场景&读操作慢于写操作,概率最小读操作比写操作更慢的情况较少,相比于其他方式出错的概率小一些。勉强推荐。

    c)最佳方案

    延迟双删:采用更新前后双删除缓存策略

    • 先淘汰缓存(设置缓存过期时间
    • 再写数据库
    • 休眠1秒,再次淘汰缓存

    3. Redis内存分配策略

    a)淘汰策略

    • noeviction(默认策略):若是内存的大小达到阀值的时候,所有申请内存的指令都会报错。
    • allkeys-lru:所有key都是使用LRU算法进行淘汰。
    • volatile-lru:所有设置了过期时间的key使用LRU算法进行淘汰。
    • allkeys-random:所有的key使用随机淘汰的方式进行淘汰。
    • volatile-random:所有设置了过期时间的key使用随机淘汰的方式进行淘汰。
    • volatile-ttl:所有设置了过期时间的key根据过期时间进行淘汰,越早过期就越快被淘汰。

    b)过期键的删除策略

    • 被动删除。在访问key时,过期删除。
    • 主动删除。定时清理key20个过期key。
    • 内存不够时清理。内存超过了设置的最大内存,会按照配置的淘汰策略清理内存。

    4. Redis持久化

    • RDB持久化:将当前数据保存到硬盘(快照持久化)
    • AOF持久化:将每次执行的写命令保存到硬盘(类似于MySQL的Binlog)

    rdb适合大规模的数据恢复,由于rdb时异快照的形式持久化数据,恢复的数据快,在一定的时间备份一次,而aof的保证数据更加完整,损失的数据只在秒内。

    具体哪种更适合生产,在官方的建议中两种持久化机制同时开启,如果两种机制同时开启,优先使用aof持久化机制。

    二. Redis高可用
    1. 集群模式

    a)Redis主从模式

    主从模式采用一主多从,主数据库(master)可以读也可以写(read/write),从数据库仅读(only read)。但是,主从模式一般实现读写分离主数据库仅写(only write)

    工作机制如下:

    1. 当slave启动后会向master发送SYNC命令,master节后到从数据库的命令后通过bgsave保存快照(RDB持久化),并且期间的执行的些命令会被缓存起来。
    2. 然后master会将保存的快照发送给slave,并且继续缓存期间的写命令。
    3. slave收到主数据库发送过来的快照就会加载到自己的数据库中。
    4. 最后master讲缓存的命令同步给slave,slave收到命令后执行一遍,这样master与slave数据就保持一致了。

    主从模式问题:

    • 主从切换无法自动,需要手动切换;
    • 会导致读写的数据一致性问题,未完成从库同步时,读取从库造成数据一致性问题。

    b)Redis Sentinel(哨兵模式)

    Redis哨兵机制:

    • 哨兵节点定义:特殊的 Redis 服务,不提供读写服务
    • 哨兵节点监控:监控master和slave是否正常运行,以及哨兵之间也会相互监控
    • 自动故障恢复:当master出现故障的时候,会自动选举一个slave作为master顶上去。

    选举算法:

    • 判断主机下线:有 N/2+1 个实例判断主库“主观下线”,才判定主库为“客观下线”;
    • 选取新主库,通过Raft算法。

    哨兵模式问题:

    • 写瓶颈(单写节点);
    • master宕机恢复周期长(Raft选举时间);
    • 系统复杂(需要维护哨兵节点);

    c)Redis Cluster

    Redis-Cluster采用无中心结构,其结构特点: 1、每个节点都和其它节点通过互ping保持连接,每个节点保存整个集群的状态信息,可以通过连接任意节点读取或者写入数据(甚至是没有数据的空节点)。 2、节点的fail是通过集群中超过半数的节点检测失效时才生效。 3、Redis集群预分好16384个槽,当需要在 Redis 集群中放置一个 key-value 时,根据公式HASH_SLOT=CRC16(key) mod 16384的值,决定将一个key放到哪个槽中。
     

    2. Redis Cluster 核心概念

    a)哈希槽

    Redis集群通过分片的方式来保存数据库中的键值对,集群的整个数据库被分为16384个槽( slot ),数据库中的每个键都属于这16384个槽的其中的一个,集群中的每个节点可以处理0个或最多16384个槽。当数据库中的16384个槽都有节点在处理时,集群处于上线状态( ok);相反地,如果数据库中有任何一个槽没有得到处理,那么集群处于下线状态( fail )。

    当你往Redis Cluster中加入一个Key时,会根据crc16(key) mod 16384计算这个key应该分布到哪个hash slot中,一个hash slot中会有很多key和value。你可以理解成表的分区,使用单节点时的redis时只有一个表,所有的key都放在这个表里;改用Redis Cluster以后会自动为你生成16384个分区表,你insert数据时会根据上面的简单算法来决定你的key应该存在哪个分区关系:cluster>node>slot>key。

    b)集群节点间通讯

    1、所有集群节点都使用 TCP 总线和二进制协议连接,称为Redis 集群总线。每个节点都使用集群总线连接到集群中的每个其他节点。

    2、节点之间采用Gossip协议进行通信,Gossip协议就是指节点彼此之间不断通信交换信息

    当主从角色变化或新增节点,彼此通过ping/pong进行通信知道全部节点的最新状态并达到集群同步

    c)故障检测

    Redis Cluster 故障检测用于识别何时大多数节点不再可以访问主节点或副本节点,然后通过将副本提升为主节点来做出响应。当无法进行副本提升时,集群将处于错误状态以停止接收来自客户端的查询。

    d)故障转移

    当一个从节点发现自己正在复制的主节点进入了已下线状态时,从节点将开始对下线主节点进行故障转移,以下是故障转移的步骤:

    1. 复制下线主节点的所有从节点里面,会有一个从节点被选中。
    2. 被选中的从节点会执行 SLAVEOF no one命令,成为新的主节点。
    3. 新的主节点会撤销所有对已下线主节点的槽指派,并将这些槽全部指派给自己。
    4. 新的主节点向集群广播一条PONG消息,这条PONG消息可以让集群中的其他节点立即知道这个节点已经由从节点变成了主节点,并且这个主节点已经接管了原本由已下线节点负责处理的槽。
    5. 新的节点开始接收和自己负责处理的槽有关的命令请求,故障转移完成。

    e)选举新的主节点

    当满足以下条件时,副本开始选举:

    • 副本的主节点处于FAIL状态。
    • 主服务器正在服务非零数量的插槽。
    • 副本复制链接与主节点断开连接的时间不超过给定的时间
    • 副本通过FAILOVER_AUTH_REQUEST向集群的每个主节点广播数据包来请求投票。然后它等待最多两倍NODE_TIMEOUT于回复到达的时间(但总是至少 2 秒)。
    • 一旦 master 为给定的副本投票,并以 肯定答复FAILOVER_AUTH_ACK,一段时间NODE_TIMEOUT * 2就不能再为同一 master 的另一个副本投票。在此期间,它将无法回复同一主站的其他授权请求。

    f)集群节点宕机

    • 集群是如何判断是否有某个节点挂掉
      • 首先要说的是,每一个节点都存有这个集群所有主节点以及从节点的信息。它们之间通过互相的ping-pong判断是否节点可以连接上。如果有一半以上的节点去ping一个节点的时候没有回应,集群就认为这个节点宕机了,然后去连接它的备用节点。
    • 集群进入fail状态的必要条件
      • 当数据库中的16384个槽都有节点在处理时,集群处于在线状态(ok),相反的,如果数据库中有任何一个槽没有得到处理,那么集群处于下线状态(fail)。

    二. Redis底层实现

    1.5种数据类型

    • String(字符串):动态字符串;
    • Hash(和字典):压缩列表(字典中每个 entry 的 key/value 都小于 64 字节;元素个数小于 512 个),hash 表;
    • Set(集合):有序整数数组(集合中元素都是整数类型;元素个数不超过 512 个)、hash 表;
    • List(列表):压缩列表(列表中单个元素小于 64 字节;元素个数少于 512)、双向链表;
    • SortedSet(有序集合):有序整数数组(集合中元素都小于 64 字节;元素个数小于 128 个)、跳表;

    2.Redis数据应用

    • String(字符串):
      • 说明:最常用的一种数据类型,String类型的值可以是字符串、数字或者二进制,但值最大不能超过512MB。
      • 结构:Key-Value
      • 实战场景:缓存、计数器、session
    • List(列表):
      • 说明:有序可重复的集合,底层是依赖双向链表实现的。
      • 结构:Key-Index-Value
      • 实战场景:TimeLine(lpush加入时间轴)、消息队列
    • Set(集合):
      • 说明:无序去重的集合。Set 提供了交集、并集等方法,对于实现共同好友、共同关注等功能特别方便。添加,删除,查找的复杂度都是 O(1)
      • 结构:Key-Value
      •  实战场景:标签(tag)、点赞,或点踩,收藏
    • Hash(和字典):
      • 说明:Hash 是一个键值对集合。
      • 结构:Key-Field-Value
      • 实战场景:缓存
    • SortedSet(有序集合):
      • 说明:有序Set。内部维护了一个score的参数来实现。适用于排行榜和带权重的消息队列等场景。
      • 结构:Key-Score-Value
      • 实战场景:排行榜

    特殊的数据类型:

    • Hyperloglog(基数统计):
      • 说明:HyperLogLog 是用来做基数统计的算法,其优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。典型的使用场景是统计独立访客。
      • 实战场景:注册 IP 数、每日访问 IP 数的页面实时UV、在线用户数,共同好友数
    • Bitmap(位存储):
      • 说明:位图,可以认为是一个以位为单位数组,数组中的每个单元只能存0或者1,数组的下标在 Bitmap 中叫做偏移量。Bitmap的长度与集合中元素个数无关,而是与基数的上限有关。
      • 实战场景:统计用户信息,活跃,不活跃! 登录,未登录! 打卡,不打卡
    • Geospatial  (地理位置):
      • 说明:主要用于存储地理位置信息,并对存储的信息进行操作,适用场景如定位、附近的人等。

    三. Redis应用

    1.订阅发布

    Redis发布与发布功能(Pub/Sub)是基于事件座位基本的通信机制,是目前应用比较普遍的通信模型,它的目的主要是解除消息的发布者与订阅者之间的耦合关系

    2.分布式锁

    • 使用setIfAbsent()
    • 开源框架Redisson

    3.RedLock

    算法流程,开启五个节点,为了索取锁,client进行的操作

    1. 获取当前时间精确到毫秒
    2. client尝试使用相同的key,value获取所有redis服务的锁,在获取锁的过程中获取时间比锁过期时间要短的多,避免长时间去等待一个已经关闭的redis服务,并试着去获取下一个实例
    3. client通过获取所有能获取的锁的时间后减去第一步时间,这个时间差要小于TTL时间和至少三个redis实例成功获取锁,才能算真正的获取锁成功
    4. 如果成功获取锁,那么锁的有效时间是TTL减去第三步的时间差的时间
    5. 如果获取锁失败,那么将开始解锁所有redis实例,因为已经获取了小于3个锁,必须要释放防止影响其他client获取锁

  • 相关阅读:
    队列的实现
    linux 给根目录扩容(lvm CentOS 7.6 &kylinx86)
    Kafka知识补充
    MMrotate_dev 1.x训练自己的数据集
    双非本计算机从零开始三年努力能做到什么程度【学习路线回顾&总结&问答】
    什么是网络编程?
    python+vue+elementui电影个性化推荐系统django协同过滤算法
    dotNet8 全局异常处理
    C语言-判断上三角矩阵
    Sora--首个大型视频生成模型
  • 原文地址:https://blog.csdn.net/jingmiaowill/article/details/126400259