单点Redis所面临的问题及解决方法

1.数据丢失问题

大家可以设想一下这个场景,假如我们现在只有一个Redis,即单点Redis,我们在往Redis中添加数据的时候突然宕机了,那数据怎么办,如果是一条还好,我在敲一遍就行,那我敲了一万行都没保存,难道我要再敲一遍吗?这是不现实的,所以就出现了单点Redis的时第一个问题:数据丢失问题。那他的解决办法就是:实现Redis的数据持久化

1.1实现Redis的数据持久化

RDB

Redis Database Backup file,又称Redis数据快照,就是把内存中的数据全部记录到磁盘中,当Redis实例故障重启后,从磁盘读取快照文件,恢复数据。快照文件称为RDB文件,默认是保存在当前目录,Redis停机时会执行一次RDB

save 由Redis主进程执行RDB,会阻塞所有命令
bgsave 开启子进程执行RDB,避免主进程收到影响
RDB的原理

bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据。完成fork后读取内存数据并写入 RDB 文件。

fork采用的是copy-on-write技术:

  • 当主进程执行读操作时,访问共享内存;

  • 当主进程执行写操作时,则会拷贝一份数据,执行写操作。

RDB方式save的基本流程
  1. fork主进程得到一个子进程,共享内存空间

  2. 子进程读取内存数据并写入新的RDB文件

  3. 用新的RDB文件替换旧的RDB文件

RDB会在什么时候执行?
  • 默认是服务停止时

save 60 1000代表什么含义?
  • 代表60秒内至少执行1000次修改则触发RDB

RDB方式的缺点
  • RDB执行间隔时间长,两次RDB之间写入数据有丢失的风险

  • fork子进程,压缩,写出RDB文件都比较耗时

AOF

Append Only File,即追加文件,Redis处理的每一个写命令都会记录在AOF文件中,看一看做命令日志文件。因为AOF为记录命令,所以AOF文件会比RDB文件大得多,而且会记录对同一个key的多次写操作,但只有最后一次写操作才有意义。通过执行bgrewriteof命令,可以让AOF文件执行重写功能,用最少的命令达到相同的效果。Redis也会在触发阈值时,自动去重写AOF命令。

RDB和AOF区别

二者各有千秋,实际开发中往往会结合使用。

RDBAOF
持久化方式定时对整个内存做快照记录每一次执行的命令
数据完整性不完整,两次备份之间可会有丢失相对完整,取决于刷盘策略
数据恢复优先级低,数据完整性不如AOF高,因为数据完整性更高
系统资源占用高,大量的CPU和内存消耗低,主要是磁盘IO资源,但AOF重写时会占用大量的CPU和内存资源
使用场景可以容忍数分钟的数据丢失,追求更快的启动速度对数据安全性要求较高
文件大小会有压缩,文件体积小记录命令,体积大
宕机恢复速度

2.并发能力问题

现在我们解决了数据丢失的问题,那么还是在一样的场景下,我们现在只有一个Redis,既要读又要写,既当爹又当妈,那么此时此刻就是双11的零点,无数的读写请求在同一时刻打到redis上,那么即使一个Redis再快,也忙活不过来啊,因为读写的请求实在是太多了,这就是并发能力的问题,解决方法也很简单,搭建主从集群,实现读写分离

2.1主从集群实现读写分离

搭建主从架构:单点的Redis的并发能力是有上限的,要进一步提高Redis的并发能力,则要搭建Redis主从集群,实现读写分离。

假设现有A,B两个节点,那么只需要在B节点执行:slaveof A.IP A.port,B就可以成为A的slave节点

那么如何实现主从节点间的数据同步呢?

数据同步原理

主从第一次同步是全量同步

Replicatio ID:简称replID,是数据集的标记,id一致则说明是同一个数据集,每一个master都有唯一的replid,salve则会继承master的replid

offset:偏移量,随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前的eoffset。若slave的offset小于master的offset,说明master的新数据slave还未同步,需要更新。

slave做数据同步,必须向master声明自己的replid和offset,master才可以判断哪些数据需要同步

