行业报告 AI展会 数据标注 标注供求
数据标注数据集
主页 > 机器学习 正文

Elasticsearch 在贝壳搜索的部署实践

1. 引言

Elasticsearch(简称 ES) 是一个基于 Lucene 的搜索引擎,使用 java 语言进行开发,RESTful web 接口进行交互,不同语言很容易开箱即用。同时 ES 完整生态中包含了 elasticsearch、logstash、kibana(3 个组合简称 ELK)、Beats、APM 等多个组件。ES 的简单快捷部署、成熟的生态、稳定的服务为搜索引擎与日志分析带来了极大的便利。在贝壳搜索架构的技术迭代中,也从 Solr Cloud 迁移到了 ES 上。

2.Elasitcsearch 基本概念

在介绍安装与部署之前先了解一下 ES 的基本概念。

  • Cluster(集群)

  • 集群是由一个或者多个 node 组成,进行跨节点的数据存储于查询功能。

  • Node(节点)

  • 是集群组成部分,每个节点都可提供对集群的查询和搜索功能。

  • 每个节点由唯一的名字进行标识,默认情况下使用 UUID,node 通过集群名称与集群地址加入集群。

  • node 可扮演 master、data、ingest、tribe 等不同的角色,不同的角色可以同时存在。例如一个 node 节点作为 master 角色的同时也可以为 data 角色。

  • Index(索引)

  • 是文本集合,类似与 mysql 中的表。

  • 存在 mapping 对索引字段结构、查询分词类型、写入分词类型等属性进行定义。

  • 通过 settings 对索引进行备份、分片、最大查询数目、分词器、refresh 等进行设置。

  • Document(文本)

  • 是集群中的最基本的存储信息,每个 document 存在唯一的 ID。

  • 每个文本以 json 格式进行存储。

  • Shard(分片)

  • 每个 index 由多个 shard 组成,每个 shard 是一个单独的 Lucene 索引,用来存储真正的文本数据,每个 shard 最多存储 2,147,483,519(Integer.MAX_VALUE - 128) 个 document。

  • 查询与写入的时候可通过 routing 字段进行路由到不同的分片上。

  • replica(备份)

  • 每个 shard 会存在主分片与备份分片,为保证高可用,同一个 shard 无论主备分片,不会存储在同一个 node 节点上。

3.Elasticsearch 部署实践

安装部署一个完整的高可用集群主要有以下几个步骤。

  • 官方下载、解压

  • 修改配置

  • 加密传输

  • 数据备份

  • 集群监控

  • 性能测试

1. 官方下载

当前最新版本 6.5,官方下载地址见 [1],下载后有 30 天试用版。试用版中支持账号密码、报警、Machine Learning、以及最新扩集群备份等特性。试用期结束后,转为基础版,影响较大的是账号密码验证、报警等功能不再支持。

2. 修改配置

修改配置主要有三部分配置:linux 系统配置、elasticsearch.yml 配置、jvm.options 配置。

2.1 修改 linux 配置 (需要 root 权限)

  • 修改 linux 服务器文件句柄打开数目限制。

通过使用命令 ulimit-n65536或者修改 /etc/security/limits.conf文件,在文件中添加 user-nofile65536来修改操作系统对文件句柄的限制。

  • 调高线程数目限制。

ES 中使用的线程池为不同的操作,高并发下可能需要创建大量的线程,因此官方建议至少调高到 4096。通过修改 /etc/security/limits.conf文件,在文件中添加 user-nproc4096

  • 修改虚拟内存限制。

ES 默认使用 mmapfs 目录来存储其索引。mmap 计数的默认操作系统限制可能太低,这可能导致内存不足异常,在 /etc/sysctl.conf 文件,添加 vm.max_map_count=262144,并执行 sysctl-p使配置生效。

  • 禁用文件系统缓存 swap。

因为这可能使得 JVM 的堆甚至正在执行的文件被交换到磁盘上,通过 sudo swapoff-a命令进行关闭交互区。或者在 /etc/sysctl.conf文件,添加 vm.swappiness=1, 减少内核交换的倾向,同时仍然允许在紧急条件下使用系统交换。

包含但不限于以上 linux 配置修改,修改之后,ES 即可以成功启动。

2.2 修改 elasticsearch.yml 文件

修改位于下载目录中 config 下的 elasticsearch.yml 文件,以下配置文件与生产环境配置文件有出入,附带注释,供参考。

1.  `# ---------------------------------- Cluster -----------------------------------`

