blogサービスの全文検索の話 - #groonga を囲む夕べ
TRANSCRIPT
![Page 1: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/1.jpg)
blogサービスの全文検索の話
全文検索エンジンGroongaを囲む夕べ5長野雅広 (kazeburo)
![Page 2: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/2.jpg)
Me•長野雅広 (Masahiro Nagano)•@kazeburo / github:kazeburo•Operations Engineer / Site Reliability
•LINE corp.• ISUCON 2013,2014 連覇
![Page 3: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/3.jpg)
今日のお題
![Page 4: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/4.jpg)
![Page 5: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/5.jpg)
livedoor Blog•サービス開始11周年
•国内最大級
•blog開設数 570万件
•総記事数 3億件
•約100億PV/month
![Page 6: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/6.jpg)
livedoor Blogを支える技術
•Reverse Proxy - Apache, Nginx
•Application - Perl, Go
•Cache - Memcached
•RDBMS - MySQL 4.0, 5.5
•Search Engine - Mroonga
![Page 7: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/7.jpg)
どこで Mroonga が使われているか
![Page 8: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/8.jpg)
![Page 9: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/9.jpg)
![Page 10: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/10.jpg)
blog内の記事検索blog横断の検索はありませんが、
3億件の記事が対象
![Page 11: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/11.jpg)
Mroongaを採用した理由
![Page 12: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/12.jpg)
競合• MySQLのLIKE検索
➡ 検索機能不足
➡ カテゴリやタグなどの絞り込みが面倒
• MySQL組み込みの全文検索
➡ 日本語非対応
• Elasticsearch
➡ Java/JVMの経験不足
➡ 大規模環境でのトラブルシューティングに不安
![Page 13: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/13.jpg)
Mroonga
•MySQL! MySQL! MySQL!
➡レプリケーションやバックアップなどMySQLの知見が活かせる
•日本語で作者とコミュニケーション
![Page 14: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/14.jpg)
検索サーバの構成
![Page 15: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/15.jpg)
microservicesマイクロサービスっぽく作ってます
![Page 16: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/16.jpg)
blogApp
blogApp
blogApp
cmsApp
cmsApp
cmsApp
記事表示 Service 記事編集 Service
SearchAPI
SearchAPI
IndexWorker
IndexWorker
Q4M MappingDB
検索 Serviceshard1 shard2 shard3
![Page 17: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/17.jpg)
blogApp
blogApp
blogApp
cmsApp
cmsApp
cmsApp
記事表示 Service 記事編集 Service
SearchAPI
SearchAPI
IndexWorker
IndexWorker
Q4M MappingDB
検索 Service
記事追加
shard1 shard2 shard3
![Page 18: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/18.jpg)
blogApp
blogApp
blogApp
cmsApp
cmsApp
cmsApp
記事表示 Service 記事編集 Service
SearchAPI
SearchAPI
IndexWorker
IndexWorker
Q4M MappingDB
検索 Service
記事追加
shard1 shard2 shard3
Queueing
![Page 19: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/19.jpg)
blogApp
blogApp
blogApp
cmsApp
cmsApp
cmsApp
記事表示 Service 記事編集 Service
SearchAPI
SearchAPI
IndexWorker
IndexWorker
Q4M MappingDB
検索 Service
記事追加
shard1 shard2 shard3
Queueing
blog_idとshardのmapping
![Page 20: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/20.jpg)
blogApp
blogApp
blogApp
cmsApp
cmsApp
cmsApp
記事表示 Service 記事編集 Service
SearchAPI
SearchAPI
IndexWorker
IndexWorker
Q4M MappingDB
検索 Service
記事追加
shard1 shard2 shard3
Queueing
blog_idとshardのmapping
INSERT!
![Page 21: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/21.jpg)
blogApp
blogApp
blogApp
cmsApp
cmsApp
cmsApp
記事表示 Service 記事編集 Service
SearchAPI
SearchAPI
IndexWorker
IndexWorker
Q4M MappingDB
検索 Serviceshard1 shard2 shard3
![Page 22: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/22.jpg)
blogApp
blogApp
blogApp
cmsApp
cmsApp
cmsApp
記事表示 Service 記事編集 Service
SearchAPI
SearchAPI
IndexWorker
IndexWorker
Q4M MappingDB
検索 Service
検索
shard1 shard2 shard3
![Page 23: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/23.jpg)
blogApp
blogApp
blogApp
cmsApp
cmsApp
cmsApp
記事表示 Service 記事編集 Service
SearchAPI
SearchAPI
IndexWorker
IndexWorker
Q4M MappingDB
検索 Service
検索
shard1 shard2 shard3
blog_idとshardのmapping
![Page 24: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/24.jpg)
blogApp
blogApp
blogApp
cmsApp
cmsApp
cmsApp
記事表示 Service 記事編集 Service
SearchAPI
SearchAPI
IndexWorker
IndexWorker
Q4M MappingDB
検索 Service
検索
shard1 shard2 shard3
blog_idとshardのmapping
SELECT
![Page 25: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/25.jpg)
Mroonga サーバの構成
shard1 shard2 shard3
この中身
![Page 26: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/26.jpg)
Shardの構成
master
slave slave
Shard N
![Page 27: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/27.jpg)
Shardの構成
master
slave slave
Shard N
参照・更新は全てMaster
Slaveはバックアップ
![Page 28: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/28.jpg)
ハードウェア
•Intel Xeon 6core/12thread * 2
•Memory 96GB
•PCI-E SSD
![Page 29: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/29.jpg)
テーブルとスキーマ
![Page 30: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/30.jpg)
スキーマCREATE TABLE article_index_0001 ( id bigint unsigned NOT NULL AUTO_INCREMENT, blog_id int unsigned NOT NULL, article_id int unsigned NOT NULL, status tinyint NOT NULL, public_terms mediumtext, private_terms mediumtext, article_datetime datetime NOT NULL, PRIMARY KEY (id), UNIQUE KEY unique_entry (blog_id,article_id), FULLTEXT KEY for_public (public_terms), FULLTEXT KEY for_cms (public_terms,private_terms)) ENGINE=mroonga;
storage mode
![Page 31: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/31.jpg)
スキーマCREATE TABLE article_index_0001 ( id bigint unsigned NOT NULL AUTO_INCREMENT, blog_id int unsigned NOT NULL, article_id int unsigned NOT NULL, status tinyint NOT NULL, public_terms mediumtext, private_terms mediumtext, article_datetime datetime NOT NULL, PRIMARY KEY (id), UNIQUE KEY unique_entry (blog_id,article_id), FULLTEXT KEY for_public (public_terms), FULLTEXT KEY for_cms (public_terms,private_terms)) ENGINE=mroonga; x150storage mode
![Page 32: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/32.jpg)
mysql>show tables;+--------------------+| Tables_in_hermes |+--------------------+| article_index_0001 || article_index_0002 || article_index_0003 || article_index_0004 || article_index_0005 || article_index_0006 || article_index_0007 |......| article_index_0142 || article_index_0143 || article_index_0144 || article_index_0145 || article_index_0146 || article_index_0147 || article_index_0148 || article_index_0149 || article_index_0150 |+--------------------+150 rows in set (0.00 sec)
![Page 33: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/33.jpg)
Table 分散
0001 0002 0003 0004 0005 0006
0007 ... ... ... ... 0144
0145 0146 0147 0148 0149 0150
SearchAPI
IndexWorker
blog_idで分散
![Page 34: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/34.jpg)
Table 分散
0001 0002 0003 0004 0005 0006
0007 ... ... ... ... 0144
0145 0146 0147 0148 0149 0150
SearchAPI
IndexWorker
blog_idで分散
(murmur_hash(blog_id) % 150) + 1
![Page 35: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/35.jpg)
Table分散を行う理由
•Mroonga/Groongaの制限を超えるため
•「最大インデックスサイズ: 256GByte」
•並列性能の向上
•障害時の影響範囲を最小化
![Page 36: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/36.jpg)
運用ノウハウ
![Page 37: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/37.jpg)
Kernel Tuning$ cat /etc/sysctl.conf# NUMAを無効にvm.zone_reclaim_mode = 0
# 物理メモリ以上のメモリ確保を許可vm.overcommit_memory = 1
# mmapで確保できる最大マッピング数vm.max_map_count = 5000000
![Page 38: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/38.jpg)
Linux Tuning (2)
# 透過的hugepageを切る$ echo 'never' > /sys/kernel/mm/transparent_hugepage/enabled
![Page 39: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/39.jpg)
my.cnf
[mysqld]table_open_cache = 多め!
MySQL 5.6ではデフォルト2000
![Page 40: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/40.jpg)
その他の工夫
![Page 41: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/41.jpg)
Splog/巨大記事対策•Mroongaにいれる1記事あたりの最大文字数の設定
➡Splog(spam + blog) の記事は大量のリンクを貼っていたり、自動生成した記事が多いため、1記事あたりの容量が増えがち
• ` ` やHTMLの終了タグの削除
![Page 42: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/42.jpg)
参照クエリの並列数制限
![Page 43: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/43.jpg)
並列度を上げると性能劣化
https://gist.github.com/kazeburo/9014939
0
37.5
75
112.5
150
1 2 3 4 5 6 7 8 16
参照クエリの並列度と処理時間
処理時間
並列度
http://redmine.groonga.org/issues/2335
![Page 44: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/44.jpg)
GET_LOCKで並列度制限# table名でlock
mysql> SELECT GET_LOCK(“article_index_0099”,30);
# 検索
mysql> SELECT article_id FROM article_index_0099 \ WHERE blog_id=30 AND status=1 \ AND MATCH(public_terms) AGAINST(? IN BOOLEAN MODE) \ ORDER BY article_datetime DESC LIMIT 10 OFFSET 0;
# 終わったらlockを解放
mysql> SELECT RELEASE_LOCK(“article_index_0099”)
![Page 45: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/45.jpg)
困っている事
![Page 46: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/46.jpg)
更新集中時の負荷
•記事の更新が集中した場合にロードアベレージが上がりやすい
•記事更新にもGET_LOCKが必要?
![Page 47: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/47.jpg)
たまに落ちる•masterだけじゃなくて参照が行われていないslaveもMySQLが落ちる
•落ちた時に一部のテーブルのindexが壊れるのか更新ができない状態になり、mysqldump && restoreが必要となる
まだ落ちるパターンが分かればバグレポートあげたい
![Page 48: blogサービスの全文検索の話 - #groonga を囲む夕べ](https://reader033.vdocuments.net/reader033/viewer/2022051016/559b77b01a28ab744f8b4891/html5/thumbnails/48.jpg)
以上です。