【Redis持久化】服务器突然挂了!Redis缓存都在内存中啊

该日志由 samool 发表于 2020-09-27 14:29:53

我是Redis,一个叫Antirez的男人把我带到了这个世界上。

“快醒醒!快醒醒!”,隐隐约约,我听到有人在叫我。

慢慢睁开眼睛,原来旁边是MySQL大哥。

“我怎么睡着了?”

“嗨,你刚才是不是出现了错误,整个进程都崩溃了!害得一大堆查询请求都给我怼过来了!”,MySQL说到。

刚刚醒来,脑子还有点懵,MySQL大哥扶我起来继续工作。

“糟了!我之前缓存的数据全都不见了!”

“WTF?你没有做持久化吗?”,MySQL大哥一听脸色都变了。

我尴尬的摇了摇头,“我都是保存在内存中的,所以才那么快啊”

“那也可以在硬盘上保存一下啊,遇到这种情况全部从头再来建立缓存,这不浪费时间嘛!”

我点了点头,“让我琢磨一下,看看怎么做这个持久化”。

RDB持久化

没几天,我就拿出了一套方案:RDB

既然我的数据都在内存中存放着,最简单的就是遍历一遍把它们全都写入文件中。

为了节约空间,我定义了一个二进制的格式,把数据一条一条码在一起,生成了一个RDB文件。

不过我的数据量有点大,要是全部备份一次得花不少时间,所以不能太频繁的去做这事,要不然我不用干正事了,光花时间去备份了。

还有啊,要是一直没有写入操作,都是读取操作,那我也不用重复备份,浪费时间。

思来想去,我决定提供一个配置参数,既可以支持周期性备份,也可以避免做无用功。

就像这样:

  • save 900 1 # 900秒(15分钟)内有1个写入
  • save 300 10 # 300秒(5分钟)内有10个写入
  • save 60 10000 # 60秒(1分钟)内有10000个写入

多个条件可以组合使用,只要上面一个条件满足,我就会去进行备份。

后来我又想了一下,这样还是不行,我得fork出一个子进程去做这件事,不能浪费我的时间。

有了备份文件,下次我再遇到崩溃退出,甚至服务器断电罢工了,只要我的备份文件还在,我就能在启动的时候读取,快速恢复之前的状态啦!

MySQL:binlog

我带着这套方案,兴冲冲的拿给了MySQL大哥看了,期待他给我一些鼓励。

“老弟,你这个方案有点问题啊”,没想到,他竟给我浇了一盆冷水。

“问题?有什么问题?”

“你看啊,你这个周期性去备份,周期还是分钟级别的,你可知道咱们这服务每秒钟都要响应多少请求,像你这样不得丢失多少数据?”,MySQL语重心长的说到。

我一下有些气短了,“可是,这个备份一次要遍历全部数据,开销还是挺大的,不适合高频执行啊”

“谁叫你一次遍历全部数据了?来来来,我给你看个东西”,MySQL大哥把我带到了一个文件目录下:

  • mysql-bin.000001
  • mysql-bin.000002
  • mysql-bin.000003
  • ···

“看,这些是我的二进制日志binlog,你猜猜看里面都装了些什么?”,MySQL大哥指着这一堆文件说到。

我看了一眼,全是一堆二进制数据,这哪看得懂,我摇了摇头。

“这里面呀记录了我对数据执行更改的所有操作,像是INSERTUPDATEDELETE等等动作,等我要进行数据恢复的时候就可以派上大用场了”

听他这么一说,我一下来了灵感!告别了MySQL大哥,回去研究起新的方案来了。

AOF持久化

你们也知道,我也是基于命令式的,每天的工作就是响应业务程序发来的命令请求。

回来以后,我决定照葫芦画瓢,学着MySQL大哥的样子,把我执行的所有写入命令都记录下来,专门写入了一个文件,并给这种持久化方式也取了一个名字:AOF(Append Only File)