2.  `#`

3.  `# Use a descriptive name for your cluster:`

4.  `# 集群名称`

5.  `cluster.name: cluster-test`

6.  `# ------------------------------------ Node ------------------------------------`

7.  `# Use a descriptive name for the node:`

8.  `# 节点名称`

9.  `node.name: node-name`

10.  `# 为该节点设置角色,如上介绍,一个节点可同时为多个角色,如果都为false,则为协调节点`

11.  `node.master:  true`

12.  `node.data:  true`

13.  `node.ingest:  false`

14.  `# ----------------------------------- Paths ------------------------------------`

15.  `#`

16.  `# Path to directory where to store the data (separate multiple locations by comma):`

17.  `# 数据存储路径`

18.  `path.data:  /home/work/data/elasticsearch/data`

19.  `#`

20.  `# Path to log files:`

21.  `# 日志存储路径,包含执行日志与慢查询等日志,慢查询可通过修改log4j2.properties文件来设置`

22.  `path.logs:  /home/work/data/elasticsearch/logs`

23.  `#`

24.  `# ----------------------------------- Memory -----------------------------------`

25.  `#`

26.  `# Lock the memory on startup:`

27.  `#启动的时候是否 锁定内存与弃用系统过滤器`

28.  `bootstrap.memory_lock:  true`

29.  `bootstrap.system_call_filter:  false`

30.  `#`

31.  `#`

32.  `# ---------------------------------- Network -----------------------------------`

33.  `#`

34.  `# Set the bind address to a specific IP (IPv4 or IPv6):`

35.  `#发布地址`

36.  `network.host:  127.0.0.1`

37.  `#`

38.  `# Set a custom port for HTTP:`

39.  `#`

40.  `#jmxport:7300`

41.  `提供的http端口`

42.  `http.port:  8300`

43.  `用来不同Node节点之间进行tcp交互的端口`

44.  `transport:`

45.  ` tcp:`

46.  `   port:  8309`

47.  `   compress:  true`

48.  `   connect_timeout:  30s`

50.  `http.cors.enabled:  true`

51.  `http.cors.allow-origin:  "*"`

52.  `http.cors.allow-headers:  Authorization,Content-Type`

53.  `# 用到docker的时候,因为dockerIP与宿主机IP不同,端口也可能不同,因此需要指定发布地址与端口`

54.  `http.publish_host:  10.26.9.44`

55.  `http.publish_port:  8309`

56.  `#`

57.  `# For more information, consult the network module documentation.`

58.  `#`

59.  `# --------------------------------- Discovery ----------------------------------`

60.  `#`

61.  `# Pass an initial list of hosts to perform discovery when new node is started:`

62.  `# The default list of hosts is ["127.0.0.1", "[::1]"]`

63.  `# 服务发现所配置的node节点`

64.  `discovery.zen.ping.unicast.hosts:  ["192.168.0.1:9201","192.168.0.2:9201","192.168.0.3:9201"]`

65.  `#℡`

66.  `# Prevent the "split brain" by configuring the majority of nodes (total number of master-eligible nodes / 2 + 1):`

67.  `# 至少2个节点存活`

68.  `discovery.zen.minimum_master_nodes:  2`

70.  `#ping 选主节点超时`

71.  `discovery.zen.ping_timeout:  5s`

72.  `#ping 其它节点的超时时间`

73.  `discovery.zen.fd.ping_timeout:  30s`

74.  `discovery.zen.fd.ping_retries:  6`

75.  `discovery.zen.fd.ping_interval:  10s`

76.  `#如果没有主节点 阻塞写操作`

77.  `discovery.zen.no_master_block: write`

78.  `#`

79.  `# For more information, consult the zen discovery module documentation.`

81.  `#增加查询与写入的队列长度`

82.  `thread_pool:`

83.  `   search:`

84.  `       queue_size:  2048`

85.  `   index:`

86.  `       queue_size:  1024`

87.  `# ---------------------------------- Various -----------------------------------`

88.  `#`

89.  `# Require explicit names when deleting indices:`

90.  `#是否可以自动创建索引以及模糊匹配进行删除修改等操作,如果需要打开则设置为true`

91.  `action.destructive_requires_name:  false`

92.  `+.*,-*意思是可以自动创建以  .开头的索引`

93.  `action.auto_create_index:  +.*,-*`

95.  `# 最大限制bool查询的条数`

96.  `indices.query.bool.max_clause_count:  4096`

98.  `相同shard,不能分布在同一个IP机器上,如果一台机器上部署多个节点,使用该配置增加安全性`

99.  `cluster:`

100.  ` routing:`

101.  `   allocation:`

102.  `     same_shard.host:  true`

103.  `# ---------------------------------- x-pack ----------------------------------`

104.  `# x-pack相关配置以及机密连接证书配置`

105.  `# 打开账号密码认证,6.X之后需要使用加密传输才能进行账号密码认证`

106.  `# 创建CA证书`

107.  `xpack.security.enabled:  true`

108.  `xpack.security.transport.ssl.enabled:  true`

109.  `xpack.ssl.verification_mode: certificate`

110.  `xpack.security.transport.ssl.verification_mode: certificate`

111.  `xpack.security.transport.ssl.keystore.path: certs/elastic-certificates.p12`

112.  `xpack.security.transport.ssl.truststore.path: certs/elastic-certificates.p12`

113.  `xpack.ml.enabled:  false`

114.  `node.ml:  false`

115.  `xpack.security.audit.enabled:  true`

116.  `xpack.monitoring.exporters.my_local:`

117.  ` type:  local`

118.  ` use_ingest:  false`

2.3 修改文件 jvm.options

ES 使用 java 语言开发,那不可避免的就是使用了 JVM。该文件在下载目录的 config 下,包含了 ES 的 JVM 配置,介绍以下几个关键参数与调优建议。

  • -Xms 与 -Xmx设置 JVM 堆大小,建议设置小于 32G,并且不要超过服务器内存大小 50%。

如果 JVM 堆小于 32 GB,采用一个内存对象指针压缩技术,这可以大大降低内存的使用:每个指针 4 字节而不是 8 字节。Lucene 能很好利用文件系统的缓存,它是通过系统内核管理的。如果没有足够的文件系统缓存空间,性能会受到影响。 此外,专用于堆的内存越多意味着其他所有使用 doc values 的字段内存越少。

  • -XX:+UseG1GC

建议使用使用 G1 收集器。-XX:MaxGCPauseMillis=200、-XX:G1HeapRegionSize=32M、-XX:InitiatingHeapOccupancyPercent=70 等配置;具体参数含义可见 oracle 官网 [2] 介绍。对于搜索引擎来说,秒级别的 stop the world 是不可容忍的,通过配置最长暂停时间设置目标值 200ms,来减少回收停顿时间。

  • -XX:+HeapDumpOnOutOfMemoryError

当 ES 发生 OOM 异常的时候, 可以保存堆内存数据到设置的固定目录,可用来分析 ES 节点异常原因。

其他一些常规 JVM 配置,可根据配置文件中介绍修改,不再在这里介绍。
至此,修改完以上介绍的配置之后,可直接启动了。启动后,白金版功能特性有一个月的试用期。

3. 加密传输

ES 从 6.0 开始,如果需要使用 X-pack 安全功能,要求 SSL/TLS 加密传输。通过以下步骤进行加密传入:

  • xpack.security.enabled 设置为 true。

刚下载的使用的是试用版的 license,则默认的该值为 false,需要在 elasticsearch.yml 配置文件中设置为 true。

  • 为集群生成安全证书。

使用 elasticsearch-certutil ca命令,生成一个默认名称为 elastic-stack-ca.p12的文件,在生成改文件的时候,会提示输入一个保护该证书的密码。构建集群则需要将该证书拷贝到其他机器上

  • 为集群中的每个节点生成私钥、安全证书。

使用 bin/elasticsearch-certutil cert--ca elastic-stack-ca.p12命令生成一个默认名称为 elastic-certificates.p12文件,包含了节点证书、节点秘钥,CA 证书。如果想根据每个节点 hostname 查实, bin/elasticsearch-certutil cert可通过使用 –name,–dns,–ip 等参数生成不同的证书。如果不使用,则可共用相同证书,直接将该文件拷贝到其他机器上。在生成该文件的时候,同时会输入一个保护该证书的密码。拷贝到其他集群上使用该证书的时候,需要输入该密码

  • 增加证书相关配置
1.  ` xpack.security.enabled:  true  //开启安全认证`

2.  ` xpack.security.transport.ssl.enabled:  true  //使用加密传输`

3.  `  xpack.ssl.verification_mode: certificate //只通过证书认证,如果有需要,可更加严格的进行机器认证`

4.  `  xpack.security.transport.ssl.verification_mode: certificate`