全量同步的流程

  1. slave节点请求增量同步

  2. master判断replid是否一致,不一致则拒绝

  3. master将完整的内存数据生成RDB,发送到slave

  4. slave请求本地数据,加载master的RDB

  5. master将RDB期间的命令记录在repl_baklog上,并持续将log中的命令发送给salve

  6. slave执行接收的命令,保持与master之间同步

若slave重启后同步,则执行增量同步,repl_baklog大小有上限,写满后会覆盖最早的数据,如果slave断开时间过久,导致尚未备份的数据被覆盖,则无法基于log做增量同步,只能再次全量同步

全量同步和增量同步的区别

  • 全量同步:master将完整的内存数据生成RDB文件,发送个slave,后续的命令则记录在repl_baklog中,逐步发送给slave

  • 增量同步:slave提交自己的offset到master,master获取repl_baklog中offset之后的命令个slave

什么时候执行全量同步?

  1. slave第一次连接master节点时

  2. slave节点断开太久,repl_baklog中的节点又被覆盖时

什么时候执行增量同步?

  • slave节点断开又恢复,并且在repl_baklog中能找到offset时

3.故障恢复问题

在第一个问题中,我么解决了数据持久化的问题,那么假如又出现一种新的状况(不要嫌多,实际环境的问题可能更多),那就是连我们数据持久化的RDB,AOF文件也跟着没了,此时我们该怎么办呢?不要担心,如果是slave节点没了,找master节点再进行数据同步就好了,那如果是master节点宕机怎么办呢?使用哨兵机制来实现主从集群的自动故障恢复。

3.1哨兵机制实现主从集群的自动故障恢复

哨兵集群结构

哨兵的作用

在上述的结构中,我们可以清晰的看到哨兵集群的三个作用

  • 监控:sentinal会不断检查master和slave是否按预期工作

  • 通知:哨兵会充当redis客户端的服务来发现来源,当集群发生故障转移时,会将最新消息推送给redis客户端

  • 自动故障恢复:如果master故障,哨兵会提拔一个slave作为新的master,当故障实例恢复后,也已新的master为主

服务状态监控

哨兵基于心跳机制检测服务状态,每隔一秒向集群的每一个实例发送ping命令

主观下线:如果某个哨兵发现某实例在规定时间内未作出响应,则认为该实例主观下线

客观下线:若超过指定数量的哨兵都以为该实例主管下线,则该实例客观下线,指定数量值最好超过哨兵数量的一半

自动故障恢复的过程

  1. 首先选定一个新的slave作为新的master,执行slave of no one

  2. 然后让所有节点执行slaveof 新master

  3. 修改故障节点,修改好后,执行slaveof 新master

4.存储能力问题

经过上述的学习,我们已经通过搭建主从集群,哨兵集群解决了高可用,高并发写的问题。但依然有两个问题未解决:

  • 海量数据存储问题

  • 高并发写的问题

所以使用分片集群解决上述问题

4.1分片集群

分片集群的结构

分片集群的特征

  1. 集群有多个master,每个master保存不同的数据

  2. 每个master节点都可以有多个slave

  3. master节点通过心跳机制监测批次的健康状态

  4. 客户端请求可以访问任意节点,最终都会被转发到正确节点

我们提到每个master保存不同的数据,那这些数据如何选择自己要保存的节点呢?这就要提到散列插槽

散列插槽

Redis会把每一个master节点映射到0--16383,共16384个插槽(hash slot)上,数据key不是与节点绑定,而是与插槽绑定,redis会根据key的有效部分计算插槽值,分两种情况:

  1. key中包含 { },{ }中至少有一个字符,{ }中的为有效值

  2. key中不包含{},整个key都是有效值

Redis如何判断某个key在哪个实例

  1. 将16384个插槽分配到不同的实例

  2. 根据key的有效部分计算哈希值,对16384取余

  3. 余数作为插槽,寻找插槽所在的实例即可

如何将同一类数据固定的保存在同一个Redis实例中

这一类数据使用相同的有效部分,例如key都已{typeID}为前缀

