V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
latifrons
V2EX  ›  程序员

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

  •  1
     
  •   latifrons · 2025 年 4 月 29 日 · 11783 次点击
    这是一个创建于 260 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我知道 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

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

    第 1 条附言  ·  2025 年 4 月 29 日
    感谢大家的回复,可能是我没有表述清楚。

    我的核心 concern 不是怎么防止掉电,而是在一个分布式系统中,如果各业务系统在 fsync()前就返回业务成功,无法保证系统间数据一致性;如果调用 fsync()后再返回业务成功,无法保证性能。

    操作系统有文件缓存,但 kernel 会崩。
    磁盘有写入缓存,但磁盘也会掉电。

    基于此,我是应该假设 fsync() 一定会发生,还是手动去 fsync()?每次强制 fsync() 性能太差,无法接受。

    感谢 @scegg 提供 DB2 思路,也希望听听业界的具体实践。
    第 2 条附言  ·  2025 年 4 月 30 日
    听了大家说了这么多,收获颇丰,感谢大家。

    其实这个问题在我这里产生的根源就是在分布式系统中。单体状态自己说了算,灾难恢复回来是什么就是什么。而分布式系统就需要考虑一致性了。

    TCC 分布式事务环境下,正如 @weirdte 所说,“返回失败不一定是真的失败,但返回成功是一定要成功的”。 如果被调用方返回成功,但结果却因未落盘而回滚,调用方根本不会知道有这么个回滚节点。回滚节点也不知道有什么应该做而没做的事。

    事后对账当然是一个办法,但很多时候对账并不能挽回损失。例如扣减余额这种事如果回滚,肯定要有人背锅了。

    似乎解决方法就是双写/强制落盘,不知道例如银行、券商这样的系统,对于涉及钱的跨系统的一致性,除了对账,在技术上是如何实践的呢?又如果性能要求极其苛刻,有什么更好的优化方案?

    又从业务角度而言,问题归结为:防止数据回滚,是不是应该成为每一个程序员在开发分布式系统时必须考虑的标准设计规范,还是,程序员不用管,交给 DBA ?
    133 条回复    2025-05-10 11:39:29 +08:00
    1  2  
    zgsi
        1
    zgsi  
       2025 年 4 月 29 日
    应急电源啊
    nekoneko
        2
    nekoneko  
       2025 年 4 月 29 日   ❤️ 1
    UPS 保平安
    x86
        3
    x86  
       2025 年 4 月 29 日
    金融系统连 UPS 都没一个吗?
    ghostwind
        4
    ghostwind  
       2025 年 4 月 29 日
    看你是上游还是下游,如果是下游,可以起一个重发的信号
    ghostwind
        5
    ghostwind  
       2025 年 4 月 29 日   ❤️ 5
    如果是交易所,比如是上交所 ,你可以去搜索上交所 ups 电源 结果就是:UPS+柴发

    证券技术大厦共 10 层,其中地上 8 层,可提供超过 6000 平米的托管机房,采用双路独立的市政电源作为常用电源,配备了 2N 的 UPS 及 N+1 冗余柴发作为备用电源。
    opengps
        6
    opengps  
       2025 年 4 月 29 日
    银行都是异地多活,多可用区(独立供网供电,独立 ups 电源)。内存都已经可以当硬盘用
    jvee
        7
    jvee  
       2025 年 4 月 29 日
    双路电源+ups+同城、异地灾备
    scegg
        8
    scegg  
       2025 年 4 月 29 日
    因为突然断电可能不只是导致数据丢失,不少问题很难快速恢复。
    所以不如防止突然断电。
    scegg
        9
    scegg  
       2025 年 4 月 29 日
    为了实现一个目标,不可能不需要付出其他代价。不然这个目标早就成为标准了。
    当需要付出代价的时候,就要看是否值得。
    在这个例子上,保证不突然断电就是代价最低的办法。
    julyclyde
        10
    julyclyde  
       2025 年 4 月 29 日
    @scegg 根本两码事
    你这是解决不了问题就直接不承认问题存在啊
    latifrons
        11
    latifrons  
    OP
       2025 年 4 月 29 日
    UPS 肯定能解决一部分问题,剩下的例如操作系统内核崩溃这种 UPS 无法解决的问题,似乎还有风险。
    核心 concern 是 fsync()没执行
    scegg
        12
    scegg  
       2025 年 4 月 29 日   ❤️ 4
    @julyclyde 问题不存在的原因是这个问题不需要被解决。
    任何保障“安全性”的设计都会带来“性能”损失。如果为了一个能用更小的代价(解决供电稳定性)来解决“安全性”问题,就不需要因此牺牲“性能”。

    如何解决吃垃圾会中毒的问题?那就别吃垃圾。
    ivvei
        13
    ivvei  
       2025 年 4 月 29 日 via Android   ❤️ 3
    高频?多高? 都还在用数据库,那估计也高不到哪里去,那么完全可以先写入再确认嘛。没写入的就当没发过。这是上游的做法。如果是下游的话,找上游要一份最新的快照就行,反正以人家的为准
    scegg
        14
    scegg  
       2025 年 4 月 29 日
    @latifrons 如果要解决系统级(包括硬件和软件)问题,可以考虑 FT 服务器或者支持 FT 的其他设计(比如 vmware 的 FT )。
    julyclyde
        15
    julyclyde  
       2025 年 4 月 29 日
    @scegg 那你看看哪个系统敢于“只要上了 UPS 就不需要写日志”的?
    comlewin
        16
    comlewin  
       2025 年 4 月 29 日
    金融核心系统不会存在断电的情况,双路电,UPS 电池,柴发,同城这些都是硬性要求
    seers
        17
    seers  
       2025 年 4 月 29 日 via Android   ❤️ 1
    db2 可以使用 dio 直接写盘跳过系统的缓存层
    scegg
        18
    scegg  
       2025 年 4 月 29 日   ❤️ 3
    @julyclyde 你认为的日志是为了防止掉电设计的吗。
    latifrons
        19
    latifrons  
    OP
       2025 年 4 月 29 日
    @ivvei 数据总要有地方落盘,落盘就有你落了我没落的情况发生。
    假设一个 TCC 事务,被调用方反馈说我做完了,调用方因此完成了这次 TCC ,但此时被调用方突然崩了,数据没落盘,TCC 事务看似做完了实则没做完。
    但你要被调用方落盘吧,性能又差了……
    scegg
        20
    scegg  
       2025 年 4 月 29 日   ❤️ 2
    @seers 对的。但无法跳过硬盘的缓存。因为不需要。db2 的 dio 就是因为操作系统的内存中的缓存可能不受保护。但原因可能不是因为电力,而是包括电力在内的更多原因(例如系统崩溃、大型机的背板故障之类)。
    服务器用的 RAID 系统,缓存自己就带电池,或者是 FBWC 这种掉电不会丢数据的设计。
    nxforce
        21
    nxforce  
       2025 年 4 月 29 日
    一切软件或者 OS 层面的措施都不如物理防御。

    直接上 UPS+柴油发电机。简单暴力可靠。
    scegg
        22
    scegg  
       2025 年 4 月 29 日
    @latifrons 根据业务对“数据一致性”的要求,必要时牺牲性能的方法包括但不限于分布式事务,或其等价的逻辑层实现。
    latifrons
        23
    latifrons  
    OP
       2025 年 4 月 29 日
    @comlewin 可能是我没表述清楚,我的核心 concern 是落盘 fsync()失败,原因可能会有很多,掉电只是其中之一。
    scegg
        24
    scegg  
       2025 年 4 月 29 日
    @latifrons 如果是担心数据一致性的问题,考虑分布式事务或其等价的逻辑实现方案。如果不能接受其性能开销,考虑硬件冗余机制(包括电力、硬件 FT 或虚拟化 FT )。
    crc8
        25
    crc8  
       2025 年 4 月 29 日
    世界的核心不是石油,就是电磁波。
    woodfizky
        26
    woodfizky  
       2025 年 4 月 29 日
    有些技术的牛角尖可以不用钻那么深,有些事情可以不用技术的思路而是用工程的思路去解决。
    怕断电,那就保证不要断电就行了。怕机房爆炸,那增设若干套冗余异地系统和线路就好了。

    真的遇上事,服务断了就断了吧,比如机房都被炸了,就没必要想过多技术问题了。
    picone
        27
    picone  
       2025 年 4 月 29 日
    分布式系统的 CAP 定理,只能折中。
    viking602
        28
    viking602  
       2025 年 4 月 29 日
    同城容灾 异地多活 多可用区 多云 自建机房那就是 UPS 柴发拉满 多演练 保证不断电到电才是硬道理
    Cruzz
        29
    Cruzz  
       2025 年 4 月 29 日
    第一家工作电商公司,在一个园区里,一共 7 层,2-3-4 楼是机房,还有两个异地机房。然后 ups+发电机。有一次园区停电,十分钟发电机就顶上了。三台车,在楼下发了两天。别的单位都在摸鱼,只有我们在上班,领导开玩笑,我就说要把机房搬走,如果要从系统层面想招,那么离世界末日不远了。
    kkk1234567
        30
    kkk1234567  
       2025 年 4 月 29 日
    机器上配置电容卡,供电电路加 UPS ,机房再弄个柴发
    dem0ns
        31
    dem0ns  
       2025 年 4 月 29 日
    别人问的是断电数据丢失,都说用 UPS...... 这玩意儿都是标配好吧,几地几中心也是等保强制要求。
    midsolo
        32
    midsolo  
       2025 年 4 月 29 日   ❤️ 1
    我再补充一下,可以使用 RAID 多磁盘冗余阵列技术,RAID 卡自带了 SDRAM 缓存,还可以配置独立的锂电池或电容,就算服务器掉电了,也可以把服务器缓存中的数据写入到磁盘。
    ivvei
        33
    ivvei  
       2025 年 4 月 29 日 via Android
    @latifrons 落盘了再说做完了。落盘是必要时间,是事务的一部分。
    shiny
        34
    shiny  
    PRO
       2025 年 4 月 29 日
    哪怕没有发电机,UPS 断电时候可以设置向系统发送关机信号。可以避免一些突然断电的故障。
    bli22ard
        35
    bli22ard  
       2025 年 4 月 29 日
    代码层面,没办法保证断电不丢数据,只能保证断电数据一致性
    ethsol
        36
    ethsol  
       2025 年 4 月 29 日
    用 Oracle 就不用系统管理磁盘,lvm 管理磁盘,redolog 放在高速 ssd 上基本能最大限度规避断电问题
    pingdog
        37
    pingdog  
       2025 年 4 月 29 日
    了解下 Oracle RAC ,集群多写多读,这也是 Oracle 能主宰数十年的原因,只要应用层面写好 try catch ,数据 99.99%可写入,除非数据阵列挂了
    Jinnrry
        38
    Jinnrry  
       2025 年 4 月 29 日 via iPhone   ❤️ 3
    你是研发还是 dba ?如果你是研发,直接找你们 dba ,他们有现成方案。如果你是 dba ,你连这都不知道,趁早收拾东西走人
    bearbest
        39
    bearbest  
    PRO
       2025 年 4 月 29 日
    这已经不是技术问题了,这是系统问题。
    断电造成的后果,不是一个数据库技术上处理就能解决的问题。
    感觉有点程序员思维了。
    yc8332
        40
    yc8332  
       2025 年 4 月 29 日
    这是工程问题。。正常都是有 ups 的不断电系统的。。
    littlepigpeppa
        41
    littlepigpeppa  
       2025 年 4 月 29 日
    这么思考的话无解,不如退而求其次的去保证不断电吧
    lscho
        42
    lscho  
       2025 年 4 月 29 日
    很久之前就考虑过类似的问题,得出的结论和楼上诸位大佬的观点差不多。

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

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

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

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

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

    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
        59
    Gilfoyle26  
       2025 年 4 月 30 日
    数据不是一份,是 3 份,甚至是 5 份。
    wxf666
        60
    wxf666  
       2025 年 4 月 30 日
    @aieruishi

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

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

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

    当然,上面这些都是软件层面的,硬件不可靠,软件再完善也没法力挽狂澜。。
    hefish
        61
    hefish  
       2025 年 4 月 30 日
    1 、两路供电;
    2 、搞个大点的 UPS
    3 、定期有计划地维护 UPS 电池
    me1onsoda
        62
    me1onsoda  
       2025 年 4 月 30 日
    @comlewin 不懂就问,这些供电能做到断电瞬间无缝衔接吗?
    aieruishi
        63
    aieruishi  
       2025 年 4 月 30 日
    @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 来确保数据真正落盘,避免因操作系统缓存、硬件故障或断电导致数据丢失。
    akorn
        64
    akorn  
       2025 年 4 月 30 日   ❤️ 1
    不考虑机房基建的情况。
    感觉 OP 的问题两方面看,一个是单个数据库系统,一个是业务层面。

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

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

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

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

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

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

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

    返回失败不一定是真的失败(可能网络原因导致没有收到成功的结果),但返回成功是一定要成功的。
    scegg
        80
    scegg  
       2025 年 4 月 30 日
    @wxf666 在企业应用里,一般都是有存储卡或者 HBA ,并没有这个需求。在家用环境搞这个可能没有人要买单。
    企业方案里,首先 SSD 本身就可以做分层设计,部分 SSD 就是拿来做写入缓存的,并不需要等待。在写入写入缓存 SSD 之前的那些数据,放在内存中的部分,内存本身有防掉电保护。
    在家用环境(比如 NAS )倒是有类似的功能,使用 SSD 做写入缓存,给 HDD 的 RAID 攒事务。
    另外,您自己也提到了,SSD 的顺序写入才会有累积效果,但更新一般不会变成顺序写入,而是一大堆随机事务。所以攒事务之后,也只是一个 cache 的效果。
    liqingyou2093
        81
    liqingyou2093  
       2025 年 4 月 30 日
    异地冗余呗,这边服务器被炸了换另一个
    缺点就是成本翻倍了
    akorn
        82
    akorn  
       2025 年 4 月 30 日
    @wxf666 #68 就说数据库设计原理,不具体说什么数据库,因为每种数据库的具体实现方式不一样。
    数据块的修改和回写和日志是平行的两条线。所有的 DML 操作都会记日志,为了避免频繁 IO ,日志先在日志缓存区里,等日志缓存区片满了,会统一写一次硬盘。日志里有所有的操作、操作流水号、还有 commit 。

    数据块也会在内存里做同样的操作,并且有和日志一样的流水块。内存里也有内存缓存区,缓存区满了,会写回磁盘。数据块写回磁盘的时候是不管脏不脏的。判断事物结束唯一标识是 commit 。

    这样看日志和数据块操作重复了。日志的作用(一般)就是用于做实例恢复,万一突然断电,下次启动做实例恢复,先加载数据文件,从数据文件最后一个流水号开始,去日志文件找相应流水号,把该流水号之后的操作都 redo 一遍(所以日志一般叫 redo 日志)。这样做原因,日志是顺序写,不考虑业务逻辑和数据分布,所以 io 可以非常快,基本可以同步磁盘顺序写的速度。之后,数据块的回写就可以变得非常灵活,因为数据块不仅仅是存储数据,还有查询和计算作用。

    即便日志写频繁,SSD 速度快,一般也不能每次 commit 都回写,这样就是散列 IO 了,不管 SSD 和磁盘,4K 速度和连续写都差几十倍了。还有,一个事物可能不足一个块,要不就补空块回写,一堆碎片块,占 IO 和损硬盘;或者每次都写一个空块,再把它读回来,接着写,IO 更慢了。
    chambered
        83
    chambered  
       2025 年 4 月 30 日
    我的理解:如果是分布式的数据库,fsync 可以是 1s 钟刷盘,毕竟提交成功后至少其他节点已经有数据了。如果是单机的话,为了保证绝对的不丢失,确实每次 commit 时候刷盘。以上为了保证高可用以及数据不丢失,性能肯定是打折的
    rainbowhu
        84
    rainbowhu  
       2025 年 4 月 30 日
    大嘴巴水一水,不用太当真:既然要在数据完备性要求这么高的情况下提升性能。那就考虑下怎么提升性能。
    1. 一台机器慢就多整点节点,做好负载划分。
    2. 性能也分吞吐和延迟,如果要求高吞吐,可以增大持久化的粒度。当然这样延迟会更高。如果是要求低延迟,那粒度只能维持在一个正常水平就行了,也不用太小。
    3. 剩下就是软件栈上的各种优化了,简化软件栈的关键路径,略微提升性能。。。
    rainbowhu
        85
    rainbowhu  
       2025 年 4 月 30 日
    对了,还有就是用性能更好的盘,或者用非易失内存或者保电内存之类的。反正硬件的极限就是系统的极限。
    ladeo
        86
    ladeo  
       2025 年 4 月 30 日
    供电的问题就应该供电去解决啊( UPS,ATS,多路市电,自备柴油发电机)。不要越俎代庖。
    suxb201
        87
    suxb201  
       2025 年 4 月 30 日
    和 UPS 、fsync() 没关系,想要数据安全一定得分布式,单机不管怎么搞总会有单点的安全问题(火灾、陨石)。分布式场景下性能可以做到很好的,RDMA 网络,写到同 AZ 的多份主机上,整个链路延迟很低( us 级别)。

    但这一套不是自建玩的来的,要不要考虑上云呢?各厂商数据库都有类似能力,丢数据直接甩工单索赔多爽。
    Ch3n4y
        88
    Ch3n4y  
       2025 年 4 月 30 日
    双路市电+UPS+柴油发电机,从机房建好后基本没断过电。
    latifrons
        89
    latifrons  
    OP
       2025 年 4 月 30 日
    听了大家说了这么多,收获颇丰,感谢大家。

    其实这个问题在我这里产生的根源就是在分布式系统中。单体状态自己说了算,灾难恢复回来是什么就是什么。而分布式系统就需要考虑一致性了。

    TCC 分布式事务环境下,正如 @weirdte 所说,“返回失败不一定是真的失败,但返回成功是一定要成功的”。 如果被调用方返回成功,但结果却因未落盘而回滚,调用方根本不会知道有这么个回滚节点。回滚节点也不知道有什么应该做而没做的事。

    事后对账当然是一个办法,但很多时候对账并不能挽回损失。例如扣减余额这种事如果回滚,肯定要有人背锅了。

    似乎解决方法就是双写/强制落盘,不知道例如银行、券商这样的系统,对于涉及钱的跨系统的一致性,除了对账,在技术上是如何实践的呢?又如果性能要求极其苛刻,有什么更好的优化方案?

    又从业务角度而言,问题归结为:防止数据回滚,是不是应该成为每一个程序员在开发分布式系统时必须考虑的标准设计规范,还是,程序员不用管,交给 DBA ?
    natsu94
        90
    natsu94  
       2025 年 4 月 30 日
    强一致性有 raft 这样的协议
    https://github.com/HuyuYasumi/raft-kv
    sc2yml
        91
    sc2yml  
       2025 年 4 月 30 日   ❤️ 1
    目前接触到的高频交易系统没有分布式部署,都是高频交易服务器+策略服务器,遇到极端情况交易所托管机房整体故障( AB2 路市电断电,柴发接管我司定义已经是极端情况),断开高频交易服务器与席位的连接,策略服务器执行回档落库脚本,基本都是 DBA 优化,与程序员无关
    seansong
        92
    seansong  
       2025 年 4 月 30 日
    op 估计没有接触过真正的高频交易系统,闭门造车 ing ? 高频交易系统应该极少选择 java 那一套所谓的分布式部署,不敢说所有,但我接触到的,都没有分布式部署的,会拆分成不同的独立服务,但拆分的原则之一就是没有 op 说的这种依赖问题。

    普通系统里面遇到 op 说的这个问题,除了楼上大家说的物理层防御以外,最好的办法就是堆砌硬件,尽量降低强制落盘的时延,fsync 已经是很上层的概念了,fsync 完成并不代表数据一定落盘成功了。纠结这个性能,可能还不如优化一下系统中的其他地方的性能,把这个延时从其他地方抢救回来
    ipwx
        93
    ipwx  
       2025 年 5 月 1 日
    我就不谈金融了。

    有没有可能,任何交易指令,你可以在主体处理流程之外,复制一份指令,然后旁路发给 N 个独立的服务器。这样哪怕一台没写成功,其他也写成功了。
    iceecream
        94
    iceecream  
       2025 年 5 月 1 日
    这么多人老说 ups ,ups 只是防止断电,但是如果服务器挂了呢,操作系统 crash ,等造成系统宕机,楼主说的那内存中的脏页数据不也丢了。
    PhpBB
        95
    PhpBB  
       2025 年 5 月 1 日
    板鸭这次大断电真的是深刻体会到电视剧里的灾难随时都会来,现代科技其实可以很脆弱
    julyclyde
        96
    julyclyde  
       2025 年 5 月 2 日
    @scegg UPS 也有坏的时候啊
    想当年天津塘沽联通机房的发电机进楼的线没接上的事故……
    UPS 、发电机、油库……每个 unit 单独测试都是 OK 的
    scegg
        97
    scegg  
       2025 年 5 月 2 日
    @julyclyde 嗯,机房也有塌的时候。对小概率事件的预备程度有多高,只取决于你的客户想出多少钱。
    wxf666
        98
    wxf666  
       2025 年 5 月 3 日
    @scegg #80 楼主的意思不是说,就算提交事务后,数据库脏页还在内存里,每秒才刷新一次,保证落盘到 SSD / 存储卡 / HBA ,在此之前若数据库/系统崩溃,会丢失这一秒数据吗?

    感觉 54 楼说的,数据库若能先攒够一堆事务数据(高频系统很容易短期内满足此条件),再批量顺序将脏页写入 SSD / 存储卡 / HBA ,最后才让事务返回结果,可以解决楼主的问题?

    即使是随机写入事务,WAL 落盘时也是顺序写入的,有空再慢慢回写到数据库本体就好。

    说不定还能合并多条相邻的事务数据,减少随机写入次数,事实上更快回写呢( 1MB 随机写,总体速度比 4KB 随机写快)

    比如同一用户(或同一数据页内 ID 相近的多个用户)几秒钟内几百笔交易,若每秒落盘一次,可能需要 10 次 4K 随机写。若有空慢慢回写,可以攒成一次 40K 随机写。。
    wxf666
        99
    wxf666  
       2025 年 5 月 3 日
    @acorngyl #82 嗯。。感觉你说的都是,commit 后,数据库定时将内存里的页缓存(数据/日志等),落盘到 SSD 上?

    这样就会有楼主的《 commit 后,落盘前,数据库/系统崩溃,数据丢失》问题?

    能否 commit 时,就落盘日志/数据,再结束 commit / 事务呢?

    当然,每次 commit 都落盘一次不划算,需要数据库积攒多些事务平摊成本( 4K 顺序写,和 1M 顺序写,速度也是不一样的)


    我同意你后面说的,提交事务,先顺序写数据/日志页,有空/崩溃重启后,再慢慢回写到数据库本体上。
    scegg
        100
    scegg  
       2025 年 5 月 3 日
    @wxf666 理论上,只要事务提交成功,数据库有义务完成事务的持久性( ACID 特性的 D )。至于实际上,为了“提升性能”,可做出妥协。但妥协多少是可以选择的。如果选择不妥协的策略,那么就一定会在操作系统认可的磁盘写入操作完成后,才会返回提交成功。
    另,操作系统认可的磁盘写入操作完成并不意味着实际磁盘的写入完成,因为这是存储系统的事,数据库和操作系统管不着了。但只要这存储系统设计靠谱,也意味着它在很大程度上是会完成持久保存的。至于程度有多大,又是一个为了提升性能的妥协程度问题。
    1  2  
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   Solana   ·   1030 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 22:58 · PVG 06:58 · LAX 14:58 · JFK 17:58
    ♥ Do have faith in what you're doing.