
📫作者简介:小明java问道之路,2022年度博客之星全国TOP3,专注于后端、中间件、计算机底层、架构设计演进与稳定性建设优化。文章内容兼具广度深度、大厂技术方案,对待技术喜欢推理加验证,就职于知名金融公司后端高级工程师。
📫 热衷分享,喜欢原创~ 关注我会给你带来一些不一样的认知和成长。
🏆 2022博客之星TOP3 | CSDN博客专家 | 后端领域优质创作者 | CSDN内容合伙人
🏆 InfoQ(极客邦)签约作者、阿里云专家 | 签约博主、51CTO专家 | TOP红人、华为云享专家
🔥如果此文还不错的话,还请👍关注、点赞、收藏三连支持👍一下博主~
🍅 文末获取联系 🍅 👇🏻 精彩专栏推荐订阅收藏 👇🏻
专栏系列(点击解锁)
学习路线(点击解锁)
知识定位
全面讲解MySQL知识与企业级MySQL实战 🔥计算机底层原理🔥
本文讲解Redis持久性机制RDB,RDB持久化的两种方法(RDB的两种策略方式、save和bgsave命令)并进行比较,如何使用RDB策略备份数据,分析Redis RDB优缺点,bgsave原理,bgsave执行流程,fork的实现原理(Copy On Write写时复制)。
Redis提供了两种持久性机制:一种是RDB也称为快照模式,一种是AOF日志也称为追加模式。
Redis RDB 是生成当前进程中数据的快照并将其保存到硬盘(因此也称为快照持久性),保存的文件后缀是.rdb,RDB是Redis的默认数据持久化方法,它将把数据库快照保存在dump.rdb二进制文件中,当Redis重新启动时可以读取快照(即以二进制文件的形式保存内存数据)并从文件中恢复数据。
当在Redis客户端上执行save命令时,将在Redis安装目录中生成RDB文件,save有一个致命问题,Redis服务在持久化期间被阻止(确切地说,它将阻止当前执行save命令的线程,但 Redis 是单线程的,因此整个服务将被阻止)Redis就不能继续提供外部请求,如果数据量很小,则影响很小,如果每次复制需要1小时,相当于一小时的停机时间。
使用 Linux的fork()函数用于生成主进程的子进程,用于完成RDB的生成。生成完成后,将通知主进程我们的RDB文件已成功生成。时间复杂度也是O(n),但它不会阻塞主进程
底层原理是 fork()+copyonwrite,bgsave可以在持久化的同时提供外部读写服务,而不会相互影响,新写的数据不会对已经持久化的数据造成数据影响,持久化过程中的出现异常或时间过长不会对Redis的外部服务产生任何影响,持久化后,新的rdb文件将覆盖前一个文件。
| save | bgsave | |
| IO | 同步 | 异步 |
| 阻塞 | 是 | 部分(fork时发生阻塞) |
| 时间复杂度 | O(n) | O(n) |
| 优点 | 不消耗额外内存 | 不阻塞客户端命令 |
| 缺点 | 阻塞客户端命令 | 需要fork消耗内存 |
RDB持久化的触发分为手动触发和自动触发两种,Redis可以通过客户端主动持久化,输入命令(手动在客户端输入save 或 bgsave命令)生成RDB文件,也可以通过配置来等满足条件时自动持久化(自动触发是在配置文件中通过save m n,指定当m秒内发生n次变化时,会触发bgsave,比如save m n配置,save 900 1,意味着900秒内至少有1个key被改变则做一次快照)生成RDB文件。
一般情况下不会手动触发,在主从复制期间,从库全量主库数据,主库将执行bgsave命令进行快照;当客户端执行数据库清空命令FLUSHALL时触发快照;当客户端执行shutdown关闭Redis时触发快照。
优点:RDB文件简单快捷,它在某个时间点存储Redis数据,适合备份,可以设置一个时间点来归档RDB文件,以便在需要时可以轻松地将数据恢复到不同的版本,也就是说RDB适合灾难恢复(灾备),单个文件可以轻松地传输到远程服务器,RDB的性能非常好,当需要持久性时,主进程将派生出一个子进程,然后将持久性工作移交给子进程(bgsave)。
缺点:RDB存在丢失数据问题,假设快照(自动触发save m n配置)每5分钟保存一次,如果Redis由于某种原因无法正常工作,则从上次生成快照到Redis出现问题的数据将丢失。RDB使用fork() 为数据持久化生成子进程,如果数据很大,可能需要一些时间,导致Redis停止服务。

Redis父进程首先确定否有有正在执行的save、bgsave、bgrewriteaof的子进程,如果正在执行,bgsave命令将直接返回。
父进程执行fork操作以创建子进程,在此过程中,父进程被阻止,Redis无法从客户端执行任何命令。在父进程fork后,bgsave命令返回保存信息,不再阻止父进程,并可以响应其他命令,子进程创建RDB文件,基于父进程的内存快照生成临时快照文件,并在完成后执行原始文件的原子替换
子进程向父进程发送信号以指示完成,父进程更新统计信息。
fork实现通过Copy-on-Write写时复制,,类似于Java中的CopyOnWriteArrayList。如果多个调用方同时需要相同的资源(如内存或磁盘中的数据存储),多个调用方将共同获得指向同一资源的相同指针,在调用方尝试修改资源的内容之前,系统实际上会向调用方复制一个特殊副本,其他调用方看到的初始资源保持不变。
这是 Linux 的机制,为了节省内存资源,尽可能多地共享资源,在进程分离的时刻,内存增长几乎没有显著变化。在Redis中,子进程执行数据持久化不会修改现有的内存数据结构,只会遍历和读取数据结构,然后将其序列化到磁盘。父进程不同需要继续服务客户端请求,然后不断修改内存数据结构。这个时候就会使用操作系统的 COW 机制来进行数据段页面的分离(请参考:【精通内核】计算机程序的本质、内存组成与ELF格式深度解析)。

