在es的實踐學習中,我覺得它的文檔是最好的老師,所以先把這部分鏈接貼出來,本文只是引導,文檔全是細節,還是推薦大家事后認真看看文檔
Metadata fields-routing
在es搜索中,請求是先分發到所有分片,然后聚合結果返回,如果我們將相同業務領域的數據聚集到同一個或者少部分分片,搜索的時候只搜索這幾個分片,那么將會減少機器壓力,提高搜索性能。
沒有指定路由的情況
在沒有指定路由的情況,所有的數據是依據文檔_id(_routing的默認為_id),然后套公式均勻的分發到分片中,公式如下:
//我這邊用的是7.9.3版本,我看7.17的公式多加了一個num_routing_shards參數,分片算法改進但本質結果沒有變。
shard_num = hash(_routing) % num_primary_shards
從公式中我們可以看到id的不同必然導致文檔會分散到不同的分片中,這就是沒有自定義路由的普遍情況。
指定路由的情況
新建索引
如何指定路由要分析產品需求和數據上的相通性,就拿商品搜索來說,商品分布在不同的門店,而同一門店的商品可能會有列表搜索,有了這么一個需求,那么同一門店的商品是不是放在一個分片里是最好選擇?
分析好需求以后我們確定了針對門店編碼做路由,首先我們簡單建立一個索引
PUT ***/routing{"settings": {"number_of_shards": "3","number_of_replicas": "3","index.routing_partition_size": "2","index.number_of_routing_shards": "3"},"mappings": {"_routing": {"required": true}}
}
除了指定了常見的分片數,副本數,還有兩個新的參數index.routing_partition_size和
index.number_of_routing_shards,
index.routing_partition_size
當使用了路由,可以讓路由相同的文檔分配到同一個分片上,從而減少查詢時需要的分片數,提高查詢效率。但是使用該參數容易導致數據不平衡。為此,ES還提供了一個index.routing_partition_size參數,用于將路由相同的文檔映射到不止一個分片上,默認值是1,這樣一方面可以減少查詢的分片數,另一方面又可以在一定程度上防止分片數據不平衡。引入該參數后計算公式如下
shard_num = (hash(_routing) + hash(_id) % routing_partition_size) % num_primary_shards
這個參數只是對上面公式的進一步延申,我在索引參數中設置了2,說明在這個3個分片的索引中,路由相同的文檔分配到其中2個分片上,后面我們導入數據時看看效果。
index.number_of_routing_shards
當在es中使用自定義路由時,路由分片的數量(number_of_routing_shards)決定了有多少分片用于路由。如果不指定此設置,則無論設置的分區大小(routing_partition_size)是多少,都只使用一個分片進行路由。為了確保正確實現分區大小,請將number_of_routing_shards設置為索引中的主分片數(number_of_shards)。這將確保根據指定的路由分片大小(number_of_routing_shards)使用預期數量的分片(number_of_routing_shards)進行路由。
在很多資料中,只提了routing_partition_size但是沒有提number_of_routing_shards,如果不設置number_of_routing_shards,routing_partition_size的作用就會失效,這里著重強調,我在例子中設置了3,跟主分片數量一樣。
Unique IDs with custom routing
其次,mappings里_routing的required值為true,會讓使用自定義路由時,每當保存、獲取、刪除或更新文檔時,都必須提供路由值,否則報錯。我們要明白一點,如果不強制設置這個必填,會導致一條數據在多個分片中出現,沒錯,連_id都會一模一樣,因為在es機制中,不同的路由值下的_id才必須是唯一的。這一條規則(Unique IDs with custom routing)文檔也有寫清。
導入數據
同一個routing隨意導入若干條數據,看看數據分片的情況
插入數據
POST http://***/routing/_doc?routing=107U{"shopCode": "107U"
}
檢查預期結果
查詢分片情況:
GET
http://***/_cat/shards/routing?v
可以看到在同一個路由的情況下,數據只分布在2個分片中,符合預期。
index shard prirep state docs store ip node
routing 1 p STARTED 13 5.1kb 10.6.11.20 node-2
routing 1 r STARTED 13 5.1kb 10.6.11.20 node-1
routing 1 r STARTED 13 5.1kb 10.6.11.20 node-3
routing 2 r STARTED 7 4.8kb 10.6.11.20 node-2
routing 2 r STARTED 7 4.8kb 10.6.11.20 node-1
routing 2 p STARTED 7 4.8kb 10.6.11.20 node-3
routing 0 r STARTED 0 208b 10.6.11.20 node-2
routing 0 p STARTED 0 208b 10.6.11.20 node-1
routing 0 r STARTED 0 208b 10.6.11.20 node-3
結語
自定義路由在用戶了解查詢需求和業務的基礎之上,可以對查詢性能進行優化,然而使用不當會導致數據不平衡,重復ID等問題。所以要充分了解其機制再去使用(這里再次推薦看下官方文檔),避免反向優化。