通過Hashed ID標識並存儲在不變的文件中的數據的快速索引引擎
這是Treee™索引引擎的GO實現。這既是用於您的GO項目中的模塊的庫,又是可執行的,可以用作HTTP的微服務。
面臨的挑戰是,當數據是某些可以在子鏈中相互連接的項目列表時,要建立一個功能強大且安全的搜索引擎,通過其標識符進行索引,這些項目僅由Hashed值(例如SHA-256字符串表示)組成,並且所有存儲在不可分的文件中。
它的最佳應用程序是一個區塊鏈文件,其中項目是嵌入智能合約的交易,以及隨後的用途和/或修改此智能合約的每個項目的每個子鏈。因此,Treee™索引目前用於ROOOT™區塊鏈中。
我們在這裡定義了一種算法,用於基於標識符的標識符索引系統,該標識符同時對寫作和閱讀非常有力。
Treee™索引被構造為無環圖(樹)。每個節點都包含節點地址(其兒子)或一組葉子,該葉子與有助於檢索一個或多個鏈接項目的信息相對應。
節點的兒子數量是確定性的,取決於樹的深度。我們用深度1的節點兒子的數量表示,在深度2,在深度上,節點的兒子數量。
目的是創建一個平衡的樹,其寬度具有自適應以減小深度並優化性能。我們正在尋找索引編號,在這種情況下,項目的唯一標識符的數值值。
讓我們解釋一下索引的過程。
對於二進制樹,我們以二進制形式(例如100 )編寫數字,該數字指示其在樹上的位置。
在步驟中,如果位是0 ,我們將孩子傳遞給孩子,否則如果位是1 ,則將其傳遞給孩子。當節點是葉子時,我們停止。
對於樹,我們通過一系列數字來構建該數字的表示形式,並以相同的方式穿越樹。在深度步驟中,如果代表為0 ,我們將孩子傳給孩子,如果代表是1 ,如果代表為1,則將其傳遞給孩子。當節點是葉子時,我們停止。
為了構建數字的表示,我們將依次採用質數的模型。根據中國遺骸的定理,每個數字都有一個獨特的代表,可以寫為這些模量的延續。確實,可以以以下形式寫入數字:
項目標識符的值(其編號)表示為調製號碼。用於固定尺寸整數計算模量。由於乘法比除法快(計算模型所需的速度),因此可以通過浮動使用乘法:。
鑑於數字的隨機性質(或偽隨機,由於項目的標識符是由加密哈希技術生成的),因此樹是平衡的。要以惡意的方式使樹不平衡,必須能夠產生hashes的模仿遵循特定軌蹟的哈希。但是,這種操作的困難呈指數增加(深度為were的順序)。提醒您,前16個質數的產物等於。因此,一旦該索引包含相當大的數據,如果可能的話,以惡意的方式不平衡樹就變得越來越不可能。
葉子包含以下有關項目的信息列表:
下一個項目字段為空的葉子是子鏈中的最後一項。
其原點項目字段等於當前項目的標識符的葉子必然是子鏈的原點。因此,它具有特定的操作,此後,如果此後要有一個或多個項目,則該子鏈的最後一項將在這裡確定為上一項。因此,葉子的最後三個字段對應於圓形鏈接列表。
為索引添加一個元素:
在索引中讀取/搜索項目:
使用索引時,我們可以看到,我們最多可以執行3次讀取或3個寫入和索引運行,而索引中的項目數在哪裡。
有關更多詳細信息,請隨時閱讀完整的白皮書。
$ go get github.com/cyrildever/treee import (
"github.com/cyrildever/treee/core/index"
"github.com/cyrildever/treee/core/index/branch"
"github.com/cyrildever/treee/core/model"
)
// Instantiate default index (could be any prime number up to the 1000th existing prime number,
// but should be much lower to better leverage the solution, and if 0 will use the default INIT_PRIME value)
treee , err := index . New ( index . INIT_PRIME )
if err != nil {
// Handle error
}
// Add to index
leaf := branch. Leaf {
ID : model . Hash ( "1234567890abcdef" ),
Position : 0 ,
Size : 100 ,
}
err = treee . Add ( leaf )
if err != nil {
// Handle error
}
// Search
if found , err := treee . Search ( leaf . ID ); err == nil {
// Do something with found Leaf
}為了獲得更好的性能,您應該將搜索請求放在不同的goroutines中(例如,請參見API/Handlers/Leaf.go文件中的GetLeaf()實現)。
為了進行調試或存儲目的,您可能需要使用Treee索引上的PrintAll()方法將所有記錄的葉子打印給作者(將其作為true作為美化印刷的JSON的參數,或為原始字符串false )。
// To print to Stdout
fmt . Println ( treee . PrintAll ( true ))索引的持久性是通過使用插入時的自動保存以及使用Load()函數而不是在啟動時使用New() Treee Intantiation實現的。
treee , err := index . Load ( "path/to/treee.json" ) // If empty, will use "./saved/treee.json"它可以使用相應的環境變量或命令行中的標誌進行禁用,甚至可以通過編程方式進行禁用:
treee . UsePersistence ( false ) // If you're positive you don't want it您可以簡單地構建可執行文件並啟動Treee™索引引擎的實例。
$ git clone https://github.com/cyrildever/treee.git && cd treee && go build
$ ./treee -t.port 7001 -t.host localhost -t.init 101 Usage of ./treee:
-t.file string
File path to an existing index
-t.host string
Host address (default "0.0.0.0")
-t.init string
Initial prime number to use for the index (default "0")
-t.persist
Activate persistence (default true)
-t.port string
HTTP port number (default "7000")
如果設置,則以下環境變量將覆蓋與命令行傳遞的任何相應的默認配置或標誌:
HOST :主機地址;HTTP_PORT :要使用的HTTP端口號;INDEX_PATH :以JSON格式的索引文件的路徑;INIT_PRIME :初始質數(請注意,如果使用文件,它將沒有任何效果,因為後者將佔上風);USE_PERSISTENCE :設置false以禁用將索引保存到文件中的使用。 /api組下面可用以下端點:
DELETE /leaf此端點從索引中刪除了傳遞的項目。
它期望一系列ID作為ids查詢參數,例如。
DELETE /api/leaf?ids=1235467890abcdef [ ... ] &ids=fedcba0987654321 [ ... ]
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
Host: treee.io
Accept-Language: fr-FR
Accept-Encoding: gzip, deflate
Accept: application/json如果刪除了所有經過的項目,它將返回204狀態代碼,或200狀態代碼以及以下未刪除ID的JSON列表,如果某些未刪除:
{
"ids" : [ " fedcba0987654321[...] " ]
}GET /leaf此端點根據傳遞的ID搜索項目。
它期望將一系列ID作為ids查詢參數和可選的takeLast boolean(默認為false ),例如。 http://localhost:7000/api/leaf?ids=1234567890abcdef[...]&ids=fedcba0987654321[...]&takeLast=true
它返回狀態代碼200以及尊重以下格式的JSON對象:
[
{
"id" : " 1234567890abcdef[...] " ,
"position" : 0 ,
"size" : 100 ,
"origin" : " 1234567890abcdef[...] " ,
"previous" : " 1234567890abcdef[...] " ,
"next" : " "
},
[ ... ]
]如果找不到任何項目,它將返回帶有空白的404狀態代碼。
GET /line該端點返回同一子鏈/行中的所有ID。
它希望行的任何ID作為id查詢參數,例如。 http://localhost:7000/api/line?id=1234567890abcdef[...]
它返回一個狀態代碼200長,以下JSON排序的ID數組(索引0為origin):
[
" 1234567890abcdef[...] " ,
" fedcba0987654321[...] "
]如果找不到任何項目,它將返回帶有空白的404狀態代碼。
POST /leaf此端點將項目添加到索引中。
它預計以下JSON對像是身體,前三個字段是強制性的:
{
"id" : " <The item ID as a hash string representation> " ,
"position" : 0 ,
"size" : 100 ,
"previous" : " <An optional item ID of the previous item in the current subchain if any> "
}它返回狀態代碼和以下對象為JSON:
{
"code" : 200 | 303 | 400 | 404 | 412 | 500,
"result" : " <The inserted item ID if success> " ,
"error" : " <The error message if failed> "
}狀態代碼(及其含義)的列表如下:
200 :插入的項目;303 :項目已經存在(由於文件應該是不可變的而未更新);400 :錯誤參數(缺少項目,缺少強制性字段等);404 :未找到以前的項目;412 :傳遞數據中的某些東西導致服務器失敗(錯誤的JSON格式,...);500 :服務器上發生了錯誤。平均而言,基本機器應該能夠攝入超過1億新記錄,並每小時處理約50億搜索查詢。
例如,在Apple Macbook Pro 2.3 GHz Intel Core i9上,以16個GO DDR4 RAM為2400 MHz,我在使用101作為Init Prime時觀察到以下表演:
101作為Init Prime:該模塊是根據MIT許可證分發的。
請參閱許可證文件。