ES Route


在ElaticSearch里面,路由功能算是一個高級用法,大多數時候我們用的都是系統默認的路由功能,一個es索引可以分多個shard和每個shard又可以有多個replia,默認情況下,elasticsearch是通過hash的方式確定每個文檔所屬的分片的,公式如下:
shard_num = hash(_routing) % num_primary_shards
  • _routing字段的取值,默認是_id字段
  • num_primary_shards表示索引有多少個shard

最終得到這條數據應該在被分配在那個一個shard上,也就是說默認是基於hash的分片保證在每個shard上數據量都近似平均,這樣就不會出現負載不均衡的情況,然后在檢索的時候,es默認會搜索所有shard上的數據,最后在master節點上匯聚在處理后,返回最終數據

    實際應用中的場景:比如說存儲一年的數據,如果按hash去索引,那就是分布非常均勻,這樣的話無論查詢什么數據都會去所有的shard上查詢,如果數據量比較大,那么響應速度就比較慢,但這時,一年12個月的數據本身分布並不均勻,有幾個月的數據偏多,有幾個月的數據偏少,理想情況下,數據偏少的月,查詢性能應該更快,但如果是基於hash分片,那么我們並不能實現這種需求,因為hash分片,查詢時候必須要命中所有shard之后,查詢的結果才是准的,這樣以來,每次查詢都要掃描所有shard,比如我已經知道數據本身就是1月份的,那其實最好的情況下,只查詢1月的數據就行,而不需要把一年的數據都掃描一遍,導致最終的結果就是慢的更慢,快的也慢,所以我們要針對性的做優化。

    思路也比較明確了,那就是按照月份分區,每一個月的數據都存在指定的分區中,如果是mysql那就是每個月份一張表,然后查詢時候,直接查詢對應月份的數據即可,在es和solr中原理也大致如此,唯一不同的地方在於es和solr都比較方便的支持了路由字段的設置而如果是數據庫,則需要自己通過中間件的方式來搞定。

在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 route

  • elasticsearch直接通過hash值取模然后除以routingFactor來確定所屬的shard,而solr中必須要遍歷索引下的每個shard才能確定所屬shard。從效率看如果有n個shard,那么solr的時間復雜度為O(n),而elasticserach的時間復雜度為O(1)。
  • 對於shard數比較大,索引數據很多的情況下,elasticsearch會快上不少。
  • elasticsearch不支持單個shard split, 而solr支持

參考資料:



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM