高频金融系统如何防止突然断电导致的数据丢失?

138 天前
 latifrons

我知道 MySQL ,RocksDB 等数据库其实都有 WAL ,但同样地都依赖操作系统定期将内存缓存中的数据通过 fsync()刷回磁盘。如果此时断电(或者操作系统崩溃),1 秒内的数据可能会丢失。

MySQL:innodb_flush_log_at_trx_commit

https://dba.stackexchange.com/questions/12611/is-it-safe-to-use-innodb-flush-log-at-trx-commit-2

The default value of 1 is required for full ACID compliance. You can achieve better performance by setting the value different from 1, but then you can lose up to one second worth of transactions in a crash. With a value of 0, any mysqld process crash can erase the last second of transactions. With a value of 2, only an operating system crash or a power outage can erase the last second of transactions. InnoDB's crash recovery works regardless of the value.

所以似乎为了数据完备性,innodb_flush_log_at_trx_commit=1 是不可避免的,从而会导致比较严重的性能劣势。

例如 LevelDB ,开启 WriteOptions(Sync=true)后,tps 从 190000/s 骤降为 1200/s.

Qwen3 的一个回答: https://chat.qwen.ai/s/0e7d9977-4400-41da-883f-2972893104cf?fev=0.0.85

想请教一下大家,在对数据完备性要求极高的场景下,大家是怎么优化性能的?

10995 次点击
所在节点    程序员
133 条回复
littlepigpeppa
137 天前
这么思考的话无解,不如退而求其次的去保证不断电吧
lscho
137 天前
很久之前就考虑过类似的问题,得出的结论和楼上诸位大佬的观点差不多。

非要从技术方面解决断电问题,性能下降极其严重,成本无法接受。
不如从工程方面解决断电问题,保证正常情况下不断电。然后不可抗力情况(地震等)下可以通过人力恢复即可。
030
137 天前
金融的研发都是这种水平吗
gaxila
137 天前
我理解楼主的担忧, 这个是无法做到完美的, 就算落盘了, 磁盘也可能有坏道等情况发生. 这里其实是一种取舍, 为了小于 1%的场景去牺牲 100%场景的性能不值得, 所以不如接受这种小概率事件, 再引入对账来检测出小概率事件
min
137 天前
电的问题#5 已经说了
软件的问题应该去看看常见的分布式存储和分布式数据库的解决方案
itskingname
137 天前
CAP 理论指出,一个分布式系统不可能同时满足一致性( Consistency )、可用性( Availability )和分区容错性( Partition Tolerance )这三个特性,最多只能同时满足其中的两个。
pkoukk
137 天前
性能劣势怎么了?都玩高频金融了,上高配物理机啊,我们这虽然不是搞金融的,但是强一致性要求的就是拿物理机硬顶的。世界上没有完美的东西,你只能 trade off ,在金融领域,花钱恐怕是最容易解决的问题吧
elltor
137 天前
UPS ,柴油发电机,多 AZ ,多副本备份....
XingWu
137 天前
碰巧我就在金融行业,大家说的是对的,确实就是
技术层面:同城容灾 异地多活
非技术层面:24 小时不间断有人值守+UPS+柴油发电
UPS 可以给机房供电 2 小时,大楼里就有柴油和发电机,再保障 5-6 个小时的核心生产用电不是问题,所以停电导致的问题不大
至于 fsync()的问题,不是后端,就不乱说以免哄堂大笑了
dynastysea
137 天前
谁告诉你 mysql 会都数据的?第一句话就是错的
xxx88xxx
137 天前
金融系统没接触过,但地铁里面管钱的系统( AFC)我知道,在设计时,安装了超级电容,在检查到断电的一瞬间,保证最后一笔交易上传。
mmdsun
137 天前
如果你的提问是这个标题,那考虑底层的是思路完全不对的... 系统设计中的本质问题,不同层级对“数据完整性”的保障边界不同,如果忽视这个事实,就会走偏方向,甚至产生错误的“安全感”。

即使操作系统可以保证,他也是保证自己的文件系统的完整性,而不是保证你 mysql 甚至应用层丢不丢数据的问题。即使是 tcp 协议可以保证绝对丢消息,你的应用层还好做消息确认这种机制的。