总结与反思

  1. 这四个问题及解决方法的核心,其实都是围绕在高并发的实际环境中展开的,这也就是如何应对日益增长的物质需求。

  2. 在这些集群中所使用到的方式,简直就是社会结构的缩影,在分片集群中甚至连哨兵的开销都省了。

  3. 笔落至此,我唯一顿感精妙之处在散列插槽,其利用了散列表键值对的特点,使算法复杂度降低为O(1),利用key计算哈希值,从而确定value,使本就基于内存的查找速度又更进一步,但是文中并未谈论到如果发生哈希碰撞,会怎么办呢?对插槽数值取余,这看起来像是采用了除法散列法,作为哈希函数的构造函方法,解决哈希碰撞可采用链接法,开放寻址法等,本文是讲解Redis的,就不赘述了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/65114.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机组成原理的学习笔记(8)-- 指令系统·其一 指令的组成以及数据寻址方式

学习笔记 前言 ​ 本文主要是对于b站尚硅谷的计算机组成原理的学习笔记,仅用于学习交流。 1. 指令 1.1 组成 操作码(Opcode):指指令中执行特定操作的部分。地址码:指令中用于指定操作数位置的部分。 1.2 扩展操作…

RAGFlow 基于深度文档理解构建的开源 RAG引擎 - 安装部署