数据段由许多操作系统的页面组成,当父进程修改其中一个页面的数据时,它将复制并分离共享页面,然后修改复制的页面,此时,子流程的相应页面或生成流程时的数据不会更改。因为子进程的数据没有改变,所以它所能看到的内存中的数据在进程生成时被冻结,不会再改变,所有Redis持久性被称为快照,所有子进程可以安全的遍历数据并写入磁盘。
本文讲解Redis持久性机制RDB,RDB持久化的两种方法(RDB的两种策略方式、save和bgsave命令)并进行比较,如何使用RDB策略备份数据,分析Redis RDB优缺点,bgsave原理,bgsave执行流程,fork的实现原理(Copy On Write写时复制)。
最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru
对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs
一、引擎主循环UE版本:4.27一、引擎主循环的位置:Launch.cpp:GuardedMain函数二、、GuardedMain函数执行逻辑:1、EnginePreInit:加载大多数模块int32ErrorLevel=EnginePreInit(CmdLine);PreInit模块加载顺序:模块加载过程:(1)注册模块中定义的UObject,同时为每个类构造一个类默认对象(CDO,记录类的默认状态,作为模板用于子类实例创建)(2)调用模块的StartUpModule方法2、FEngineLoop::Init()1、检查Engine的配置文件找出使用了哪一个GameEngine类(UGame
我想用Capistrano启动sidekiq。下面是代码namespace:sidekiqdotask:startdorun"cd#{current_path}&&bundleexecsidekiq-c10-eproduction-Llog/sidekiq.log&"pcapture("psaux|grepsidekiq|awk'{print$2}'|sed-n1p").strip!endend它执行成功但sidekiq仍然没有在服务器上启动。输出:$capsidekiq:starttriggeringloadcallbacks*2014-06-0315:03:01executing`
我有一个正在升级到Rails3的Rails2.3.5应用程序。我做了所有我需要做的升级以及当我使用启动Rails服务器时要做的事情railsserver它给了我这个PleaseswitchtoRuby1.9'sstandardCSVlibrary.It'sFasterCSVplussupportforRuby1.9'sm17nencodingengine.我正在使用ruby-1.9.2-p0并安装了fastercsv(1.5.3)gem。在puts语句的帮助下,我能够追踪到错误发生的位置。我发现执行在这一行停止了Bundler.require(:default,Rails.env)if
电脑启动出现显示器黑屏是一个相当常见的问题。如果您遇到了这个问题,不要惊慌,因为它有很多可能的原因,可以采取一些简单的措施来解决它。在本文中,小编将介绍下面4种常见的电脑启动后显示器黑屏的原因,排查这些原因,快速解决! 演示机型:联想Ideapad700-15ISK-ISE系统版本:Windows10一、显示器问题如果出现电脑启动后显示器黑屏的情况。那么首先您需要检查一下显示器是否正常工作。您可以通过更换另一个显示器或将当前显示器连接到另一台计算机来检查显示器是否存在问题。如果问题仍然存在,那么您可以排除显示器故障的可能性。 二、显卡问题如果您的电脑配备了独立显卡,那么显卡故障也可能是导致电脑
一、什么是MQTT协议MessageQueuingTelemetryTransport:消息队列遥测传输协议。是一种基于客户端-服务端的发布/订阅模式。与HTTP一样,基于TCP/IP协议之上的通讯协议,提供有序、无损、双向连接,由IBM(蓝色巨人)发布。原理:(1)MQTT协议身份和消息格式有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。MQTT传输的消息分为:主题(Topic)和负载(payload)两部分Topic,可以理解为消息的类型,订阅者订阅(Su
TCL脚本语言简介•TCL(ToolCommandLanguage)是一种解释执行的脚本语言(ScriptingLanguage),它提供了通用的编程能力:支持变量、过程和控制结构;同时TCL还拥有一个功能强大的固有的核心命令集。TCL经常被用于快速原型开发,脚本编程,GUI和测试等方面。•实际上包含了两个部分:一个语言和一个库。首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。由于TCL的解释器是用C\C++语言的过程库实现的,因此在某种意义上我们又可以把TCL看作C库,这个库中有丰富的用于扩展TCL命令的C\C++过程和函数,所以,Tcl是
plsql连接Oracle超时,完犊子了肯定是服务器断电了。得马上检查Oracle服务器状态1、检查数据库是否启动su-oracle切换到Oracle用户,输入sqlplus/assysdba显示连接状态。如果末尾显示的状态是Connectedtoanidleinstance.证明未启动2、启动数据库startup启动数据库,末尾出现Databaseopened说明数据库启动成功3、查看数据库监听是否正常先quit;断开Oracle连接,使用lsnrctlstatus查看监听状态,如果出现TNS-开头的Nolistener、Connectionrefused等错误,说明监听未启动4、启动数据库
当Rails启动时,它会预加载所有依赖项(gems),这会导致启动时间非常缓慢。在我正在处理的一个中型项目中,Rails的启动时间为10-15秒,具体取决于机器。虽然这在生产中不是问题,但在开发中却是一个巨大的痛苦。特别是在工作TDD/BDD时。有加速测试的解决方案(如spork),但它们会引入自己的问题。我的问题是:为什么不在每个代码文件中要求所需的依赖项,而不是在启动时预加载所有内容?手动要求的缺点是什么?额外的代码行? 最佳答案 Rails不是PHP。一些资源是自动加载的,但是您可能需要的所有资源都在启动/初始化时加载,因为最