5.  `  xpack.security.transport.ssl.keystore.path: certs/elastic-certificates.p12 //指定证书所在路径`

6.  `  xpack.security.transport.ssl.truststore.path: certs/elastic-certificates.p12`

  • 添加证书到秘钥库

使用 bin/elasticsearch-keystore add xpack.security.transport.ssl.keystore.secure_passwordbin/elasticsearch-keystore add xpack.security.transport.ssl.truststore.secure_password命令,将秘钥添加到 ES 的秘钥库中

4. 数据备份

为了增加集群的稳定性与数据安全性,每天对索引数据进行快照备份。现在 ES 提供了 S3、Hadoop、谷歌云等多种备份到共享存储上的插件,由于公司内部大数据集群比较完善,因此采用将快照数据备份到 HDFS 上。

4.1Hadoop HDFS 插件安装

使用 bin/elasticsearch-plugin install repository-hdfs命令安装该插件

4.2 连接 Hadoop 集群

为每个 ES 节点安装玩插件之后,需要为节点所在的机器确认能与 Hadoop 客户端进行连接。如果集群中一个节点在启动的时候,未与 Hadoop 连接通,则需要将该节点移除,或者重启该节点。公司内部 Hadoop 使用了 kerberos 作为安全认证,需要使用 keytab,获取到 keytab 之后,在 config 目录下创建 repository-hdfs 目录,将 keytab 名称改为 krb5.keytab,然后使用 keytab 验证是否能连接通 Hadoop 集群

4.3 配置仓库

与 Hadoop 联通后,创建仓库。在创建仓库的时候,应该执行在 HDFS 下的路径,快照数据存储在该路径下。同时也应该对写入与恢复速度进行限制,防止在进行快照备份与恢复的情况下,将网络 IO 打满,影响正常业务的使用。

1.  `PUT _snapshot/hdfs_repository`

2.  `{`

3.  ` "type":  "hdfs",`

4.  `   "settings":  {`

5.  `   "uri":  "hdfs://nn-cluster",`

6.  `   "path":  "/user/search/elasticsearch/repositories"`

7.  `   "compress":"true",`

8.  `   "max_restore_bytes_per_sec":"300mb",`

9.  `   "max_snapshot_bytes_per_sec":"100mb", `

10.  `   "security.principal":  "search/_HOST@HADOOP.COM",`

11.  ` }`

12.  `}`

4.4 将集群上的数据,选择性的备份

在备份集群上数据的时候,可能会进行选择性的备份数据,可通过模糊匹配的方式进行索引的批量选取

1. put _snapshot/hdfs_repository/snapshot_1

2.  `{`

3.  `   "indices":"+白名单索引,-黑名单索引"`

4.  `}`

4.5 从集群上恢复数据

可以选择性的从仓库中恢复索引,如果未指定,则将该快照下的所有索引恢复到当前集群中。

POST _snapshot/仓库名称/快照名称/_restore
{
    
"indices":"索引名称"
}

4.6 意义

通过每天在业务低峰期将 ES 集群中的重要索引数据定时备份到 HDFS 上,可以增加数据的安全性,如果多个集群共用相同的 HDFS 目录,则可进行跨集群恢复。例如将 A 集群中的数据快照备份到仓库中,B 集群同样可以使用该快照,恢复到 B 集群中。当一个集群出现故障的时候,可快速在另一个集群中,将数据恢复到备份的时间点。再结合我们引入 docker 部署 ES 集群,可分钟级部署一个新集群,使用快照恢复数据。在一个集群完全不可用的情况下,分钟级就可重建一个相同的集群提供服务。

同时如果有数据回溯需求或者开发、测试、线上等不同环境跨集群拷贝索引等需求,也可使用快照进行拷贝。

5. 集群监控

5.1 性能监控

性能监控包含主要的三大资源:磁盘、CPU、内存

5.1.1 通过 kibana 监控

安装 kibana,安装后,每个 Node 节点的 CPU、内存、QPS、查询队列、segment 数目等信息都可在界面中看到。
如下图所示

5.1.2 通过 grafana 监控报警

kibana 虽然对每个节点都有详细的监控,但是无法在一个界面中展现出整个集群的状态,而且 kibana 的报警机制并不完善。通过 grafana 读取 ES 中内置索引 .monitoring-es-6-*数据,索引中包含了对整个集群的监控信息。可对整个集群甚至多个集群的状态进行监控与报警。在 grafana 中配置阈值,超过阈值时候讲报警信息发送到指定 API 进行微信、短信、邮件等报警处理。

