分布式基础概念-分布式缓存[2]

2023-11-21 09:21:04 浏览数 (1)

分布式缓存寻址算法

  • hash算法:

根据key进行hash函数运算、结果对分片数取模,确定分片适合固定分片数的场景。

扩展分片或者减少分片时,所有数据都需要重新计算分片、存储

  • 一致性hash:

将整个hash值得区间组织成一个闭合的圆环,计算每台服务器的hash值、映射到圆环中。使用相同的hash算法计算数据的hash值,映射到圆环,顺时针寻找,找到的第一个服务器就是数据存储的服务器。

新增及减少节点时只会影响节点到他逆时针最近的一个服务器之间的值

存在hash环倾斜的问题,即服务器分布不均匀,可以通过虚拟节点解决

  • hash slot:

将数据与服务器隔离开,数据与slot映射,slot与服务器映射,数据进行hash决定存放的slot

新增及删除节点时,将slot进行迁移即可

Redis的持久化机制

RDB

RDB:Redis DataBase将某一个时刻的内存快照(Snapshot),以二进制的方式写入磁盘。

手动触发:

  • save命令,使Redis处于阻塞状态,直到RDB持久化完成,才会响应其他客户端发来的命令,所以在生产环境一定要慎用
  • bgsave命令,fork出一个子进程执行持久化,主进程只在fork过程中有短暂的阻塞,子进程创建之后,主进程就可以响应客户端请求了

自动触发:

  • save m n:在m秒内,如果有n个键发生改变,则自动触发持久化,通过bgsave执行,如果设置多个、只要满足其一就会触发,配置文件有默认配置(可以注释掉)
  • flushall:用于清空redis所有的数据库,flushdb清空当前redis所在库数据(默认是0号数据库),会清空RDB文件,同时也会生成dump.rdb、内容为空
  • 主从同步:全量同步时会自动触发bgsave命令,生成rdb发送给从节点

优点:

  1. 整个Redis数据库将只包含一个文件dump.rdb,方便持久化。
  2. 容灾性好,方便备份。
  3. 性能最大化,fork子进程来完成写操作,让主进程继续处理命令,所以是IO最大化。使用单独子进程来进行持久化,主进程不会进行任何IO操作,保证了redis的高性能
  4. 相对于数据集大时,比AOF的启动效率更高。

缺点:

  1. 数据安全性低。RDB是间隔一段时间进行持久化,如果持久化之间redis发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候)
  2. 由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导 致整个服务器停止服务几百毫秒,甚至是1秒钟。会占用cpuAOFAOF:Append Only File以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录,调操作系统命令进程刷盘
  3. 所有的写命令会追加到AOF缓冲中。
  4. AOF缓冲区根据对应的策略向硬盘进行同步操作。
  5. 随着AOF文件越来越大,需要定期对AOF文件进行重写,达到压缩的目的。
  6. 当Redis重启时,可以加载AOF文件进行数据恢复。

同步策略:

  • 每秒同步:异步完成,效率非常高,一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失
  • 每修改同步:同步持久化,每次发生的数据变化都会被立即记录到磁盘中,最多丢一条
  • 不同步:由操作系统控制,可能丢失较多数据

优点:

  1. 数据安全
  2. 通过append模式写文件,即使中途服务器宕机也不会破坏已经存在的内容,可以通过redis-check-aof工具解决数据一致性问题。
  3. AOF机制的rewrite模式。定期对AOF文件进行重写,以达到压缩的目的

缺点:

  1. AOF文件比RDB文件大,且恢复速度慢。
  2. 数据集大的时候,比rdb启动效率低。
  3. 运行效率没有RDB高AOF文件比RDB更新频率高,优先使用AOF还原数据。

AOF比RDB更安全也更大

RDB性能比AOF好

如果两个都配了优先加载AOF

也可参考对线面试官系列文章:

https://mp.weixin.qq.com/s/SSYCYJKpTjsFvpwb0r4zqQ

Redis单线程为什么这么快

Redis基于Reactor模式开发了网络事件处理器、文件事件处理器file event handler。它是单线程的,所以Redis才叫做单线程的模型,它采用IO多路复用机制来同时监听多个Socket,根据Socket上的事件类型来选择对应的事件处理器来处理这个事件。可以实现高性能的网络通信模型,又可以跟内部其他单线程的模块进行对接,保证了Redis内部的线程模型的简单性。

文件事件处理器的结构包含4个部分:多个Socket、IO多路复用程序、文件事件分派器以及事件处理器(命令请求处理器、命令回复处理器、连接应答处理器等)。

多个Socket可能并发的产生不同的事件,IO多路复用程序会监听多个Socket,会将Socket放入一个队列中排队,每次从队列中有序、同步取出一个Socket给事件分派器,事件分派器把Socket给对应的事件处理器。

然后一个Socket的事件处理完之后,IO多路复用程序才会将队列中的下一个Socket给事件分派器。文

