/首页
/开源
/关于
来,聊个小问题
发表@2020-10-09 22:28:16
更新@2023-04-27 18:45:26
大家好,我是神棍局副局长兼谢顶道人老李。 这次吧,我也实在给自己找不到偷懒的借口了,总之一句话:有好多话现阶段我不能敞开聊。比如有可能在将来某一天,老李也老母鸡翻着跟头生孩子---滚蛋,滚蛋回老家了,滚蛋离开这行业了,就啥也能叨叨了。不过咋说吧,感谢各位的长期关注,这段时间莫名其妙的增长关注量让我觉得我不能太懒惰了寒了大伙儿的心,以后保持周更级别的活跃更新发文的节奏,准备更一个比较简单平时用的比较多的业务方向系列:《API安全指东》。 鉴于老李最近在造火箭,然后就遇到了一个拧螺丝的疑难杂症(造火箭也不为别的,主要是考虑到自己的JB全家桶快到期了,需要马上用新的开源火箭去换新一年的JB许可证)。 事情大概是这样shai儿的:假设有一个文本文件X,假设其中都是json文本,进程A会在朗朗乾坤下随时随地读取X文件并解析,进程B会在光天化日之下随心所欲地写X文件,其中进程A和进程B之间是清白的且在同一操作系统环境中,如何保证进程B写文件时候进程A也能读到完整文件json内容并解析。 实际上这又是一个典型的“ 我以为我读懂了apue但实际上并没有 ”基础问题。上一次遇到这种问题还是老李大战file_put_content的时候,这篇文章链接我会加到末尾。 当时这问题被抛到神棍局后,有几个神棍兼泥腿子上来就抛出来几个神棍级的泥腿方案。虽然言语之间对自己的方法充满了自豪但嘴上却声称“ 自己也是抛砖引玉 ”,呵,泥腿子。 其中,最火爆的人气级神棍方案当属“ 给文件加锁 ”,为了给文件花式加锁,各路棍子和泥腿子使出了浑身解数,有用flock的,有用redis的,最后连tm基于zk的分布式锁都搬出来了。先说这种基于加锁的方案行不行,按说是没问题的,宗旨就是“ 又不是不能用 ”。但是毕竟还是觉得稍微蠢了点儿,假如这是要在高IO的环境中,难道所有读取进程或线程都要等写进程解锁?真的是给阎王爷推销保健品 --- 糊弄鬼呢。 实际上这个问题本身也不是个问题。不卖关子了,老李先说下最佳方案:进程B在将json内容写文件的时候,先写到一个临时文件中假设名字为temp.json,然后直接利用rename调用rename系统调用将temp.json更改名称为目标文件名称即可。 部分人有没有产生一种吃了苍蝇屎一样的赶脚? ![](https://ti-node.com/static/upload/PNP/a/img_64.png#width-full) 是的,就这,就这就完美解决了「单个进程写多个进程读」瞬间过程中数据完整性的问题。这个问题整体隶属于文件系统,但是聊文件系统(FS)就有点儿太tm扯了,毕竟这玩意没人看,关键是我也不怎么懂想写都没得写,但是解释个皮毛现象还是可以的。实际上在OS中,磁盘这种物理实体是通过文件系统(FS)实现了系统抽象,在Linux下,磁盘基本上被抽象成了很多部分,其中比较重要的三个部分分别是「超级块」、「i节点」、「数据块」,其中超级块是存储文件系统(FS)自身信息的一块区域,不属于本文我们需要关注的地方,我们需要关注「i节点」和「数据块」: - i节点:包含了大量节点信息、文件属性、所有者、可执行者等等信息 - 数据块:文件数据真正存放的区域,这块儿区域一般说来并不是连续的 同时,在Linux中实际上文件名都是障眼法,真正起作用的是一个叫做i-node号的玩意,多个文件名可以对应同一个i-node号,Linux是先根据文件名获取到其对应的i-node号,然后根据i-node号就可以在「i节点」区域找到node节点相关信息,继而就能找到文件内容所在「数据块」区域。 真正完整的内容参考APUE第91页至95页,大概是这样shai儿的: ![](https://ti-node.com/static/upload/PNP/a/img_65.png#width-full) 举个例子,我们touch一个临时文件叫做rule.json.temp,然后目标文件为rule.json,进程B将向rule.json.temp中写入新的内容然后利用rename(命令行命令为mv)将其重新命名为rule.json以供进程A来读取并解析其中的json数据并保证数据的完整性。这其中,最重要的一个要点就是:rename系统调用本身保证了原子性。也就是说在rule.json.temp向rule.json改名的过程中,rename操作不会被打断,不会允许进程读这个文件,rename的原子性才是解决问题的根本所在,而rename这个操作本身又是一个非常迅速的操作。这个过程在Redis的RDB快照文件生成过程中就被应用了。不过,最后值得注意的一点是:rename并不能保证跨分区跨文件系统中的成功概率。 最后推荐大家补充一下关于Linux文件系统的相关知识点,相信各位都擅长使用搜索引擎以及优质的提问或搜索方式。补充下上次感受到「APUE满满恶意」时候的那篇文章:《老李大战PHP之file_put_contents》。 我每次觉得自己读懂APUE的时候,他总是会肆无忌惮在任意时间和地点狠狠地打我一次脸。「如果你觉得你已经读懂了APUE,那你一定是读错了」