5.2 慢查询监控

对搜索引擎来说,查询所花费的时间是至关重要的,因此对于每个索引可设置慢查询阈值,目前线上设置的为 100ms,超过 100ms 时候会打印出所有的慢查询请求,随着集群 cluster 数目与节点 node 数目增多,对于慢查询的监控也是非常有必要的。通过使用 rsyslog+kafka+logstash+Elasticsearch+Grafana 对慢查询日志进行统计收集后进行监控报警

至此,一个完整的高可用集群搭建完毕!!!

6. 性能测试

集群搭建好,选择多少 Node 节点合适呢,不同的 Node 扮演什么角色呢。通过对搭建好的 ES 集群进行压力测试,来根据业务规模,预估 ES 集群。因为 ES 检索会存在缓存,所以不适合使用 apacheAB 进行压力测试,需要模拟线上真实请求进行测试。以下压测为线上一个集群部署服务之前进行的测试,与线上使用的多个集群中可能存在出入供参考:

6.1 集群规模

ES 集群: 3 台 master+6 台 data

index 索引: 500 万左右 Document,1 个 shard,5 个 replica

客户端: 使用 6 台直接连接 ES 的搜索客户端

6.2 压力测试

复制贝壳找房线上搜索请求,结论如下:

请求总数 408 错误 错误率 QPS 响应时间
1200000 次 60 条 0.005% 5402.36 18.21ms

成功率统计速率监控

6.3 小结

对集群进行更高压力测试,超时错误增多,响应时间也同比上升。为保证搜索时效性,并且 20ms 以内将数据返回与集群的稳定性,因此选择了资源与效果的权衡,使用当前 3+6 节点提供 5000QPS 线上搜索。当然不同的集群也要根据应用场景的不同,进行集群规模与参数的一些调整,例如日志集群多用于写可适当调整写入队列等参数。

在线上使用的时候,客户端可以使用 sniffer[3] 与集群中每个节点获得连接,采用轮询的方式与集群进行数据交互,既可以防止配置中只连接的某几个节点而导致压力过大,又可以动态的添加节点后直接与新增节点获得连接。

4. 高可用集群架构

4.1 跨机房部署

为了保证数据的安全性与集群容错性,采用冷备跨集群部署。通过 index 模块,双写到不同机房的 ES 集群,保持主备集群都可用,对外提供搜索服务,正常情况下,同一机房读取模块使用当前机房的集群提供服务,一旦当前机房网络出现问题,则降级切换到远程其他机房。有跨机房备份之后,大大提高了集群的安全性与可用性。

4.2 业务隔离

虽然一个 ES 集群能够很容的动态扩展,但是大量业务使用同一个集群带来的风险是比较高的,因此建议采用多集群部署,进行业务隔离,避免业务之间的相互干扰,提高稳定性。

4.3 容器化部署

使用 Docker 容器化部署 ES 节点,既可充分利用机器资源,也进行 CPU、内存、磁盘、网络等资源隔离,避免不同集群之间相互干扰。

5. 总结

elasticsearch 是一个快速迭代的开源组件,迭代更新非常迅速,很方便用于搜索引擎和日志分析。本文主要介绍了一个高可用集群完整的安装部署实践,在使用的过程中如何对集群进行配置、监控、测试、数据备份,以及最后介绍我们的高可用架构,使用 docker 容器支持多个机房进行主备,K8s 编排快速创建集群。希望本文对于计划使用 Elasticsearch 的维护者可以带来一些有用的信息。

6. 参考文献

[1]. https://www.elastic.co/downloads/elasticsearch
[2]. https://www.oracle.com/technetwork/cn/articles/java/g1gc-1984535-zhs.html
[3]. https://www.elastic.co/guide/en/elasticsearch/client/java-rest/master/sniffer.html

微信公众号

声明:本站部分作品是由网友自主投稿和发布、编辑整理上传,对此类作品本站仅提供交流平台,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,不为其版权负责。如果您发现网站上有侵犯您的知识产权的作品,请与我们取得联系,我们会及时修改或删除。

网友评论:

发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
SEM推广服务

Copyright©2005-2028 Sykv.com 可思数据 版权所有    京ICP备14056871号

关于我们   免责声明   广告合作   版权声明   联系我们   原创投稿   网站地图  

可思数据 数据标注

扫码入群
扫码关注

微信公众号

返回顶部