件事件分派器会根据每个Socket当前产生的事件,来选择对应的事件处理器来处理。

  1. Redis启动初始化时,将连接应答处理器跟AE_READABLE事件关联。
  2. 若一个客户端发起连接,会产生一个AE_READABLE事件,然后由连接应答处理器负责和客户端建立连接,创建客户端对应的socket,同时将这个socket的AE_READABLE事件和命令请求处理器关联,使得客户端可以向主服务器发送命令请求。
  3. 当客户端向Redis发请求时(不管读还是写请求),客户端socket都会产生一个AE_READABLE事件,触发命令请求处理器。处理器读取客户端的命令内容,然后传给相关程序执行。
  4. 当Redis服务器准备好给客户端的响应数据后,会将socket的AE_WRITABLE事件和命令回复处理器关联,当客户端准备好读取响应数据时,会在socket产生一个AE_WRITABLE事件,由对应命令回复处理器处理,即将准备好的响应数据写入socket,供客户端读取。
  5. 命令回复处理器全部写完到socket后,就会删除该socket的AE_WRITABLE事件和命令回复处理器的映射。

单线程快的原因:

  • 纯内存操作
  • 核心是基于非阻塞的IO多路复用机制
  • 单线程反而避免了多线程的频繁上下文切换带来的性能问题

也可参考对线面试官系列文章:

https://mp.weixin.qq.com/s/SSYCYJKpTjsFvpwb0r4zqQ

说一下你知道的redis高可用方案

主从

哨兵模式:

sentinel,哨兵是redis集群中非常重要的一个组件,主要有以下功能:

  • 集群监控:负责监控redis master和slave进程是否正常工作。
  • 消息通知:如果某个redis实例有故障,那么哨兵负责发送消息作为报警通知给管理员。
  • 故障转移:如果master node挂掉了,会自动转移到slave node上。
  • 配置中心:如果故障转移发生了,通知client客户端新的master地址。

哨兵用于实现redis集群的高可用,本身也是分布式的,作为一个哨兵集群去运行,互相协同工作。

  • 故障转移时,判断一个master node是否宕机了,需要大部分的哨兵都同意才行,涉及到了分布式选举
  • 即使部分哨兵节点挂掉了,哨兵集群还是能正常工作的
  • 哨兵通常需要3个实例,来保证自己的健壮性。
  • 哨兵 redis主从的部署架构,是不保证数据零丢失的,只能保证redis集群的高可用性。
  • 对于哨兵 redis主从这种复杂的部署架构,尽量在测试环境和生产环境,都进行充足的测试和演练。

Redis Cluster是一种服务端Sharding技术,3.0版本开始正式提供。采用slot(槽)的概念,一共分成16384个槽。将请求发送到任意节点,接收到请求的节点会将查询请求发送到正确的节点上执行

方案说明
  • 通过哈希的方式,将数据分片,每个节点均分存储一定哈希槽(哈希值)区间的数据,默认分配了16384个槽位
  • 每份数据分片会存储在多个互为主从的多节点上
  • 数据写入先写主节点,再同步到从节点(支持配置为阻塞同步)
  • 同一分片多个节点间的数据不保持强一致性
  • 读取数据时,当客户端操作的key没有分配在该节点上时,redis会返回转向指令,指向正确的节点
  • 扩容时需要需要把旧节点的数据迁移一部分到新节点

在redis cluster架构下,每个redis要放开两个端口号,比如一个是6379,另外一个就是加1w的端口号,比如16379。

16379端口号是用来进行节点间通信的,也就是cluster bus的通信,用来进行故障检测、配置更新、故障转移授权。cluster bus用了另外一种二进制的协议,gossip协议,用于节点间进行高效的数据交换,占用更少的网络带宽和处理时间。

优点

  • 无中心架构,支持动态扩容,对业务透明
  • 具备Sentinel的监控和自动Failover(故障转移)能力
  • 客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
  • 高性能,客户端直连redis服务,免去了proxy代理的损耗

缺点

  • 运维也很复杂,数据迁移需要人工干预
  • 只能使用0号数据库
  • 不支持批量操作(pipeline管道操作)
  • 分布式逻辑和存储模块耦合等

Redis Sharding是Redis Cluster出来之前,业界普遍使用的多Redis实例集群方法。其主要思想是采用哈希算法将Redis数据的key进行散列,通过hash函数,特定的key会映射到特定的Redis节点上。Javaredis客户端驱动jedis,支持Redis Sharding功能,即ShardedJedis以及结合缓存池的ShardedJedisPool

优点:

优势在于非常简单,服务端的Redis实例彼此独立,相互无关联,每个Redis实例像单服务器一样运行,非常容易线性扩展,系统的灵活性很强

缺点

由于sharding处理放到客户端,规模进一步扩大时给运维带来挑战。客户端sharding不支持动态增删节点。服务端Redis实例群拓扑结构有变化时,每个客户端都需要更新调整。连接不能共享,当应用规模增大时,资源浪费制约优化

也可参考对线面试官系列文章:

https://mp.weixin.qq.com/s/2HoOd_d6tLFWQi1BpopSyw

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

0 人点赞