全部產品
Search
文件中心

Tablestore:原子計數器

更新時間:Jun 30, 2024

如果要在某些線上應用中快速進行計數操作,您可以使用原子計數器實現。使用原子計數器時,您需要將表中的某一列當成一個原子計數器,然後對該列進行原子計數操作。

情境

原子計數器適用於需要快速進行計數操作的情境,例如在某些線上應用中實現統計文章的PV(即時瀏覽量)、訊息計數等功能。

功能概述

原子計數器可以解決由強一致性導致的寫入效能開銷的問題。一個RMW(Read-Modify-Write)操作,通過一次網路請求發送到伺服器端,伺服器端使用內部行鎖機制在本地完成RMW的操作。通過原子計數器將分散式運算器的計算邏輯下推到伺服器端,在保證強一致性的情況下,提升原子計數器的寫入效能。

重要

原子計數操作可能會由於網路逾時、系統錯誤等導致失敗。此時只需重試操作即可,但是可能會更新兩次原子計數器,導致原子計數器偏多或偏少。針對此類異常情境,建議使用條件更新精確變更列值。

使用原子計數器功能,您可以對某一行中的資料做即時統計。為了實現原子計數器功能,Table StoreUpdateRow介面中新增了原子計數器的相關操作,例如對列執行增量變更、返回進行原子計數操作後的列值。

假設您需要使用Table Store來儲存圖片元資訊並統計圖片數資訊,資料表內每一行對應某一個使用者ID,行上的其中一列用於儲存上傳的圖片,另一列用於即時統計上傳的圖片數。

  • 使用UpdateRow介面增加一張新圖片時,原子計數器+1。

  • 使用UpdateRow介面刪除一張舊圖片時,原子計數器-1。

  • 使用GetRow介面讀取原子計數器的值,擷取目前使用者的圖片數。

上述行為具有強一致性,即當增加一張新圖片時,原子計數器會相應+1,而不會出現-1的情況。

注意事項

  • 只支援對整型列的列值進行原子計數操作。

  • 作為原子計數器的列,如果寫入資料前該列不存在,則預設值為0;如果寫入資料前該列已存在且列值非整型,則產生OTSParameterInvalid錯誤。

  • 增量值可以是正數或負數,但不能出現計算溢出。如果出現計算溢出,則產生OTSParameterInvalid錯誤。

  • 預設不返回進行原子計數操作的列值,您可以通過相應操作指定返回進行原子計數操作的列值。

  • 在單次更新要求中,不能對某一列同時進行更新和原子計數操作。假設列A已經執行原子計數操作,則列A不能再執行其他動作(例如列的覆蓋寫,列刪除等)。

  • 在一次BatchWriteRow請求中,支援對同一行資料進行多次更新操作。但是如果某一行已進行原子計數操作,則該行在此批量請求中只能出現一次。

  • 原子計數操作只能作用在列值的最新版本,不支援對列值的特定版本做原子計數操作。更新完成後,原子計數操作會插入一個新的資料版本。

使用方式

重要

只支援通過SDK方式使用原子計數器功能。

您可以通過Java SDKGo SDKPython SDKNode.js SDK.NET SDKPHP SDK使用原子計數器功能。此處以Java SDK為例介紹原子計數器功能的使用。

寫入資料時,使用rowUpdateChange介面對整型列做列值的增量變更,然後讀取更新後的新值。

private static void incrementByUpdateRowApi(SyncClient client) {
    //構造主鍵。
    PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    primaryKeyBuilder.addPrimaryKeyColumn("<PRIMARY_KEY_NAME>", PrimaryKeyValue.fromString("pk0"));
    PrimaryKey primaryKey = primaryKeyBuilder.build();
    //設定資料表名稱。
    RowUpdateChange rowUpdateChange = new RowUpdateChange("<TABLE_NAME>", primaryKey); 

    //將進行原子計數操作的price列的列值+10,不能設定時間戳記。
    rowUpdateChange.increment(new Column("price", ColumnValue.fromLong(10)));

    //設定returnType為ReturnType.RT_AFTER_MODIFY,將進行原子計數操作的列值返回。
    rowUpdateChange.addReturnColumn("price");
    rowUpdateChange.setReturnType(ReturnType.RT_AFTER_MODIFY);

    //對price列進行原子計數操作。
    UpdateRowResponse response = client.updateRow(new UpdateRowRequest(rowUpdateChange));

    //列印更新後的新值。
    Row row = response.getRow();
    System.out.println(row);
}

計費說明

使用原子計數器功能不影響現有計費規則。關於計費的更多資訊,請參見計費概述