不过我遇到了RDB方案同样的问题,我该多久写一次文件呢?

我肯定不能每执行一条写入命令就记录到文件中,那会严重拖垮我的性能!我决定准备一个缓冲区,然后把要记录的命令先临时保存在这里,然后再择机写入文件,我把这个临时缓冲区叫做aof_buf

说干就干,我试了一下,竟然发现数据没有写入到文件中去。多方打听才知道,原来操作系统也有个缓存区,我写的数据被他缓存起来了,没有给我写入到文件中去,这不是坑爹呢嘛!

看来,我写完了还得要去刷新一下,把数据真正给写下去,思来想去,我还是提供一个参数,让业务程序去设置什么时候刷新吧。

appendfsync参数,三个取值:

  • always: 每个事件周期都同步刷新一次
  • everysec: 每一秒都同步刷新一次
  • no: 我只管写,让操作系统自己决定什么时候真正写入吧

AOF重写

这一次我不像之前那么冲动,我决定先试运行一段时间再去告诉MySQL大哥,免得又被他戳到软肋。

试用了一段时间,各方面都运行良好,不过我发现随着时间的推移,我写的这个AOF备份文件越来越大,越来越大!不仅非常占硬盘空间,复制移动,加载分析都非常的麻烦耗时。

我得想个办法把文件给压缩一下,我把这个过程叫做AOF重写

一开始,我打算去分析原来的AOF文件,然后将其中的冗余指令去掉,来给AOF文件瘦瘦身,不过我很快放弃了这个想法,这工作量实在太大了,分析起来也颇为麻烦,浪费很多精力跟时间。

原来的一条条记录这种方式实在是太笨了,数据改来改去,有很多中间状态都没用,我何不就把最终都数据状态记录下来就好了?

比如:

  • RPUSH name_list'编程技术宇宙'
  • RPUSH name_list'帅地玩编程'
  • RPUSH name_list'后端技术学堂'

可以合并成一条搞定:

  • RPUSH name_list '编程技术宇宙' '帅地玩编程' '后端技术学堂'

AOF文件重写的思路我是有了,不过这件事干起来还是很耗时间,我决定和RDB方式一样,fork出一个子进程来做这件事情。

谨慎如我,发现这样做之后,子进程在重写期间,我要是修改了数据,就会出现和重写的内容不一致的情况!MySQL大哥肯定会挑刺儿,我还得把这个漏洞给补上。

于是,我在之前的aof_buf之外,又准备了一个缓冲区:AOF重写缓冲区

从创建重写子进程开始的那一刻起,我把后面来的写入命令也copy一份写到这个重写缓冲区中,等到子进程重写AOF文件结束之后,我再把这个缓冲区中的命令写入到新的AOF文件中。

最后再重命名新的AOF文件,替换掉原来的那个臃肿不堪的大文件,终于大功告成!

再三确定我的思路没有问题之后,我带着新的方案再次找到了MySQL大哥,我都做到这份儿上了,这一次,想必他应该无话可说了吧?

MySQL大哥看了我的方案露出了满意的笑容,只是问了一个问题:

这AOF方案这么好了,RDB方案是不是可以不要了呢?

万万没想到,他居然问我这个问题,我竟陷入了沉思,你觉得我该怎么回答好呢?

彩蛋

“你怎么又崩溃了?”

“不好意思,又遇到bug了,不过不用担心,我现在可以快速恢复了!”

“那老崩溃也不是事儿啊,你只有一个实例太不可靠了,去找几个帮手吧!”

该日志标签: 技术, 进程, 查询, 动作, 工作, 目录, 错误, 日志, 漏洞, 世界, 内容, 文件, 程序, 运行, 实例, 男人, mysql, 编程, bug, 周期, 问题, 命令, 同步, 数据, 记录, 时间, 参数, 指令, 内存, 崩溃, , 时候, aof, 写入, 重写

如何学习一门新的语言

该日志由 samool 发表于 2020-09-13 17:14:29