数据一致性的保障是“自上而下”理解,而非只盯着底层。操作系统、文件系统、数据库等底层组件的“保证”,无法等价为业务层金融场景“不会丢数据”。
所以根本上,你需要在应用层当事务出现异常时做处理。
neoblackcap
137 天前
@latifrons 退一步,fsync()成功也不代表落盘成功。fsync 成功了,顶天是 OS 把自己系统缓存刷写到了磁盘设备那边去。数据很有可能还存在磁盘控制器的缓存中而没有被完全落盘。但是磁盘控制器已经响应 OS 了 fsync()成功了
wxf666
137 天前
@scegg 数据库能否根据 SSD 『不同块大小顺序写入 - 延迟』关系,等待一段时间,积累更多写入事务,再一次性刷到 SSD 上,实现数据严格一致性的同时,性能影响降到最小呢?

比如,如果发现 SSD 顺序写入 1MB 时,延迟 100 μs ,那每次攒够 256 个事务(假设每事务写入 4KB 页),再一次性落盘,这样总体延迟不高(平均每事务延迟 50 μs ),数据一致性也能得到保证?
noogler67
137 天前
只要购买尊重 fsync 的硬件就行。至于性能,可以用批量操作。用户发送 1000 条 sql ,只要互相不干扰,db 都批量接收以后发送 fsync 给硬件。硬件批量处理完以后返回 ok 。这样就是延迟大一点,可以是几十几百 ms 。
关键点只要硬件保证收到 fsync ,数据落盘,返回 ok 的时序。就行。
messaround
137 天前
总结下来就是 这个逻辑没有考虑
abcbuzhiming
137 天前
搞高频金融系统的人,可以为了几毫秒的差距把一座山打穿拉光纤,分布式系统这种延时很大的东西,直接在高频金融系统里用,我个人是怀疑的,用于数据冷备差不多。

我觉得楼主考虑的方向不对,高频金融系统人机就不会考虑意外断电问题,除非发生能让交易中心断电的大事件
aieruishi
137 天前
我尝试回答下该问题,下面仅是个人意见。

1. 调整 fsync 频率与事务持久化的权衡,如缩短 fsync 的间隔(如从默认的 1 秒改为 100ms ),可以减少数据丢失的窗口期,但会牺牲一定的吞吐量。
2. 将 WAL 文件放在持久内存( PMEM 设备)上,每次写入都 fsync ,延迟是非常低的,但 PM 厂商不继续生产了。
3. XFS 文件系统可以开启 data=journal 模式能保护数据,但性能代价极高,通常仅用于特殊场景。
4. 减少脏页在内存中的停留时间或者降低脏页触发刷盘的阈值。
5. [楼上提到] 机房/服务器在硬件上双路电源 + UPS ;服务上支持同城多活等

如果还有其他,也欢迎各位进行补充。

另外回到提到的就是,性能和数据不丢失权衡,没有完美的解决方案。在数据中心中,数据存储就算数据落盘我们也没办法保证数据永远不丢,经常会遇到磁盘掉盘,颗粒(或扇区)损坏导致数据静默错误,还是需要在硬件上层处理尽量保证数据不丢。举个例子,AWS S3 设计为默认提供 99.999999999%( 11 个 9 )的数据持久性,也不会保证 100%。
Gilfoyle26
137 天前
数据不是一份,是 3 份,甚至是 5 份。
wxf666
137 天前
@aieruishi

关于第一点,如果数据库能做到 54 楼说的那样,是否能消除『数据丢失的窗口期』呢?毕竟是批量落盘后再返回事务结果的?(这应该是数据库要实现的?)

第二点,还是 54 楼说的,应该没必要每次事务都单独刷盘吧。。等一小会儿,积攒多些事务数据后,再批量落盘,总体更划算?代价就是每个事务延迟大一点点。。但高频系统,要短时间内攒够足够多的事务,轻而易举吧。。

这和你说的第四点是类似的,但应该是脏页在内存中停留时间增大一些?攒够一堆脏页再批量写盘?

当然,上面这些都是软件层面的,硬件不可靠,软件再完善也没法力挽狂澜。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1128883

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX