PostgreSQL , 全局ID配置設定服務 , 序列 , UDF , plpgsql , 字典化
設計一個全局ID配置設定服務,要求:
1. 輸入字元串 傳回 ID
i. 已經存在系統中的字元串傳回原ID 【嚴格要求】
ii. 新字元串配置設定新ID 遞增配置設定
2. 輸入ID 傳回字元串
3. 每個Topic一個ID序列
4. Topic可以動态增删
5. 支援hsf調用
1. 支援 100萬QPS以上的讀通路
2. 支援批量 雙向查詢讀操作,一次批量100的查詢延時在1ms
3. 支援1萬QPS左右的寫操作
4. 支援批量寫操作 ,一次批量100的寫延時在10ms
1. 穩定可靠
2. 資料完全一緻
3. 資料永遠不丢
4. ID從0開始遞增,盡量少空洞 【空洞占比少于 1%】
5. 災難自恢複
實際上在之前,我有寫過另一個任務配置設定系統的設計。
<a href="https://github.com/digoal/blog/blob/master/201712/20171216_01.md">《PostgreSQL 高并發任務配置設定系統 實踐》</a>
另一方面,如果業務要求完全無縫的自增ID,我也有對應的文檔提及。
<a href="https://github.com/digoal/blog/blob/master/201610/20161020_02.md">《PostgreSQL 無縫自增ID的實作 - by advisory lock》</a>
那麼接下來按本文開頭提到的幾個要求進行設計。
1、設計一個UDF,自動生成與組ID一對一的序列,并傳回序列的值。
2、建立測試表
3、建立一個UDF,當輸入組ID和文本時,如果文本存在,傳回已有的序列,如果文本不存在則配置設定一個唯一ID,并傳回這個ID。
1、建立一個序列即可
3、建立一個UDF,當輸入文本時,如果文本已存在,傳回文本對應的序列,如果文本不存在,則配置設定一個唯一序列值,同時傳回該值。
我們假設字典空間為40億,則使用INT4。
如果字典空間超過40億,則需要使用INT8。
1、建立序列,設定起始值為INT4的最小值
例子與性能,配置設定100條文本的ID約2毫秒
1、包括組ID
2、不包括組ID
3、包括組ID,且全局唯一
空洞來源,序列不可逆轉的使用。即使事務失敗,耗費掉的序列值也不可能被傳回。
實測符合要求。
隻要寫滿了,就隻是傳回SN,是以隻要略微修改一下壓測腳本
或者你可以換成SELECT
資料庫本身沒有做任何優化,同時使用了ECS虛拟機環境,還有一定的性能提升空間。或者可以按GID拆成多個庫,實作100萬QPS不是問題。
使用PostgreSQL的UDF,序列等功能,可以實作本文開頭要求的“全局ID配置設定服務”的設計。
同時本例用到的PG執行個體為ECS虛拟機執行個體,讀性能相比實體機要差一倍左右,單機實作100萬的讀,在實體機下面是沒有問題的。
如果考慮将來的擴充性,可以将GID配置設定到不同的執行個體上,實作橫向擴充,做到單個PG執行個體100萬,多個執行個體100萬*N的讀TPS。
<a href="https://github.com/digoal/blog/blob/master/201703/20170315_01.md">《PostgreSQL 單機3.9萬億/天(計數器、序列、自增)》</a>
<a href="https://github.com/digoal/blog/blob/master/201301/20130122_01.md">《PostgreSQL sharding有序UUID最佳實踐 - serial global uuid stored in 64bit int8》</a>
<a href="https://github.com/digoal/blog/blob/master/201210/20121024_01.md">《PostgreSQL 優化CASE - 無序UUID性能問題診斷》</a>