首先要说,这并不是一篇教你如何学习的文章,因为到今天为止我也没有找到一种通用的方法来解决如何学习的问题。但是在探索的道路上,我确实产生过一些思路,我想把这些思考的过程分享出来让大家探讨。如果这对你有帮助的话,那我会非常高兴。

我最近在学习 Rust ,这是一门很酷但是相对冷门的语言(学习冷门语言可能是我的一大爱好,比如我就非常喜欢 CoffeeScript ,这是 JavaScript 的一门方言)。自从在某些语言的舒适区待久之后,经常会产生自己无所不能的错觉,这也是我不断想学习新语言的一大动力。

而我的学习过程跟大多数人类似,就是先在网上找文档然后自学。而在看文档的过程中,我就发现了一些问题。

手册的作用

“去看文档喽。”这是老鸟在面对新手时最喜欢扔的一句话,我通常也是这么扔给自己的。但当你打开一门语言的手册,你会发现它除了教你语法外,几乎没有教你什么其它东西。于是你会陷入这样一个境地:

“背下来了么?”
“背不下来,太难懂了。”
“再看一遍,给我背下来。”
。。。
“背下来了么?”
“大部分背下来了。”
“给我写个程序,实现个XX功能。”
“不会。。。”
“。。。”

在一个高级开发者眼里,你会了语法理所当然就应该会写程序了,但实际情况并非如此。这让我想起前段时间跟一个朋友关于目前编程教育市场的一个讨论。我出于自己的经验提出一个想法:让大牛开发者来教新手入门。在我的设想中,大牛开发者拥有强大的实战经验,以及丰富的专业知识,更是自带光环,这不比现在市场上那些半吊子的讲师好多了。在我为自己“伟大”的想法得意的时候,朋友给我浇了一盆冷水。他告诉我这样根本行不通,大牛根本不知道菜鸟需要什么知识,你可能以为基础语法讲清楚就好了,人家却连编辑器是什么都不清楚。设想一下,让一个大学教授去教一群小学生,这对两者来说都是一种灾难吧。

这些语言的创造者,或者文档的作者,无疑都是一些大神。它们在撰写一个语言手册的过程中,只能尽量负责地把这个语言的全貌准确地有组织地展现给你。然而这种全面的展现,对于一个没有任何引导的初学者来说并不完全是一件好事。简单来说就是,你会在一些次要的事情上浪费太多时间,而一些主要的概念又没有理解透彻。

关于看真实代码

当觉得文档满足不了你的时候,老鸟们往往会扔给你第二招:看代码。看什么代码呢?那还用说,当然是被业界奉为经典的,在 GitHub 上至少有一万颗星的知名开源项目代码啦。

当你怀着崇敬的心情,打开扔给你的网址,看着满屏幕的代码时,你会对自己问出那三个经典的哲学问题。这是什么东西?它是怎么做到的?为什么要这么写?搞不好某些人还会因为惊吓过度,从而失去了学习下去的信心。

那么让我们一起来看看这些代码里有什么鬼东西,会吓得新手信心不足。

大段的注释

说一件事你们不要笑,在我还是个萌新的时候,我曾经对这些穿插在代码中的神秘文字产生了深深的困惑,我还以为它们对代码有某种加成作用,以至于我还试验过把注释去掉会对代码执行产生什么影响。而现实中好的代码会让后面的维护者方便很多,但不好的甚至错误的注释会让人迷惑不已。

语法糖

语法糖是个好东西,它大大简化了我们的编程过程,高手用起语法糖写起代码来简直不要太爽,所以越强大的项目这玩意儿越多。但是对于初学者来说,语法糖隐藏了一些细节,而且让语法看起来很怪异。有些代码如果你用标准语法来写是很好懂的,但如果用语法糖来写的话很难让人一下子明白。

初学者为了弄懂这些语法往往要花大量时间,但其实这些时间在这个阶段是没必要的浪费。你看不懂它觉得它是一个很重要的东西,其实它只是一个做工精巧的小玩意儿,离开了它这些代码照样能工作。而随着你的经验丰富,也可以随时随地用起来,用的方法可能也不尽相同。

