天天看點

簡析Cassandra的BATCH操作batch使用注意事項關于batch的原子性入群邀約

cassandra中批量寫入的操作稱為batch,通過batch操作可以将多個寫入請求合并為一個請求。這樣有如下好處:

  • 把多次更新操作合并為一次請求,減少用戶端和服務端的網絡互動。
  • batch中同一個partition key的操作具有隔離性。
  • 預設的LOGGED類型可以保證batch中的所有操作要麼(最終)全部成功,要麼全部失敗。也就是原子性。

本文介紹batch的使用和注意事項。并分析batch操作原子性的實作。

batch使用

cqlsh中使用batch

在cqlsh中如下語句可以送出一個batch(例子來自

cassandra官方文檔

):

BEGIN BATCH
   INSERT INTO users (userid, password, name) VALUES ('user2', 'ch@ngem3b', 'second user');
   UPDATE users SET password = 'ps22dhds' WHERE userid = 'user3';
   INSERT INTO users (userid, password) VALUES ('user4', 'ch@ngem3c');
   DELETE name FROM users WHERE userid = 'user1';
APPLY BATCH;           

在java應用中使用batch

下面的例子示意了如何使用java用戶端實作批量寫入:

PreparedStatement statement = session.prepare("insert into test(intcol,boolcol) values(?,?)");
    BatchStatement batchStatement = new BatchStatement(Type.UNLOGGED);
    for( int i = 0; i < 5; i++ ) {
      BoundStatement boundStmt = statement.bind();
      boundStmt.setInt(0, i);
      boundStmt.setBool(1, false);
      batchStatement.add(boundStmt);
    }
    session.execute(batchStatement);           

注意事項

  • UNLOGGED/COUNTER batch操作不保證原子性,可能會部分成功。
  • batch大小(指的是所有statement的内容總的大小)不能超過batch_size_fail_threshold_in_kb,否則會失敗;另外,如果batch大小如果超過batch_size_warn_threshold_in_kb,batch會成功,但會收到一個警告提示batch過大,如果日志中頻繁看到這樣的警告,需要考慮batch的使用是否正确。
  • 不建議在UNLOGGED batch中包含多個partition key,因為這樣雖然用戶端和服務端之間的互動變少,但是coordinator和其他節點的互動并沒有減少。如果partition key的數量超出了unlogged_batch_across_partitions_warn_threshold,會收到警告提示。順便說一句,cassandra的copy指令在寫入時用的就是UNLOGGED batch,在調用batch之前對請求按照key所在的節點做分組,然後再對每個分組調用batch。
  • 表的gc_grace_seconds配置會影響batch的回放。在回放batch時,會檢查涉及的所有表的gc_grace_seconds,如果目前時間已經超出了其中某個表的gc_grace_seconds,則整個batch都不會回放直接删除。另外,如果表的gc_grace_seconds為0,會收到警告提示。
  • 如果在batch中使用了條件更新,需要注意隻有所有更新操作的條件都滿足時batch才會成功,隻要有一個不滿足batch就會失敗;另外,所有更新都隻能針對同一個partition key,這是因為cassandra中cas操作隻能提供partition級别的一緻性保證。

關于batch的原子性

UNLOGGED和COUNTER類型的batch是不保證原子性的,這種batch類型的處理是簡單的把寫請求分發到對應的節點上面,是以可能會出現部分成功的情況。以下分析LOGGED batch的處理,說明batch是如何做到原子性的。

簡單來說,LOGGED batch的處理分三個步驟:

第一步 寫入batches表

batches表的結構如下:

"CREATE TABLE %s ("
                + "id timeuuid,"
                + "mutations list<blob>,"
                + "version int,"
                + "PRIMARY KEY ((id)))")           

我們可以看出一個batch的所有mutations都在一行記錄裡面。這樣的設計保證了batchlog寫入的原子性,要麼成功,要麼失敗。

第二步 分發mutation

這一步處理和UNLOGGED batch差不多,就是把每個mutation操作發送到他對應的節點上面去。比UNLOGGED batch多出的一個步驟是,如果所有mutation都成功執行了,會删除到batches表中對應的記錄。

第三部 回放batchlog

如果第二步失敗了,cassandra仍然可以保證batch最終成功。有一個線程池會以10s執行一次replayFailedBatches回放batch。如果batch中的請求全部執行成功就會删除batch。

一些細節:

  • batch中的mutate要麼成功發到endpoint,要麼成功寫入hint并落盤然後才會被删除。
  • 為了避免回放正在執行中的batch,回放時隻會選擇BATCHLOG_REPLAY_TIMEOUT之前的記錄。BATCHLOG_REPLAY_TIMEOUT的值可以通過系統屬性“cassandra.batchlog.replay_timeout_in_ms”來設定,如果沒有設定,預設值write_request_timeout_in_ms的兩倍。

從上面的分析可以看出,batch的原子性主要展現在:

  • 如果batch log寫入失敗,那麼batch的操作全部失敗。
  • 如果batch log寫入成功,即使某個mutation沒有成功,cassandra也會(在gc_grace_seconds之前)一直回放batch,保證最終全部成功。

入群邀約

為了營造一個開放的 Cassandra 技術交流,我們建立了微信群公衆号和釘釘群,為廣大使用者提供專業的技術分享及問答,定期開展專家技術直播,歡迎大家加入。另外阿裡雲提供免費Cassandra試用:

https://www.aliyun.com/product/cds
簡析Cassandra的BATCH操作batch使用注意事項關于batch的原子性入群邀約

釘釘群入群連結:

https://c.tb.cn/F3.ZRTY0o

微信群公衆号:

簡析Cassandra的BATCH操作batch使用注意事項關于batch的原子性入群邀約