RAGFlow 基于深度文档理解构建的开源 RAG引擎 - 安装部署 flyfish 1. 确保 vm.max_map_count ≥ 262144 这是指要调整Linux内核参数vm.max_map_count,以确保其值至少为262144。这个参数控制着进程可以映射的最大内存区域数量。对于某些应用程序(如Ela…

2024.2 ACM Explainability for Large Language Models: A Survey

Explainability for Large Language Models: A Survey | ACM Transactions on Intelligent Systems and Technology 问题 可解释性问题:大语言模型(LLMs)内部机制不透明,难以理解其决策过程,如在自然语言处理任务中&…

docker与docker-compose版本对应

1、说明 docker 和 docker-compose 是两个独立但又紧密相关的工具,docker用于管理docker容器,docker-compose用于编排多docker容器应用。了解它们之间的版本对应关系有助于确保在使用 docker-compose 时不会遇到兼容性问题。 2、docker与docker-compos…

【动态规划篇】步步带你深入解答成功AC最优包含问题(通俗易懂版)

本篇小鸡汤:待到苦尽甘来时,我给你讲讲来时路。 欢迎拜访:羑悻的小杀马特.-CSDN博客 本篇主题:解答洛谷的最优包含问题 制作日期:2024.12.23 隶属专栏:C/C题海汇总 ​​ 目录 本篇简介: 一动态…

Intent--组件通信

组件通信1 获取子活动的返回值 创建Activity时实现自动注册!【Activity必须要注册才能使用】 默认 LinearLayout 布局,注意 xml 中约束布局的使用; 若需要更改 线性布局 只需要将标签更改为 LinearLayout 即可,记得 设置线性布局…

table 表格转成 excell 导出

OK,功能非常简单,但是很实用啊! 依赖安装 这里我们需要安装两个依赖: xlsx 和 file-saver,就可以帮助我们实现功能了! npm i xlsx file-saver代码参考 导出方法 utils/index.js import * as XLSX from …

Vivado 编译(单核性能对比+高性能迷你主机+Ubuntu20.04/22.04安装与区别+20.04使用远程命令)

目录 1. 简介 2. 单核性能对比 2.1 PassMark 2.2 geekbench 2.3 CPU-7 2.4 选择 UM790 pro 3. Ubuntu 22.04 物理机 3.1 安装 Ubuntu 22.04 3.2 安装 Vitis 2022.1 3.3 缺点 4. Ubuntu 20.04 物理机 4.1 安装 Ubuntu 20.04 4.2 实用命令 4.2.1 SSH 保持活跃 4.2…

Java期末复习JDBC|网课笔记+校课总结

目录 1、概念 2、JDBC步骤 JDBC的基本步骤: 1、加载数据库驱动:通常使用Class类的forName()静态方法来加载驱动。 2、通过DriverManager获取数据库连接:需要传入3个参数:数据库URL、登陆数据库的用户名和密码。 3、通过Conn…

Require:离线部署 Sourcegraph

Sourcegraph 使读取、编写和修复代码变得容易——即使在庞大而复杂的代码库中。 代码搜索:搜索所有分支和所有代码主机的所有存储库。代码智能:导航代码、查找引用、查看代码所有者、跟踪历史记录等。修复和重构:一次对许多存储库进行大规模更…

element ui--下拉根据拼音首字母过滤

很多场景下我们的下拉不仅仅要根据选项中的字过滤,还要根据拼音首字母过滤,现在我们来实现下。 要获取汉字拼音,可以用pinyin-pro库来实现 1.导入拼音库 npm install pinyin-pro 下面的代码可以获取companyName的拼音,返回的是…

Vue3 中使用axios

1.安装axios、js-cookie、pinia axios命令行: npm install axios js-cookie命令行: npm install js-cookie store命令行: npm install pinia 2.配置文件 (1)缓存文件配置 src/plugins/auth.js const sessionCache {set (key, valu…

从AI换脸到篡改图像,合合信息如何提升视觉内容安全?

本文目录 引言一、AI“真假之战”下的发展现状与考验挑战1.1 视觉内容安全现状与技术分类1.2视觉内容安全企业1.3视觉内容安全领域挑战 二、开山之石:引领视觉内容安全的创新之路2.1合合内容安全系统2.2发起编制相关技术规范2.3参与篡改检测挑战赛 三、视觉内容安全…

解决Ubuntu下无法装载 Windows D盘的问题

电脑安装了 Windows 和 Ubuntu 24.04 后,在Ubuntu系统上装载 D盘,发现无法装载错误如下: Error mounting /dev/nvme0n1p4 at /media/jackeysong/Data: wrong fs type, bad option, bad superblock on /dev/nvme0n1p4, missing codepage or h…

STM32-笔记10-手写延时函数(SysTick)

1、什么是SysTick Systick,即滴答定时器,是内核中的一个特殊定时器,用于提供系统级的定时服务。该定时器是一个24位的倒计数定时器‌。它从设定的初值(即重载值)开始计数,每经过一个系统时钟周期&#xff0…

“AI+Security”系列第4期(一)之“洞” 见未来:AI 驱动的漏洞挖掘新范式

在数字化浪潮下,安全漏洞问题日益严峻,成为各行业发展的重大挑战。近日,“AISecurity” 系列第 4 期线下活动于北京成功举办,聚焦 “洞” 见未来:AI 驱动的漏洞挖掘新范式,汇聚了安全领域的众多专家。 本次…

攻防世界 PHP2

开启场景 访问 /index.php,页面无变化 访问 /index.phps index.php 和 index.phps 文件之间的主要区别在于它们的文件扩展名。 index.php:这是一个标准的 PHP 文件,通常用于编写 PHP 代码。当用户访问 index.php 文件时,Web 服务器…

AI应用-本地模型实现AI生成PPT(简易版)

文章目录 前言技术栈效果展示 一、实现思路二、实现步骤1.本地安装marp-cli2.后端实现3.前端实现 三、代码地址及说明 前言 在许多项目中,生成 PPT 是常见的需求,尤其在教育和报告展示中。传统的生成 PPT 的方法需要手动创建,而使用生成模型…

项目2路由交换

背景 某学校为满足日常教学生活需求,推动数字校园的建设,学校有办公楼和学生宿舍楼和服务器集群三块区域,请合理规划IP地址和VLAN,实现企业内部能够互联互通现要求外网能通过公网地址访问服务器集群,学生和老师能正常…

快速掌握Haproxy原理架构

文章目录 一、原理架构二、无负载均衡三、四层负载均衡的工作流程四、七层负载均衡工作流程五、基础属性mode 属性retries 属性maxconn 属性clitimeout 属性servtimeout 属性states uri 属性 一、原理架构 四层tcp代理:Haproxy仅在客户端和服务器之间双向转发流量&…