🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 落盘 ![](https://images.unsplash.com/photo-1572789109224-a991228f2ac9?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&dl=zhao-chen-UwnPJSIF33U-unsplash.jpg) ![](https://images.unsplash.com/photo-1562414962-a6b4f966070d?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&dl=markus-spiske-5yEiCUynJ9w-unsplash.jpg) ``` write('1', $file); write('2', $file); write_log('ok'); write 2 时突然断电,write_log 没成功,就认为是失败的,只有 write_log 成功 才算是事务的提交,表示写入的 1 2 数据 被成功 永久的写入到磁盘或其它存储设备了(持久化)。 注意,应用层同步写,但在操作系统底层,乃至硬件底层不一定同步的,可能存在缓刷盘,所以 write_log 一定要是 操作系统级别和硬件级别的同步刷盘,只有这样才能保证可靠。 并且还要考虑所使用的编程语言层实现,所以使用越低级的语言就能最大限度,甚至硬件级别的去控制数据的处理,这也体现了 “封装会泄露” 的概念。 程序并不是作为一个整体(所有代码并不是原子性的),让CPU独立时间片串行执行的(一次执行一个独立的程序,所有代码为一个整体),而是被操作系统“大卸八块”来调度执行的,对应用层来说也可以简单的理解成代码是从上到下一行一行执行的,所有代码最后都是一个一个的系统调用,这些调用的顺序,时间我们无法控制,取决于系统调度和IO情况,这个过程可能有多个程序在被这样处理(只是他们不知道彼此,以为cpu是自己专属的一样 —— CPU 是中央空调,且保密工作做的好),所以对应层用来说,每一行代码都可能和不同的进程、程序 里面某个系统调用(某行代码)抢夺系统资源(网络,文件,IO),在这种情况下,编程开始变得复杂,并且开始产生了 事务、并发编程、锁等概念。 程序的这种执行机制确实使得CPU利用率更高,毕竟没人愿意使用非批处理计算机。 编程之所以会是这样,是因为底层平台是这么设计的,如果换做另一种完全不同的平台,那么编程的概念可能又是另一种截然不同的光景了。 ``` 数据只有落盘成功了,才算是持久化了,我们调用保存文件函数返回也成功了,此时文件一定安全的保存好了吗,如果调用返回后立即断电呢。 几乎所有的写入都被 应用软件(db/nosql)做了封装,甚至操作系统也有缓存刷盘机制,所以 上游调用并不知道调用后是否真正落盘了,不过通常也并不需要关心(下游可能会缓存并立即返回写入成功,上游假装是成功了就可以,这样应用速度就会快很多),只有这样上游应用才能专注于自己的业务逻辑,除非是做那种对准确性稳定些要求超级高的应用,当然这也是一个取舍的问题,准确性&稳定与性能。 将事情交给其他程序做,自己只关心应用层,这样封装了的好处是屏蔽掉了底层复杂的实现问题,从而让开发变得更简单直观了,所以当我们调用 `error_log`就不需要担心并发写日志是否会错乱的问题了,只要将写的请求发出去就可以心安理得的做其他事情了,`应用层` `php` `c` `操作系统` `驱动底层`,每一层都有封装,最终会按照顺序将内容写入目标文件,至于数据 是不是在调用时就写入的,还是其它时机写入的,这些并不重要,只要最后我们准确的得到了没有错乱的日志就好了。—— **哪有什么的岁月静好,只是有人为你负重前行。** [PHP error\_log 实际运用 - walkingSun - 博客园](https://www.cnblogs.com/followyou/p/46600749ff3894915ff040b50162c645.html) ***** ### 并发写文件 **并发写文件会让文件字节乱掉吗,可能根本不可能**,因为操作系统,甚至磁盘驱动底层都做了序列化(串行)操作,不会允许出现这样的操作,除非深入硬件底层,突破上层封装和驱动,手写驱动控制硬件才能实现这样破坏性的操作。 [多进程同时写一个文件会怎样? - 杨博东的博客 - CSDN博客](https://blog.csdn.net/yangbodong22011/article/details/63064166/) [用读写锁三句代码解决多线程并发写入文件 z - 武胜-阿伟 - 博客园](https://www.cnblogs.com/zeroone/p/6160232.html) ***** ### 扩展 [浅谈mysql事务 - 知乎](https://zhuanlan.zhihu.com/p/52677680) [硬盘太慢!内存太慢!网络太慢!全靠我来拯救](https://mp.weixin.qq.com/s/tf76tik8gs6KGMEIWTbAVQ) > 俗话说,**计算机编程的任何问题,都可以通过增加一个抽象层来解决**,这句话用在我身上就太合适了。 我是缓存(Cache),今天我给大家聊聊我这个抽象层是怎么工作的 [操作系统和Web服务器那点事儿](https://mp.weixin.qq.com/s/-rzyDpckS9CUQblAUac0FQ) > 这其实就是所谓的**zero copy**技术, 从内核角度看,除了把文件从硬盘读出来之外,没有任何的额外copy。 > zero copy技术减少了上下文的切换,避免了数据不断地在用户态和核心态搬运,不需要CPU参与数据的复制,提高了系统性能,在ngnix, apache等web 服务器中都引入了zero copy技术。(另外还有一个 写时复制 技术 也是为了提高系统性能) [缓存更新的套路](https://coolshell.cn/articles/17416.html) [无锁队列的实现](https://coolshell.cn/articles/8239.html) > 对于Retry-Loop,我个人感觉其实和锁什么什么两样。只是这种“锁”的粒度变小了,主要是“锁”HEAD和TAIL这两个关键资源。而不是整个数据结构。 [SFKP • 计算机百科丨存储介质发展史](https://mp.weixin.qq.com/s/G50EpIguF9G5hgS2nEZODg) [假如有人把支付宝存储服务器炸了](https://mp.weixin.qq.com/s/Iipiv5njlPDD8BJMUzr0Pw) [《吊打面试官》系列-缓存雪崩、击穿、穿透](https://mp.weixin.qq.com/s/tyo_pkTvFo-nODCdkE-d2w) [double write buffer,你居然没听过?](https://mp.weixin.qq.com/s/bkoQ9g4cIcFFZBnpVh8ERQ) [玩转 Redis 持久化](https://mp.weixin.qq.com/s/7B2oteX-bpyALQIp-saA3g) > 顺序追加写入文件会很快,但要写或者更新结构化数据就很耗时,所以顺序写的性能损耗可以忽略不计 [硬盘太慢!内存太慢!网络太慢!全靠我来拯救!](https://mp.weixin.qq.com/s/tf76tik8gs6KGMEIWTbAVQ) [漫画:要跳槽?这道缓存设计题你有必要看看!](https://mp.weixin.qq.com/s/kldwdfNUloJHGE43VaFeGg) [事务已提交,数据却丢了,赶紧检查下这个配置!!! | 数据库系列](https://mp.weixin.qq.com/s/-Hx2KKYMEQCcTC-ADEuwVA) [国产数据库崛起史](https://mp.weixin.qq.com/s/h6goLk8qofsYtAC3FNWggg) [我用Rust徒手重写了一个Spark,并把它开源了](https://mp.weixin.qq.com/s/F9mGwxkpYjprx2DWD__nBQ) [【系统架构】缓存关注点——先写DB还是「缓存」?](https://mp.weixin.qq.com/s/Gm7S0a5VN9L57wlry4-t6w) > 可能你会说本地缓存修改失败怎么办?比如重复key啊什么的异常。那你可以反思一下为这种数据为什么可以成功的写进数据库。 > 分布式由于是网络环境,多节点服务,所以可认为所有的一切操作都不可控,都可能会失败,失败不一定是单机程序的问题,而是网络的问题。 [你真的理解零拷贝了吗?](https://mp.weixin.qq.com/s/8J3Hnr7PX7YBX4hbK8oAQQ) [分库分表就能无限扩容吗](https://mp.weixin.qq.com/s/P9pV7jx9zj30YjZ_p0nSAQ) > 或许这是一个架构问题,不应该属于业务范畴,TiDB能彻底解决这个问题吗? [ElasticSearch写入数据的工作原理是什么?](https://mp.weixin.qq.com/s/rw6vmDgXUh0SUUh7uo1APg) [undo log和redo log](https://www.cnblogs.com/shizheyangde/p/7390122.html) > Undo日志记录某数据被修改前的值,可以用来在事务失败时进行rollback;Redo日志记录某数据块被修改后的值,可以用来恢复未写入data file的已成功事务更新的数据。 > tp日志并发,写入文件的系统调用,在系统底层中对文件句柄资源是独占,串行的,每个写入都是原子性的,再写这一句的时候,另一句要等这句写完才能写,不然字节就乱了,就会出现乱码,也就是对文件资源每次写入的字节串是原子性和串行的,只有这样写入文件才不会乱码。 > trace默认传两个参数不会实时写入日志到文件,而是记录到内存,在脚本执行完毕时一次性执行写入到日志文件,这样做的好处是保证了每个请求的日志最终写入顺序是正确的,而不会打乱。所以通常来说我们不用传第三个参数,但如果你有需要,比如你想记录的日志信息只想要单条的便于分析,那么可以传第三个参数: > tp日志其实也考虑到并发了,日志是写入到内存,最后才一次性写入文件的,并不是每次记录实时写入的,这样就规避了并发问题,不然的话就会出现多次请求的日志串联了,这样日志就回错乱了。 ~~~ trace($value, '>my-debug', true); ~~~ [为什么寄存器比内存块?](https://mp.weixin.qq.com/s/QGz_kEs0zyYNdt9sR05q5Q) [一篇文章理解 Web 缓存](https://mp.weixin.qq.com/s/3SDKNbWZHWenzi34TR38gg) [缓存的正确使用方式,你都会了吗?](https://mp.weixin.qq.com/s/pUBa4L1bfF09LgGyq_LSCw) [Python和Java的硬盘夜话](https://mp.weixin.qq.com/s/0z-KbJS3dvNs2XlsvSGVEw) [持久化:Java帝国反击战](https://mp.weixin.qq.com/s/FrRWFaI2X5x9RpPbXoMq9w) [三年之久的 etcd3 数据不一致 bug 分析](https://mp.weixin.qq.com/s/qittYHY2GUwhFtvsRDaIAQ) [降低 80% 的读写响应延迟!我们测评了 etcd 3.4 新特性(内含读写发展史)](https://mp.weixin.qq.com/s/uLntRRW4R9WQ-I-N-mM0yg) [重大事故!IO问题引发线上20台机器同时崩溃](https://mp.weixin.qq.com/s/bpIgifIaoQ7aBtX2zmLXrA) [就为了一个原子操作,其他CPU核心罢工了](https://mp.weixin.qq.com/s?__biz=MzAwNjkxNzgxNg==&mid=2247485772&idx=1&sn=0f89aa0d44ee2c1d0753e43588cca32d&source=41#wechat_redirect) [我一顿操作把电脑弄崩了!!!数据全没了!!!我该怎么办?](https://mp.weixin.qq.com/s/_3zotlzAl_1OrF1zg3ksKg) [昨晚上女友问我,你知道啥是文件吗?于是就有了今天的文章](https://mp.weixin.qq.com/s/NMAYt0mNiVDRM9Ys05WgFw) [MySQL为什么取消了Query Cache?](https://mp.weixin.qq.com/s/4cbtKU2P5f-S8cILpkCpbQ) > MySQL8.0取消查询缓存的另外一个原因是,研究表明,缓存越靠近客户端,获得的好处越大。 [老李大战PHP之file\_put\_contents](https://mp.weixin.qq.com/s/fImYaDiSJDNlBx48bFbEtQ) [来,聊个小问题](https://mp.weixin.qq.com/s/dfyglaSAfLQzoGLREte3aw) ---- 为什么生产测试时第一次api请求快些,每次都是这样,后面会快一些,过一段时间第一次又慢一点,难道有什么东西存活,缓存。 操作系统,数据库,网络,乃至硬件层,为了提高响应速度都有各自的缓存设计,所以这就是为什么第一次明显比后面慢些的原因。 [机械硬盘随机IO慢的超乎你的想象](https://mp.weixin.qq.com/s/qz57uPtFaoQ_5z59NSBEUQ) > 数据库事务:所有的数据库在实现事务的时候,都要保证写数据落盘成功才能返回。但为什么他们 **几乎都是落盘到自己的事务日志文件里去就返回成功的,而不是直接写入到数据表文件里。** 这背后的原因还是磁盘读写性能问题,事务只需要保证数据落地成功就可以,至于写到哪里并不重要。写到数据文件中的话大概率就变成随机IO了。**如果写到一个日志文件中,就是地地道道的顺序IO,性能就发挥到极致。** [write文件一个字节后何时发起写磁盘IO?](https://mp.weixin.qq.com/s/qEsK6X_HwthWUbbMGiydBQ) > 最后我们要认识到,这套write pagecache+回写的机制第一目标是性能,不是保证不丢失我们写入的数据的。如果这时候掉电,脏页时间未超过dirty\_expire\_centisecs的就真的丢了。如果你做的是和钱相关非常重要的业务,必须保证落盘完成才能返回,那么你就可能需要考虑使用fsync。 [read文件一个字节实际会发生多大的磁盘IO?](https://mp.weixin.qq.com/s/LcuWAg10hxZjCoyR1cMJSQ) > 操作系统的本意是做到让你简单可依赖, 让你尽量把它当成一个黑盒。 [理解格式化原理](https://mp.weixin.qq.com/s/DobymgQ-TRXrO32wjf2fWQ) > 比如oracle就是绕开操作系统直接使用裸设备的。**但是这个时候你就无法利用Linux文件系统里为你封装好的inode、block组成的文件与目录了,开发工作量会增加。** ~~~ 上传 模板文件的过程中,tp可能生成这一半 残缺 不完整的 模板缓存文件 [笑哭],所以 原子性 还是很必要的啊,极端情况也还是很容易出现的 ~~~ ----