• zhaozhao.zz's avatar
    Durability enhancement for appendfsync=always policy (#9678) · 1a7765cb
    zhaozhao.zz authored
    Durability of database is a big and old topic, in this regard Redis use AOF to
    support it, and `appendfsync=alwasys` policy is the most strict level, guarantee
    all data is both written and synced on disk before reply success to client.
    
    But there are some cases have been overlooked, and could lead to durability broken.
    
    1. The most clear one is about threaded-io mode
       we should also set client's write handler with `ae_barrier` in
       `handleClientsWithPendingWritesUsingThreads`, or the write handler would be
       called after read handler in the next event loop, it means the write command result
       could be replied to client before flush to AOF.
    2. About blocked client (mostly by module)
       in `beforeSleep()`, `handleClientsBlockedOnKeys()` should be called before
       `flushAppendOnlyFile()`, in case the unblocked clients modify data without persistence
       but send reply.
    3. When handling `ProcessingEventsWhileBlocked`
       normally it takes place when lua/function/module timeout, and we give a chance to users
       to kill the slow operation, but we should call `flushAppendOnlyFile()` before
       `handleClientsWithPendingWrites()`, in case the other clients in the last event loop get
       acknowledge before data persistence.
       for a instance:
       ```
       in the same event loop
       client A executes set foo bar
       client B executes eval "for var=1,10000000,1 do end" 0
       ```
       after the script timeout, client A will get `OK` but lose data after restart (kill redis when
       timeout) if we don't flush the write command to AOF.
    4. A more complex case about `ProcessingEventsWhileBlocked`
       it is lua timeout in transaction, for example
       `MULTI; set foo bar; eval "for var=1,10000000,1 do end" 0; EXEC`, then client will get set
       command's result before the whole transaction done, that breaks atomicity too.
       fortunately, it's already fixed by #5428 (although it's not the original purpose just a side
       effect : )), but module timeout should be fixed too.
    
    case 1, 2, 3 are fixed in this commit, the module issue in case 4 needs a followup PR.
    1a7765cb
networking.c 168 KB