代码里的重点

对于一个开源项目来说,往往 50% 的代码可能都是在适配各种不同的运行环境,将系统的 API 抽象成项目里通用的接口,这部分代码除非你自己要做类似的项目,要不然的话对初学者来说参考意义不大。更何况,为了适配某些系统奇葩的运行环境,开发者往往会大开脑洞,创造出一些非常奇怪的代码。这些旁门左道充满了玄学和不确定性,初学者看多了可能会发生如武侠小说里练功出差错的结果:走火入魔。

剩下的代码里 20% 是项目内部的接口抽象和定义,最后 30% 才是真正值得看的东西,它们往往散落在各个地方,但又为了一个设计核心服务。让初学者识别出这些代码来,未免太强人所难。

野文档

这是我自己的一个定义,我把一切非官方的开发文档都称为野文档。初学者会在搜索引擎里得到大量的相关文档,他们很多是学习心得,很多人在写这篇文章时水平可能比你也高不了多少。这就造成了这些文档的水平参差不齐,所面向的重点也不同,也许你花了大把时间弄懂的是一个错误的或者过时的知识。而大部分号称教你入门的文章,可能也就是告诉了你如何搭建一个运行环境,这门语言的精髓和重点作者自己估计也没弄明白。

而如果你碰到一篇被奉为经典的好的入门文章,那你真的要好好感谢作者。因为这意味着作者付出了大量的深入思考,深入浅出这四个字说起来简单,做起来可是需要相当的功底的。

相对较好的做法

在这么多语言的学习过程中,我也总结了一些相对比较好的学习方法。我认为看代码是非常有必要的,因为光死记语法是无法掌握好这门语言的。但是去看一些大型项目代码的缺点我在上面也说了,到底该如何是好呢?

我建议大家可以去看官方给出的,专门供初学者学习的 Step-By-Step 代码,这种代码一般在官方的文档页就可以找到链接入口,它有如下好处:

  1. 由浅入深,富有层次。这些代码往往是跟随者文档的深入,慢慢把语法细节展开的。不会一下给你展现太多,让你无法 GET 到重点。每段代码都会有一个重点要表现的特性,这样看起来会一目了然。
  2. 有质量保证。这些代码的撰写一般是官方人员负责,这可以在很大程度上保证准确性。
  3. 更新及时。我们知道很多语言的细节是会随着版本的升级有所改变的,而很多网上的第三方文档往往缺乏维护,但官方文档一般都会同步更新。

我建议大家一边看手册一边看代码,这样印象会更深刻。眼睛看了之后,我认为要尽快找一些好的例子来练手,不需要一上来就搞比较复杂的大型项目,也是由浅入深。这种练手项目去哪里找呢,很多语言的 tutorial 板块就是干这个的,做的比较完善的甚至还提供在线的教学体验环境,大家应该好好利用。

写在最后

这篇讨论学习方法的文章引发了我的一些额外思考。我经常在开发者社区里看到老鸟和初学者互怼,写这篇文章的过程也让我理性思考了产生这些矛盾的原因。总的来说就是一些信息的不对称造成的。老鸟认为这个问题根本不是问题,网上一搜一大把,不愿多讲甚至冷嘲热讽。而初学者却觉得这些信息根本理解不能,老鸟的嘲讽就是一种羞辱。

我认为要打破这种不对称需要双方付出耐心,而这种耐心的付出是相互的,你付出的多回报的就越多。而最先迈出付出这一步的,应该是初学者,毕竟从情理上来说是你请求人家办事。而你需要付出的不过是把自己的问题讲明白,说出你的思考过程,附上必要的信息。一个好学的人是不会让人讨厌的,但前提是你得有一个不让人讨厌的姿态展现出来。

文章来源:https://joyqi.com/develop/how-to-learn-a-programming-language.html

