Edited at
SolrDay 7

Solrのドキュメントルーティングのやり方

More than 1 year has passed since last update.


ドキュメントルーティングとは

クライアントからインデックスさせるシャードを指定する機能です。

シャーディングしているインデックスに対してはgroup.ngroups、group.facetが正常に機能しない(間違った値が取れる)という欠点がありますが、ドキュメントルーティングすることで、これらの機能を正常に動かすことができます。


参考資料

下記を参考にしました。

https://lucidworks.com/blog/2013/06/13/solr-cloud-document-routing/


やり方

ドキュメントルーティングをするには、下記の形式でunique keyを書き換えます。

routing key + ! + unique key 

hogehoge!00001

routing keyの文字列を元にしてハッシュ値(murmurhash3の32bit)が生成されます。

各シャードは自分が担当するハッシュの値域が予め設定されており、このハッシュ値が該当するシャードにドキュメントが振り分けられます。

各シャードの担当値域はstate.jsonの中で確認できます。

{"routing":{

"replicationFactor":"3",
"router":{"name":"compositeId"},
"maxShardsPerNode":"1",
"autoAddReplicas":"false",
"shards":{
"shard1":{
"range":"80000000-d554ffff", //これ


調査用のインデックス

https://github.com/tkondo1223/solr-advent-calender2016/tree/master/routing


各種比較


ドキュメントの偏り


ドキュメントルーティング無し

全シャードにドキュメントが振り分けられています。

シャード1

シャード2

シャード3


ドキュメントルーティング有り

シャード1

シャード2

シャード3

キーと各シャードの担当範囲は下記の通りなので、正しくルーティングされています。

ルーティングキー
mmh3
振り分け先
ドキュメント数

key1
9b970125
shard1
6

key2
737139b4
shard3
4

key3
a648eb58
shard1
9

担当範囲

shard1
80000000-d554ffff

shard2
d5550000-2aa9ffff

shard3
2aaa0000-7fffffff


groupingへの影響


group.ngroups

q=*:*&wt=json&start=0&rows=10&group=true&group.field=mmh3&group.ngroups=true


ドキュメントルーティング無し

ngroupsが正しくない

{

"grouped": {
"mmh3": {
"matches": 19,
"ngroups": 7, //間違い
"groups": [
{
"groupValue": "a648eb58",
"doclist": {
"numFound": 9,
"start": 0,
"maxScore": 1,
"docs": [
{
"id": "5",
"mmh3": "a648eb58",
"_version_": 1553056878448083000
}
]
}
},
{
"groupValue": "9b970125",
"doclist": {
"numFound": 6,
"start": 0,
"maxScore": 1,
"docs": [
{
"id": "18",
"mmh3": "9b970125",
"_version_": 1553056878470103000
}
]
}
},
{
"groupValue": "737139b4",
"doclist": {
"numFound": 4,
"start": 0,
"docs": [
{
"id": "1",
"mmh3": "737139b4",
"_version_": 1553056878368391200
}
]
}
}
]
}
}
}


ドキュメントルーティング有り

正しい結果が返ってきている

{

"grouped": {
"mmh3": {
"matches": 19,
"ngroups": 3, //正しい
"groups": [
{
"groupValue": "737139b4",
"doclist": {
"numFound": 4,
"start": 0,
"docs": [
{
"id": "key2!1",
"mmh3": "737139b4",
"_version_": 1553055543823696000
}
]
}
},
{
"groupValue": "9b970125",
"doclist": {
"numFound": 6,
"start": 0,
"docs": [
{
"id": "key1!2",
"mmh3": "9b970125",
"_version_": 1553055543823696000
}
]
}
},
{
"groupValue": "a648eb58",
"doclist": {
"numFound": 9,
"start": 0,
"docs": [
{
"id": "key3!3",
"mmh3": "a648eb58",
"_version_": 1553055543826841600
}
]
}
}
]
}
}
}


group.facet

q=*:*&wt=json&start=0&rows=10&group=true&group.field=mmh3&group.ngroups=true&group.facet=true&facet.field=mmh3&facet=true

mmh3単位での集計のため、全て1が正しい

ドキュメントルーティング無し

    "facet_fields": {

"mmh3": [
"9b970125",
3,
"a648eb58",
3,
"737139b4",
1
]
},

ドキュメントルーティング有り

    "facet_fields": {

"mmh3": [
"737139b4",
1,
"9b970125",
1,
"a648eb58",
1
]
}


デメリット

ドキュメントルーティングを使い振り分けをすればngourpsなどの機能が正常に処理できますが、デメリットも存在します。

1つ目はハッシュ値(ユーザーから確認できない)で振り分けがされるのですが、キーがどのハッシュ値になるかSolrからは確認できないので、事前にソースコードを書いてどのキーでどのシャードに振り分けられるか確認しておかないといけません。

2つ目はキー名の自由度が無いことです。

キー名をgroup[1-3]みたいなものにして、それぞれ対応するナンバリングのshardに振り分けたいと考えていても、group1とgroup3のハッシュがshard1の担当範囲に入るとキー名を変える必要があります。

3つ目はこの仕様をシステム担当者がずっと引き継いでいかないといけないことです。

時が経って、仕様も忘れ去られた時に新しいグループの追加が発生すると大変なことになるかもしれません。


まとめ

ドキュメントルーティング自体はクセがあって少し使いにくい機能だなと感じましたが、ドキュメント数が多くなるとインデキシングのパフォーマンス向上やインデックスをメモリに乗せきるために、シャーディングは必須なため、上手くこの仕様と付き合っていきたいところです。