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

142 天前
 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

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

11034 次点击
所在节点    程序员
133 条回复
hefish
141 天前
1 、两路供电;
2 、搞个大点的 UPS
3 、定期有计划地维护 UPS 电池
me1onsoda
141 天前
@comlewin 不懂就问,这些供电能做到断电瞬间无缝衔接吗?
aieruishi
141 天前
@wxf666 窗口期可以缩短,但是无法避免。 攒批是常用的技术手段之一,代价多少取决于如何实现。软件上目前很难保证这一点。

redpanda 就吐槽 Kafka 不开 fsync
https://www.redpanda.com/blog/why-fsync-is-needed-for-data-safety-in-kafka-or-non-byzantine-protocols

大致意思是:在 Kafka 或其他非拜占庭( Non-Byzantine )分布式协议中,fsync 是保证数据安全性的关键机制,即使系统设计上采用了多副本、持久化存储或高可用策略,仍然需要依赖 fsync 来确保数据真正落盘,避免因操作系统缓存、硬件故障或断电导致数据丢失。
acorngyl
141 天前
不考虑机房基建的情况。
感觉 OP 的问题两方面看,一个是单个数据库系统,一个是业务层面。

单数据库,只要业务 commit 了,commit 会写入日志,日志会秒级回写,只要 commit 的日志回写了,数据的事物就算提交了。即便这时电脑崩了,做实例恢复,日志里的事物都能做回来。如果日志都没回写,那肯定业务就丢了。这个没办法避免,除非事物提交强制回写,而且等待。这样系统的响应时间就得是秒级了。

业务层面。首先,越重要的系统,业务流程要越短、越简单。如果业务复杂,最后一定要有个落单系统,业务完成以落单为准。每个稽核账期结束前,所有系统要和落单系统对账,落单系统失败或者没有的业务,其他系统要做回滚操作。这就是充值缴费或者订票,偶尔会有退费的情况(现在很少了)。银行的交易系统和其他业务都是隔离的,交易系统甚至只做 insert ,账单是最后算出来的。
xuanbg
141 天前
一个 UPS 搞定,想太多没用
dode
141 天前
数据顺序写入日志很快,写入完成后作为成功标志返回响应,再写入实际系统内
clickhouse 好像是直接全部都写入一些小文件,再合并,最终稳定存储
wxf666
141 天前
@aieruishi 你们说的『数据丢失』,包括『事务结束后,数据无法持久』吗?

感觉从题主描述来看,是包括的?

但个人认为,数据一致性要求极高的地方,就该攒批落盘数据后,这堆事务再批量返回结果。。

调用方线程被阻塞太多的话,应改用协程等方式实现。。
dode
141 天前
操作系统内核接口很多都是原子调用,例如 fsync ,调用后肯定是成功了,调用失败就不会返回
wxf666
141 天前
@acorngyl 为啥不能做到,落盘日志,commit 才结束?

难道 SSD 落盘 1MB 数据,延迟要几秒钟吗?

否则为啥不能积攒几十上百个事务的脏页数据/日志,批量顺序落盘,再 commit 结束,批量返回事务结果呢?
wtks1
141 天前
与其搞系统层的东西,不如改造供电,把 UPS 和应急发电机都准备起来
tinydancer
141 天前
@me1onsoda 是的,毫秒级的切换时间,能够保证服务器不掉电
min
141 天前
不需要无缝,有电容、电池、ups 可以保证备用线路有足够时间跟上来
kiracyan
141 天前
正规机房都有应急电源
robinchina
141 天前
@Richared 对不起,看到园区脑子里的画面就变成了四面环山,丛林茂密,保安都拿着 AK47·······
zfzrx
141 天前
金融数据 基本都是双路市电 双 ups 双柴油机
weirdte
141 天前
选择一家商用的 oltp 数据库都能够保证数据不丢失(这里说的不丢失,不包含某些超大规模的自然灾害,比如地球爆炸)。 可以了解下数据库的 RPO 指标,商用数据库该指标一般都要求是 0 ,即使单个机房地震摧毁了一样能保证你数据不丢失。 性能在可靠性面前是一定要做出牺牲的。 你如果要自己维护一套高性能的数据库系统,那至少也得有上百人的团队,金融系统的数据库飞掉是不可接受的,凭几个开发根本兜不住底,建议还是采购成熟的商用 db 。
julyclyde
141 天前
异地不是用来应付断电的
而是应付地震损毁之类的事故的
weirdte
141 天前
什么时候返回成功和 fsync 前后没有必然关系, 返回成功一定是在数据落盘之后再返回成功(不调用 fsync 数据也会落盘)。一般数据库做法是记录当前数据落盘点(通常叫 log sequence number LSN ,或者 WAL id 这种),请求跟踪这个 LSN ,flushed LSN 已经大于我当前请求产生的写操作的 LSN 时就说明数据已经持久化了,可以告诉客户端完成了。 分布式中,这个日志是要同步给其他节点的, 那 global Flushed LSN 应该取节点多数派都已大于的某个 flush lsn
weirdte
141 天前
@weirdte “ 返回成功一定是在数据落盘之后再返回成功” => 返回成功一定是数据达成多数派一致的时候再返回成功。

返回失败不一定是真的失败(可能网络原因导致没有收到成功的结果),但返回成功是一定要成功的。
scegg
141 天前
@wxf666 在企业应用里,一般都是有存储卡或者 HBA ,并没有这个需求。在家用环境搞这个可能没有人要买单。
企业方案里,首先 SSD 本身就可以做分层设计,部分 SSD 就是拿来做写入缓存的,并不需要等待。在写入写入缓存 SSD 之前的那些数据,放在内存中的部分,内存本身有防掉电保护。
在家用环境(比如 NAS )倒是有类似的功能,使用 SSD 做写入缓存,给 HDD 的 RAID 攒事务。
另外,您自己也提到了,SSD 的顺序写入才会有累积效果,但更新一般不会变成顺序写入,而是一大堆随机事务。所以攒事务之后,也只是一个 cache 的效果。

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

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

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

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

© 2021 V2EX