该日志标签: 升级, 朋友, 工作, 心情, 系统, 来源, 经典, 心得, 搜索引擎, 社区, 设计, 开发, 接口, 学习, 方法, 程序, 运行, 在线, 链接, 代码, 编程, 信息, 网址, 灾难, 问题, 时间, 环境, 特性, 细节, 组织, API, 文章, GitHub, 缺点, 时候, 初学者, 语法, 文档, 语言

Visual Studio 2008 Service Pack 1 - BETA发布

该日志由 samool 发表于 2008-05-12 08:51:27

Visual Studio 2008 SP1 提供了对Visual Studio 2008的各项改进,支持SQL Server 2008和ADO.NET的新特性Entity Framework,许多WPF设计器的改进,Silverlight 项目的WCF模板,.NET Framework的symbols和代码调试支持,控件的改进和增加新的控件(例如Windows From的DataRepeater控件和支持 C++Office 2007 Ribbons ),以及许多的泛型调试和智能感知的支持。这个补丁包还包括改善Visual Studio 的稳定性,性能和安全性。

有什么问题可以反馈到http://connect.microsoft.com/VisualStudio. Visual Studio 2008 Service Pack 1的Msdn论坛http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=2136&SiteID=1

下载地址:

  • VS 2008 SP1 : http://download.microsoft.com/download/7/3/8/7382EA08-4DD6-4134-9B92-8585A5B07973/VS90sp1-KB945140-ENU.exe
  • .NET 3.5 SP1 : http://download.microsoft.com/download/8/f/c/8fc1fe13-55de-4bf5-b43e-375daf01452e/dotNetFx35setup.exe
  • Express 2008 with SP1:
  • http://download.microsoft.com/download/F/E/7/FE754BA4-140B-413C-933F-8D35FB150F12/vbsetup.exe
  • http://download.microsoft.com/download/F/E/7/FE754BA4-140B-413C-933F-8D35FB150F12/vcsetup.exe
  • http://download.microsoft.com/download/F/E/7/FE754BA4-140B-413C-933F-8D35FB150F12/vcssetup.exe
  • http://download.microsoft.com/download/F/E/7/FE754BA4-140B-413C-933F-8D35FB150F12/vnssetup.exe
  • TFS 2008 SP1:http://download.microsoft.com/download/a/e/2/ae2eb0ff-e687-4221-9c3e-9165a942bc1c/TFS90sp1-KB949786.exe
  • 该日志标签: 编程, vs

    学习编程人员必读(C++为例)

    该日志由 samool 发表于 2008-03-03 14:52:03

    这是俺在别的论坛看到的一篇很早的帖子,虽然俺学C++时间也不长,还是一只菜鸟,但是俺觉得下面说的不错,真的不错,同时可以免了很多坛友询问如何学习C++的口舌:
    1.把C++当成一门新的语言学习(和C没啥关系!真的。);
    2.看《Thinking In C++》,不要看《C++变成死相》;
    3.看《The C++ Programming Language》和《Inside The C++ Object Model》,不要因为他们很难而我们自己是初学者所以就不看;
    4.不要被VC、BCB、BC、MC、TC等词汇所迷惑——他们都是集成开发环境,而我们要学的是一门语言;
    5.不要放过任何一个看上去很简单的小编程问题——他们往往并不那么简单,或者可以引伸出很多知识点;
    6.会用Visual C++,并不说明你会C++;
    7.学class并不难,template、STL、generic programming也不过如此——难的是长期坚持实践和不遗余力的博览群书;
    8.如果不是天才的话,想学编程就不要想玩游戏——你以为你做到了,其实你的C++水平并没有和你通关的能力一起变高——其实可以时刻记住:学C++是为了编游戏的;
    9.看Visual C++的书,是学不了C++语言的;
    10.浮躁的人容易说:XX语言不行了,应该学YY;——是你自己不行了吧!?
    11.浮躁的人容易问:我到底该学什么;——别问,学就对了;
    12.浮躁的人容易问:XX有钱途吗;——建议你去抢银行;
    13.浮躁的人容易说:我要中文版!我英文不行!——不行?学呀!
    14.浮躁的人容易问:XX和YY哪个好;——告诉你吧,都好——只要你学就行;
    15.浮躁的人分两种:a)只观望而不学的人;b)只学而不坚持的人;
    16.把时髦的技术挂在嘴边,还不如把过时的技术记在心里;
    17.C++不仅仅是支持面向对象的程序设计语言;
    18.学习编程最好的方法之一就是阅读源代码;
    19.在任何时刻都不要认为自己手中的书已经足够了;
    20.请阅读《The Standard C++ Bible》(中文版:标准C++宝典),掌握C++标准;
    21.看得懂的书,请仔细看;看不懂的书,请硬着头皮看;
    22.别指望看第一遍书就能记住和掌握什么——请看第二遍、第三遍;
    23.请看《Effective C++》和《More Effective C++》以及《Exceptional C++》;
    24.不要停留在集成开发环境的摇篮上,要学会控制集成开发环境,还要学会用命令行方式处理程序;
    25.和别人一起讨论有意义的C++知识点,而不是争吵XX行不行或者YY与ZZ哪个好;
    26.请看《程序设计实践》,并严格的按照其要求去做;
    27.不要因为C和C++中有一些语法和关键字看上去相同,就认为它们的意义和作用完全一样;
    28.C++绝不是所谓的C的“扩充”——如果C++一开始就起名叫Z语言,你一定不会把C和Z语言联系得那么紧密;
    29.请不要认为学过XX语言再改学C++会有什么问题——你只不过又在学一门全新的语言而已;
    30.读完了《Inside The C++ Object Model》以后再来认定自己是不是已经学会了C++;
    31.学习编程的秘诀是:编程,编程,再编程;
    32.请留意下列书籍:《C++面向对象高效编程(C++ Effective Object-Oriented Software Construction)》《面向对象软件构造(Object-Oriented Software Construction)》《设计模式(Design Patterns)》《The Art of Computer Programming》;
    33.记住:面向对象技术不只是C++专有的;
    34.请把书上的程序例子亲手输入到电脑上实践,即使配套光盘中有源代码;
    35.把在书中看到的有意义的例子扩充;
    36.请重视C++中的异常处理技术,并将其切实的运用到自己的程序中;
    37.经常回顾自己以前写过的程序,并尝试重写,把自己学到的新知识运用进去;
    38.不要漏掉书中任何一个练习题——请全部做完并记录下解题思路;
    39.C++语言和C++的集成开发环境要同时学习和掌握;
    40.既然决定了学C++,就请坚持学下去,因为学习程序设计语言的目的是掌握程序设计技术,而程序设计技术是跨语言的;
    41.就让C++语言的各种平台和开发环境去激烈的竞争吧,我们要以学习C++语言本身为主;
    42.当你写C++程序写到一半却发现自己用的方法很拙劣时,请不要马上停手;请尽快将余下的部分粗略的完成以保证这个设计的完整性,然后分析自己的错误并重新设计和编写(参见43);
    43.别心急,设计C++的class确实不容易;自己程序中的class和自己的class设计水平是在不断的编程实践中完善和发展的;
    44.决不要因为程序“很小”就不遵循某些你不熟练的规则——好习惯是培养出来的,而不是一次记住的;
    45.每学到一个C++难点的时候,尝试着对别人讲解这个知识点并让他理解——你能讲清楚才说明你真的理解了;
    46.记录下在和别人交流时发现的自己忽视或不理解的知识点;
    47.请不断的对自己写的程序提出更高的要求,哪怕你的程序版本号会变成Version 100.XX;
    48.保存好你写过的所有的程序——那是你最好的积累之一;
    49.请不要做浮躁的人;
    50.请热爱C++!

    该日志标签: 开发, 程序, c, c++, 编程