blogサービスの全文検索の話 - #groonga を囲む夕べ
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share

blogサービスの全文検索の話 - #groonga を囲む夕べ

  • 0 views
Uploaded on

 

More in: Internet
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
0
On Slideshare
0
From Embeds
0
Number of Embeds
1

Actions

Shares
Downloads
0
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

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