备注:为了提高Elasticsearch的写入性能所做的事情

背景

通过FTP传输超过500万条包含位置信息的记录数据到服务器。在传输过来时,它们被以一种特定的方法压缩在一个文件中,但是这样的话不能进行基于位置信息的检索,所以解压并将位置信息写入支持位置信息的数据库是本次的挑战。

此外,该文件每5分钟传送一次。因此,写入操作不能超过5分钟。最好能在应用程序展开和写入数据库这两个步骤在2分钟左右完成,之后必须能根据位置信息进行检索。

一个热心的人告诉我,如果是位置信息,Elasticsearch可能是一个不错的选择。所以经过一番尝试和努力,我终于能在2分钟多一点的时间内完成写入操作了。以下是我在此之前所做的一些记录。

【2017/1/3 更新】参考资料 。

当我将这个备忘录给了桂子时,大谷准先生向我介绍了以下文章。内容非常出色,我认为使用Elasticsearch的人应该阅读一下,不会有损失。

而且,这个备忘录里面没有写的事情在这里写了很多,所以比读这个备忘录更值得读这个。

Elasticsearch索引性能技巧
Elasticsearch索引性能考虑因素
Elasticsearch 2.0索引性能考虑因素

JDK(Java Development Kit)是Java开发工具包。

在公式文档中,Elasticsearch 2.4推荐使用Oracle JDK 1.8.0_73作为运行Elasticsearch的JDK,虽然OpenJDK也可以。

然而,尽管我尝试了两种方法,但写入所需的时间是相同的。以下是备忘录。

在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_size 和 threadpool.bulk.queue_size 被设置为无限制的 -1。

threadpool.index.queue_size: -1
threadpool.bulk.queue_size: -1

启动文件

ES_HEAP_SIZE 设置为实际内存的一半左右。然而,如果设置得过大,会导致Java的垃圾回收花费很长时间,因此不能超过31GB。

由于这次使用的是装有128GB的实例,所以将其设置为31G。

ES_HEAP_SIZE=31g
MAX_OPEN_FILES=165535
MAX_LOCKED_MEMORY=unlimited

参数调整

将number_of_replicas设置为0,以防止创建任何副本。另外,将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

修改启动文件

DATA_DIR=/ramdisk/elasticsearch/$NAME

重新启动

$ /etc/init.d/elasticsearch restart

客户

因为种种原因,本次决定在应用程序中采用Erlang/OTP。我们通过Erlang/OTP + worker_pool构建了一个包含200个进程的进程池,并且让所有进程并行地使用bulk_index将数据写入Elasticsearch。

广告
将在 10 秒后关闭
bannerAds