LoginSignup
15
16

More than 5 years have passed since last update.

メモ:Elasticsearchの書き込み性能を上げるためにやったこと

Last updated at Posted at 2016-12-26

背景

 サーバーに対して位置情報を含む500万レコード以上のデータがFTP経由で送られてくる。送られてくるときは1つのファイルにある独自の方法で圧縮されているが、このままでは位置情報を元にした検査ができないため、受け取った時点で展開して位置情報をサポートしたデータベースに書き込むのが今回の課題。
 なお、このファイルは5分毎に送られてくる。したがって書き込みに5分以上かかってはダメ。できたら アプリケーションでの展開データベースへの書き込み までを2分程度で終わらせて、その後は位置情報をもとに検索ができなければならない。という状況。
 
 親切な方から、位置情報ならElasticsearchがいいんじゃないかと教えてくれた。で、試行錯誤してなんとか2分ちょっとで書き込めるようになったので、そこまでにやったことの覚え書き。

【2017/1/3 追記】参考資料

このメモをキータにあげた際に、Jun Ohtaniさんより、以下の記事を案内いただきました。内容的に素晴らしく、Elasticsearchを使う方は読んでおいて損はないと思いました。
てか、このキータには書いてないことが沢山書いてあるので、こんなキータ読んでるよりこっち読んだ方が

Indexing Performance Tips
Performance Considerations for Elasticsearch Indexing
Performance Considerations for Elasticsearch 2.0 Indexing

JDK

Elasticsearchが稼働するJDKはOpenJDKでもいいが、Elasticsearch 2.4の公式ドキュメントでは Oracle JDK version 1.8.0_73 を推奨している。

ただ、両方やってみたけど書き込みにかかる時間は同じだった。以下は忘備録

Ubuntuでのインストール

$ sudo apt-get install oracle-java8-installer ca-certificates oracle-java8-set-default

ansible管理の場合は以下のように(参照サイト)。

#--------------------------------------------------------------
# aptにリポジトリを追加
#--------------------------------------------------------------
- apt_repository: repo='ppa:webupd8team/java'

#--------------------------------------------------------------
# ライセンスのAcceptをパスするように設定
#--------------------------------------------------------------
- name: Autoaccept license for Java8
  debconf: name='oracle-java8-installer' question='shared/accepted-oracle-license-v1-1' value='true' vtype='select'

#--------------------------------------------------------------
# Oracle JDK8をインストール
#--------------------------------------------------------------
- name: Install Oracle JDK8
  apt: name={{item}} state=latest
  with_items:
    - oracle-java8-installer
    - ca-certificates
    - oracle-java8-set-default

設定ファイル

threadpool.index.queue_sizethreadpool.bulk.queue_size は無制限の -1 を設定。

/etc/elasticsearch.yml
threadpool.index.queue_size: -1
threadpool.bulk.queue_size: -1

起動ファイル

ES_HEAP_SIZE は実メモリの半分くらい。ただしあまり大きいとJavaのGCが走るのに時間がかかってしまうため、31GBを超えてはいけないとのこと。
今回のインスタンスは128GB積んでるものを使用したため、 31G に設定。

/etc/init.d/elasticsearch
ES_HEAP_SIZE=31g
MAX_OPEN_FILES=165535
MAX_LOCKED_MEMORY=unlimited

パラメータ調整

number_of_replicas0 に設定してレプリカが作られないようにする。さらに refresh_interval-1 に設定して書き込みが終わるまでインデキシングが行われないようにする(すべての書き込みが終わったらアプリケーション側からインデキシングを指示する)。

$ curl -XPUT http://localhost:9200/index_name/_settings -d '
{ "index" : { "number_of_replicas" : 0,  "refresh_interval" : -1 } }'

ディスク

当然、ディスクが速い方が書き込みも早い。SSDが使えるならSSDがいい。

【反則技】Ramdiskを使う

SSDへの書き込みと比べて書き込み速度が特別改善されなかったので、最終的に今回はRamdiskを使用しなかった。以下は忘備録

今回の場合は、データの永続性は必要ない上に溢れるほどメモリがあるため、Ramdiskを使ってみた。なんと15GBをRAMディスクとして使用してみる。

/dev/shm /ramdisk ramfs size=15360m 0 0

マウント

$ sudo mount -a

保存先ディレクトリを作成

$ mkdir /ramdisk/elasticsearch

起動ファイルを修正

/etc/init.d/elasticsearch
DATA_DIR=/ramdisk/elasticsearch/$NAME

再起動

$ /etc/init.d/elasticsearch restart

クライアント

今回は諸事情でアプリケーションにErlang/OTPを採用。 Erlang/OTP + worker_pool で200プロセスからなるプロセスプールを作り、すべてのプロセスから並列にElasticsearchにbulk_indexで書き込むようにした。

15
16
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
16