ElasticSearch裡面的路由功能介紹
在ElaticSearch裡面,路由功能算是一個高階用法,大多數時候我們用的都是系統預設的路由功能,我們知道一個es索引可以分多個shard和每個shard又可以有多個replia,那麼現在思考一個問題,我們新增進去的資料,是如何分佈在各個shard上面的,而查詢時候它是又怎麼找到特定的資料呢。
預設情況下,索引資料的分片規則,是下面的公式:
shard_num = hash(_routing) % num_primary_shards
_routing欄位的取值,預設是_id欄位或者是_parent欄位,這樣的取值在hash之後再與有多少個shard的數量取模,最終得到這條資料應該在被分配在那個一個shard上,也就是說預設是基於hash的分片,保證在每個shard上資料量都近似平均,這樣就不會出現負載不均衡的情況,然後在檢索的時候,es預設會搜尋所有shard上的資料,最後在master節點上匯聚在處理後,返回最終資料。
但有時候,我們會有另外一種情況,比如說儲存一年的資料,如果按hash去索引,那就是分佈非常均勻,這樣的話無論查詢什麼資料都會去所有的shard上查詢,如果資料量比較大,那麼響應速度就比較慢,但這時,我們通過調查發現,一年12個月的資料本身分佈並不均勻,有幾個月的資料偏多,有幾個月的資料偏少,理想情況下,資料偏少的月,查詢效能應該更快,但如果是基於hash分片,那麼我們並不能實現這種需求,因為hash分片,查詢時候必須要命中所有shard之後,查詢的結果才是準的,這樣以來,每次查詢都要掃描所有shard,比如我已經知道資料本身就是1月份的,那其實最好的情況下,只查詢1月的資料就行,而不需要把一年的資料都掃描一遍,導致最終的結果就是慢的更慢,快的也慢,所以我們要針對性的做優化。
那麼如何優化,其實思路也比較明確了,那就是按照月份分割槽,每一個月的資料都存在指定的分割槽中,如果是mysql那就是每個月份一張表,然後查詢時候,直接查詢對應月份的資料即可,在es和solr中原理也大致如此,唯一不同的地方在於es和solr都比較方便的支援了路由欄位的設定而如果是資料庫,則需要自己通過中介軟體的方式來搞定,比如說mycat等。
下面來介紹如何在es中使用路由欄位,先看一個官網給的簡單的例子:
PUT my_index/my_type/1?routing=user1&refresh=true
{
"title": "This is a document"
}
GET my_index/my_type /1?routing=user1
上面的程式碼中,指定了一個使用者屬性作為路由進行分割槽,然後查詢的時候也必須指定路由。這一點需要注意 只要在索引時候加入路由欄位,那麼在以後的get,delete,update操作中都必須使用路由欄位,否則會出現問題。
當然,路由欄位本身,也是可以被查詢的,看下面的程式碼:
GET my_index/_search
{
"query": {
"terms": {
"_routing": [ "user1" ]
}
}
}
除此之外,路由欄位,也可以指定多個:
GET my_index/_search?routing=user1,user2
{
"query": {
"match": {
"title": "document"
}
}
}
如果指定多個使用者屬性,那麼es會僅僅查詢關聯了這兩個route屬性的shard
如果加入路由欄位之後,其他的操作(indexing,getting,deleting,updating)都必須指定路由欄位,為了避免在使用時忘記新增 路由欄位,導致同類資料會分佈在多個shard上,這就違反了路由的原則,所以我們可以在mapping中 設定路由欄位是必須欄位,否則會提示錯誤:
PUT my_index2
{
"mappings": {
"my_type": {
"_routing": {
"required": true
}
}
}
}
PUT my_index2/my_type/1
{
"text": "No routing value provided"
}
缺失路由欄位會丟擲異常:
routing_missing_exception
還需要注意到是如果使用了路由欄位,那麼_id欄位只能由使用者保證唯一性,因為同一個id的資料,如果路由欄位不一樣 它是可以被存在到多個shard中的,而預設情況下是不會出現這種情況的。
最後接著說開頭的例子,如果某個月資料量偏大,全部路由到一個shard裡面依然效能有問題,es也提供了 同一個路由的欄位的資料可以被分配到多個shard上,注意這是是多個shard,而不是所有shard,當然這裡面有一定 限制一般情況下,不建議使用這種模式。
對solr中路由感興趣的朋友,可以檢視我以前寫的文章:
參考資料: