天天看點

Tablestore自增列的正确使用姿勢

本文立題來源于Tablestore的日常線上支援,為解剛上手Tablestore的同學對“主鍵列自增”這個功能的使用疑惑。

一個日常咨詢:

X同學:我想修改一行資料,用UpdateRow接口,但是我的表裡用了自增列,我不知道自增主鍵的值是什麼,PrimaryKey怎麼填寫呢?

技術支援:您要修改這行需要先讀出來,拿到主鍵資訊,再做修改。

X同學:是用GetRow接口讀嗎?那GetRow的PrimaryKey怎麼填寫?

技術支援:沒有完整的主鍵資訊不能使用GetRow接口讀,您可以嘗試用GetRange加上過濾條件找到要修改的行。如果有單行讀和單行修改的操作,建議在插入行的時候選擇傳回主鍵資訊,做一下記錄供以後操作,可以

參考文檔

X同學:...(内心感覺很不好用)

自增列-“主鍵列自增”,是Tablestore很有特色的一個功能,和常見的k-v存儲相比,我們支援建立含有一個“自增列主鍵”的表。若設定某一列主鍵為自增列,在寫入一行資料時,這一列主鍵無需填值,表格存儲會自動生成這一主鍵列的值。該值在分區鍵上保證唯一,且嚴格遞增。

要想知道自增列主鍵的用途,不妨了解下它被創造的背景,自增列主鍵最早開發是為了給某商務溝通軟體用的,目标是高效支援一個IM系統,如果您正是要找IM系統的實作方案,可以直接參考

Tablestore主鍵列自增功能在IM系統中的應用

社交IM的基本需求是:将源使用者發送的消息及時、準确地更新給該目的使用者。一條消息的基本元素 {接收方的使用者ID,消息内容};為了保證所有的消息能夠按照正确的順序被接收端處理,添加消息ID,一條消息的結構變為 {接收方的使用者ID,消息ID,消息内容},保證消息ID嚴格遞增。

實作上以“接收方使用者ID”和“消息ID”做主鍵,“消息内容”為屬性,一條消息存為一行資料;接收端根據“接收方使用者ID”和“消息ID”的範圍批量擷取并處理對應使用者的消息。

通過GetRange接口讀取最近的消息。message_id這一列PK的起始位置是上一條消息的message_id+1,結束位置是INF_MAX,這樣每次都可以讀出最新的消息,然後發送給用戶端。

代碼實作參考

自增列分區鍵級别唯一,嚴格遞增但不保證連續

分區鍵(第一個主鍵)級别唯一,從上述背景可看到,相同的“接收方使用者ID”的消息在同一個分區鍵内,是以分區鍵級别唯一且嚴格遞增的“消息ID”已經可以保證消息的順序性。為什麼不是全表唯一呢,Tablestore的底層實作決定,有“相同的分區鍵的行”會被放在“同一個分區”,一個分區同一時刻唯一被一台機器加載;是以簡單了解“分區鍵級别”是同一台機器上的操作,而“表級别”則是跨機器的操作,出于性能和可擴充性保證,我們提供部分擴充操作都是分區鍵級别的:自增列、局部事務等。

綜上可看,自增列的一個主流用法是:“同一個ID”有序的存儲一批資料,單條或批量寫入,然後批量的讀取和處理。自增列的主要作用是“保序”,而不是作為唯一定位一行的主鍵部分的主要“身份區分”元素。一來自增列的并值不是全表唯一的,二來在寫入時就開始記錄自增主鍵的值有一定維護成本。           

一個用的不好的例子

  • 某使用者做一個全國食品連鎖店的店鋪資訊統計,把自增主鍵作為區分同名連鎖店的唯一辨別:
PK1 PK2 PK3 col1 col2 col3 ......
北京 KFC 1578490808029000 位址:朝陽區 電話:xxx 營業時間:xxx
上海 M記 1578490791443000 位址:徐彙區
杭州 必勝客 1578490823817000 位址:西湖區
1578490833204000 位址:濱江區

杭州的兩家必勝客,插入資料時沒有問題,自增的主鍵隻填一個占位符,補充其他資訊即可。存儲時也沒有問題,自增主鍵保證了主鍵的唯一性,但是查詢資訊的時候就頭疼了,插入行的時候并沒有保留自增列PK3的資訊,沒有完整的主鍵資訊既沒辦法讀取單行資訊,也不能對單行資訊進行修改。

同樣的主鍵結構換個場景則适用:

  • 統計不同地區“不同品牌”連鎖店的,高低峰就餐時間段不同桌型的就座率。
桌型:兩人桌 新增就餐人數:1
桌型:四人桌 結束就餐人數:3
桌型:六人桌 新增就餐人數:5
1578490823817800 結束就餐人數:5
新增就餐人數:4

每隔時間周期,批量擷取一次某品牌不同桌型新增/結束就餐人數資訊做增量處理,統計出實時的就座率。這裡的自增列PK3保證了同一桌人開始就餐和結束就餐的順序不會錯亂,就座率始終為正。和上例的不同點:1.把“杭州-必勝客”看為一個“同一個ID” 2.行的屬性資訊是一個待處理的隊列性質資訊。

  • 如果還是要實作原來的需求店鋪資訊統計,那麼改一下表結構使主鍵唯一且使用者可知:
必勝客(西湖區)
必勝客(濱江區)
  • 如果隻想借Tablestore的主鍵自增功能做一個“唯一ID生成器”的話:

建議用一張表專門生層“唯一ID”,先插入一條資料到這張表拿到傳回的主鍵資訊,再寫入業務表。

ID生成 000
col4

不推薦這樣使用自增列屬性,因為若想保證全表唯一,生成ID的表的分區鍵是固定的。即全表隻有一個分區鍵,落在一個分區一台機器上,且分區無法再分裂,一個分區下的資料不宜過多,應該控制在10GB以内,當行數到千萬級及以上時可能就會到達瓶頸。

本文主要講Tablestore的自增列最為普遍的使用方式,大家如果用在了更多新場景解鎖了更多新姿勢,歡迎進群交流讨論。釘釘群:“表格存儲公開交流群”,群内提供免費的線上專家服務,歡迎掃碼加入,群号:23307953

Tablestore自增列的正确使用姿勢