## 落盘
![](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可能生成这一半 残缺 不完整的 模板缓存文件 [笑哭],所以 原子性 还是很必要的啊,极端情况也还是很容易出现的
~~~
----
- 开始
- 公益
- 更好的使用看云
- 推荐书单
- 优秀资源整理
- 技术文章写作规范
- SublimeText - 编码利器
- PSR-0/PSR-4命名标准
- php的多进程实验分析
- 高级PHP
- 进程
- 信号
- 事件
- IO模型
- 同步、异步
- socket
- Swoole
- PHP扩展
- Composer
- easyswoole
- php多线程
- 守护程序
- 文件锁
- s-socket
- aphp
- 队列&并发
- 队列
- 讲个故事
- 如何最大效率的问题
- 访问式的web服务(一)
- 访问式的web服务(二)
- 请求
- 浏览器访问阻塞问题
- Swoole
- 你必须理解的计算机核心概念 - 码农翻身
- CPU阿甘 - 码农翻身
- 异步通知,那我要怎么通知你啊?
- 实时操作系统
- 深入实时 Linux
- Redis 实现队列
- redis与队列
- 定时-时钟-阻塞
- 计算机的生命
- 多进程/多线程
- 进程通信
- 拜占庭将军问题深入探讨
- JAVA CAS原理深度分析
- 队列的思考
- 走进并发的世界
- 锁
- 事务笔记
- 并发问题带来的后果
- 为什么说乐观锁是安全的
- 内存锁与内存事务 - 刘小兵2014
- 加锁还是不加锁,这是一个问题 - 码农翻身
- 编程世界的那把锁 - 码农翻身
- 如何保证万无一失
- 传统事务与柔性事务
- 大白话搞懂什么是同步/异步/阻塞/非阻塞
- redis实现锁
- 浅谈mysql事务
- PHP异常
- php错误
- 文件加载
- 路由与伪静态
- URL模式之分析
- 字符串处理
- 正则表达式
- 数组合并与+
- 文件上传
- 常用验证与过滤
- 记录
- 趣图
- foreach需要注意的问题
- Discuz!笔记
- 程序设计思维
- 抽象与具体
- 配置
- 关于如何学习的思考
- 编程思维
- 谈编程
- 如何安全的修改对象
- 临时
- 临时笔记
- 透过问题看本质
- 程序后门
- 边界检查
- session
- 安全
- 王垠
- 第三方数据接口
- 验证码问题
- 还是少不了虚拟机
- 程序员如何谈恋爱
- 程序员为什么要一直改BUG,为什么不能一次性把代码写好?
- 碎碎念
- 算法
- 实用代码
- 相对私密与绝对私密
- 学习目标
- 随记
- 编程小知识
- foo
- 落盘
- URL编码的思考
- 字符编码
- Elasticsearch
- TCP-IP协议
- 碎碎念2
- Grafana
- EFK、ELK
- RPC
- 依赖注入
- 开发笔记
- 经纬度格式转换
- php时区问题
- 解决本地开发时调用远程AIP跨域问题
- 后期静态绑定
- 谈tp的跳转提示页面
- 无限分类问题
- 生成微缩图
- MVC名词
- MVC架构
- 也许模块不是唯一的答案
- 哈希算法
- 开发后台
- 软件设计架构
- mysql表字段设计
- 上传表如何设计
- 二开心得
- awesomes-tables
- 安全的代码部署
- 微信开发笔记
- 账户授权相关
- 小程序获取是否关注其公众号
- 支付相关
- 提交订单
- 微信支付笔记
- 支付接口笔记
- 支付中心开发
- 下单与支付
- 支付流程设计
- 订单与支付设计
- 敏感操作验证
- 排序设计
- 代码的运行环境
- 搜索关键字的显示处理
- 接口异步更新ip信息
- 图片处理
- 项目搭建
- 阅读文档的新方式
- mysql_insert_id并发问题思考
- 行锁注意事项
- 细节注意
- 如何处理用户的输入
- 不可见的字符
- 抽奖
- 时间处理
- 应用开发实战
- python 学习记录
- Scrapy 教程
- Playwright 教程
- stealth.min.js
- Selenium 教程
- requests 教程
- pyautogui 教程
- Flask 教程
- PyInstaller 教程
- 蜘蛛
- python 文档相似度验证
- thinkphp5.0数据库与模型的研究
- workerman进程管理
- workerman网络分析
- java学习记录
- docker
- 笔记
- kubernetes
- Kubernetes
- PaddlePaddle
- composer
- oneinstack
- 人工智能 AI
- 京东
- pc_detailpage_wareBusiness
- doc
- 电商网站设计
- iwebshop
- 商品规格分析
- 商品属性分析
- tpshop
- 商品规格分析
- 商品属性分析
- 电商表设计
- 设计记录
- 优惠券
- 生成唯一订单号
- 购物车技术
- 分类与类型
- 微信登录与绑定
- 京东到家库存系统架构设计
- crmeb
- 命名规范
- Nginx https配置
- 关于人工智能
- 从人的思考方式到二叉树
- 架构
- 今日有感
- 文章保存
- 安全背后: 浏览器是如何校验证书的
- 避不开的分布式事务
- devops自动化运维、部署、测试的最后一公里 —— ApiFox 云时代的接口管理工具
- 找到自己今生要做的事
- 自动化生活
- 开源与浆果
- Apifox: API 接口自动化测试指南