Upload
masahiro-nagano
View
9.406
Download
8
Embed Size (px)
Citation preview
blogサービスの全文検索の話
全文検索エンジンGroongaを囲む夕べ5長野雅広 (kazeburo)
Me•長野雅広 (Masahiro Nagano)•@kazeburo / github:kazeburo•Operations Engineer / Site Reliability
•LINE corp.• ISUCON 2013,2014 連覇
今日のお題
livedoor Blog•サービス開始11周年
•国内最大級
•blog開設数 570万件
•総記事数 3億件
•約100億PV/month
livedoor Blogを支える技術
•Reverse Proxy - Apache, Nginx
•Application - Perl, Go
•Cache - Memcached
•RDBMS - MySQL 4.0, 5.5
•Search Engine - Mroonga
どこで Mroonga が使われているか
blog内の記事検索blog横断の検索はありませんが、
3億件の記事が対象
Mroongaを採用した理由
競合• MySQLのLIKE検索
➡ 検索機能不足
➡ カテゴリやタグなどの絞り込みが面倒
• MySQL組み込みの全文検索
➡ 日本語非対応
• Elasticsearch
➡ Java/JVMの経験不足
➡ 大規模環境でのトラブルシューティングに不安
Mroonga
•MySQL! MySQL! MySQL!
➡レプリケーションやバックアップなどMySQLの知見が活かせる
•日本語で作者とコミュニケーション
検索サーバの構成
microservicesマイクロサービスっぽく作ってます
blogApp
blogApp
blogApp
cmsApp
cmsApp
cmsApp
記事表示 Service 記事編集 Service
SearchAPI
SearchAPI
IndexWorker
IndexWorker
Q4M MappingDB
検索 Serviceshard1 shard2 shard3
blogApp
blogApp
blogApp
cmsApp
cmsApp
cmsApp
記事表示 Service 記事編集 Service
SearchAPI
SearchAPI
IndexWorker
IndexWorker
Q4M MappingDB
検索 Service
記事追加
shard1 shard2 shard3
blogApp
blogApp
blogApp
cmsApp
cmsApp
cmsApp
記事表示 Service 記事編集 Service
SearchAPI
SearchAPI
IndexWorker
IndexWorker
Q4M MappingDB
検索 Service
記事追加
shard1 shard2 shard3
Queueing
blogApp
blogApp
blogApp
cmsApp
cmsApp
cmsApp
記事表示 Service 記事編集 Service
SearchAPI
SearchAPI
IndexWorker
IndexWorker
Q4M MappingDB
検索 Service
記事追加
shard1 shard2 shard3
Queueing
blog_idとshardのmapping
blogApp
blogApp
blogApp
cmsApp
cmsApp
cmsApp
記事表示 Service 記事編集 Service
SearchAPI
SearchAPI
IndexWorker
IndexWorker
Q4M MappingDB
検索 Service
記事追加
shard1 shard2 shard3
Queueing
blog_idとshardのmapping
INSERT!
blogApp
blogApp
blogApp
cmsApp
cmsApp
cmsApp
記事表示 Service 記事編集 Service
SearchAPI
SearchAPI
IndexWorker
IndexWorker
Q4M MappingDB
検索 Serviceshard1 shard2 shard3
blogApp
blogApp
blogApp
cmsApp
cmsApp
cmsApp
記事表示 Service 記事編集 Service
SearchAPI
SearchAPI
IndexWorker
IndexWorker
Q4M MappingDB
検索 Service
検索
shard1 shard2 shard3
blogApp
blogApp
blogApp
cmsApp
cmsApp
cmsApp
記事表示 Service 記事編集 Service
SearchAPI
SearchAPI
IndexWorker
IndexWorker
Q4M MappingDB
検索 Service
検索
shard1 shard2 shard3
blog_idとshardのmapping
blogApp
blogApp
blogApp
cmsApp
cmsApp
cmsApp
記事表示 Service 記事編集 Service
SearchAPI
SearchAPI
IndexWorker
IndexWorker
Q4M MappingDB
検索 Service
検索
shard1 shard2 shard3
blog_idとshardのmapping
SELECT
Mroonga サーバの構成
shard1 shard2 shard3
この中身
Shardの構成
master
slave slave
Shard N
Shardの構成
master
slave slave
Shard N
参照・更新は全てMaster
Slaveはバックアップ
ハードウェア
•Intel Xeon 6core/12thread * 2
•Memory 96GB
•PCI-E SSD
テーブルとスキーマ
スキーマ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
スキーマ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
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)
Table 分散
0001 0002 0003 0004 0005 0006
0007 ... ... ... ... 0144
0145 0146 0147 0148 0149 0150
SearchAPI
IndexWorker
blog_idで分散
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
Table分散を行う理由
•Mroonga/Groongaの制限を超えるため
•「最大インデックスサイズ: 256GByte」
•並列性能の向上
•障害時の影響範囲を最小化
運用ノウハウ
Kernel Tuning$ cat /etc/sysctl.conf# NUMAを無効にvm.zone_reclaim_mode = 0
# 物理メモリ以上のメモリ確保を許可vm.overcommit_memory = 1
# mmapで確保できる最大マッピング数vm.max_map_count = 5000000
Linux Tuning (2)
# 透過的hugepageを切る$ echo 'never' > /sys/kernel/mm/transparent_hugepage/enabled
my.cnf
[mysqld]table_open_cache = 多め!
MySQL 5.6ではデフォルト2000
その他の工夫
Splog/巨大記事対策•Mroongaにいれる1記事あたりの最大文字数の設定
➡Splog(spam + blog) の記事は大量のリンクを貼っていたり、自動生成した記事が多いため、1記事あたりの容量が増えがち
• ` ` やHTMLの終了タグの削除
参照クエリの並列数制限
並列度を上げると性能劣化
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
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”)
困っている事
更新集中時の負荷
•記事の更新が集中した場合にロードアベレージが上がりやすい
•記事更新にもGET_LOCKが必要?
たまに落ちる•masterだけじゃなくて参照が行われていないslaveもMySQLが落ちる
•落ちた時に一部のテーブルのindexが壊れるのか更新ができない状態になり、mysqldump && restoreが必要となる
まだ落ちるパターンが分かればバグレポートあげたい
以上です。