@[toc]
1. Install
-
解压:
sudo tar -zxvf elasticsearch-7.13.1-linux-x86_64.tar.gz -C /usr/local
- cd 到解压目录:
- 改名:sudo mv elasticsearch-7.13.1 elasticsearch
- 用户权限:sudo chown -R hadoop:hadoop elasticsearch
- 修改 es 配置:
- 取消主机限制
- 修改数据存储路径
- 取消主机限制
- 配置环境变量
vim ~/.bashrc
source ~/.bashrc
-
启动:elasticsearch
-
启动失败
-
根据提示查看日志:
- 三个问题
-
最大文件描述符量(4096)太低,解决如下:
- 切换 root 用户:
- vim /etc/security/limits.conf:65535 日志提示
* soft nofile 65535 * hard nofile 131070
- wq
- 重启:reboot
- 切换 root 用户:
-
最大虚拟内存区域太低,解决如下:
- vim /etc/sysctl.conf
vm.max_map_count=262144 # same as 65535
- wq
- 重启:reboot
- vim /etc/sysctl.conf
-
默认发现设置不适合生产使用,解决如下:
-
- 三个问题
-
再次启动:成功
-
访问
2. Learn
2.1 HTTP
略
2.2 JavaAPI
- Maven 依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>ElasticSearchLearn</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.13.1</version>
</dependency>
<!-- elasticsearch 的客户端 -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.13.1</version>
</dependency>
<!-- elasticsearch 依赖 2.x 的 log4j -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.0</version>
</dependency>
</dependencies>
</project>
- 使用:略
2.3 ES 主要术语
2.3.1 索引(Index)
- 索引就是一个拥有几分相似特征的文档的集合
- 一个索引由一个名字来标识(必须全部是小写字母),并且当我们要对这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字
- 一个集群中,可以定义任意多的索引
索引是逻辑名称空间,映射到一个或多个主分片,并且可以有零个或多个副本分片
2.3.2 类型(Type):略
- 类型是索引的逻辑上的分类/分区
- 在一个索引中,可以定义一种或多种类型
- 类型在各版本的变化
- 5.x:支持多种 Type
- 6.x:只能有一种 Type
- 7.x:默认不支持自定义索引类型(默认类型为_doc)
类比于关系数据库的表
2.3.3 文档(Document)
- 一个文档是一个可被索引的基础信息单元,也就是一条数据,文档以 JSON 格式来表示
- 在一个 index/type 里面,你可以存储任意多的文档
类似于关系数据库中的一行(不同之处在于索引中的每个文档可以具有不同的结构(字段),但是对于通用字段应该具有相同的数据类型)
2.3.4 字段(Field)
- 相当于于数据表的字段
2.3.5 映射(Mapping)
-
映射 是对处理数据的方式和规则方面做的一些限制,如:某个字段的数据类型、默认值、是否被索引等
2.3.6 分片(Shards)
- Elasticsearch 提供了将索引划分成多份的能力,每一份就称之为分片,每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上
- 当 Elasticsearch 在索引中搜索的时候, 它发送查询到每一个属于索引的分片(Lucene 索引,Elasticsearch 是基于 Lucene 搭建的),然后合并每个分片的结果到一个全局的结果集。
- 通过分片,一个索引可以存储超出单个节点硬件限制的大量数据,以及单个节点处理搜索请求响应太慢的问题
2.3.7 副本(Replicas)
- Elasticsearch 允许创建分片的一份或多份拷贝,这些拷贝叫做复制分片(副本)
- 副本的重要性
- 在分片/节点失败的情况下,提供了高可用性:因为这个原因,注意复制分片从不与原/主要(original/primary)分片置于同一节点上
- 扩展搜索量/吞吐量,因为搜索可以在所有的副本上并行运行
- 分片和复制的数量均可以在索引创建的时候指定,但在索引创建之后,只有复制的数量能动态地改变
2.3.8 分配(Allocation)
- 分配是将分片分配给某个节点的过程,包括分配主分片或者副本(如果是副本,还包含从主分片复制数据的过程),这个过程是由 master 节点完成的
3. ES 集成:略
3.1 Spring Data 框架集成
Spring Data’s mission is to provide a familiar and consistent, Spring-based programming model for data access while still retaining the special traits of the underlying data store. It makes it easy to use data access technologies, relational and non-relational databases, map-reduce frameworks, and cloud-based data services. This is an umbrella project which contains many subprojects that are specific to a given database. The projects are developed by working together with many of the companies and developers that are behind these exciting technologies. Official site
3.2 Flink 集成
4. ES Question
4.1 为什么要使用 ElasticSearch?
因为信息系统中的数据随着时间的推移、业务的发展等会变得非常多,并且业务中往往采用模糊查询(like %keyword%)进行数据的搜索,二模糊查询会导致查询引擎放弃索引,从而导致系统查询数据是通过全表扫描来查询,这在百万级别的数据库中,查询效率是非常低下的,但是我们使用 ES 做全文索引就可以将经常查询的系统功能的某些字段,如电商系统的商品表中的商品名、商品描述、价格放入 ES 索引库里,从而提高查询速度。
4.2 ElasticSearch 的 master 的选举流程
Elasticsearch 的 master 的选举是 ZenDiscovery 模块负责的,ZenDiscovery 模块主要包含 ping (节点之间通过 RPC 来发现彼此) 和 Unicast (单播模块包含一个主机列表以控制哪些节点需要 ping 通) 两个部分。
ES 针对所有可以成为 master 的结点 (即node.master设置为true的节点) 根据 nodeId 字典排序,每次选举每个节点都把自己所知道的节点排一次序,然后选出第一个节点,并暂且认为它是 master 节点。如果对某个节点的投票数达到一定的值(可以成为master节点的投票数要大于等于 n/2+1) 并且该节点自己也选举自己,那这个节点就是master;否则重新选举一直到满足上述条件。
master 节点的职责主要包括集群、节点和索引的管理,不负责文档级别的管理,而 data 节点可以关闭http功能
4.3 谈谈 Elasticsearch 集群脑裂问题的成因与解决方案?
-
成因
- 网络问题:集群间的网络延迟导致一些节点访问不到 master,而认为 master 挂掉了从而选举出新的 master,并对 master 上的分片和副本标红,分配新的主分片
- 节点负载:主节点的角色既为 master 又为 data,当访问量较大时可能会导致 ES 停止响应而造成大面积延迟,此时其他节点得不到主节点的响应会认为主节点挂掉了,会重新选取主节点
- 内存回收:data 节点上的 ES 进程占用的内存较大,引发 JVM 的大规模内存回收,造成 ES 进程失去响应
-
解决方案
- 针对网络问题导致的脑裂,可以通过减少误判的方法,即适当调大 discovery.zen.ping_ timeout 的值(节点状态的响应时间,默认为3s):如果 master 在响应时间的范围内没有做出响应应答,则判断该节点已经挂掉,通过调大 discovery.zen.ping_ timeout 的值可以一定程度上减少误判。
- 针对节点负载导致的问题,可以通过角色分离的方法,即限制节点的角色
- 主节点的配置为:node master: true,node data: false
- 从节点的配置为:node master: false,node data: true
- 选举触发:调整 discovery.zen.minimum_master_ nodes:1 参数(该参数是用于控制选举行为发生的最小集群主节点数量)以改变选举触发的条件
- 当备选主节点的个数大于等于 discovery.zen.minimum_master_ nodes 参数的值,且备选主节点中有该参数个节点认为主节点挂了,则进行选举,官方建议discovery.zen.minimum_master_ nodes的值为(n / 2) +1,其中 n 为主节点个数(即有资格成为主节点的节点个数)。
4.4 ES 搜索的流程?
搜索被执行成一个两阶段过程,我们称之为 Query Then Fetch;
- 在初始查询阶段时,查询会广播到索引中每一个分片拷贝(主分片或者副本分片):每个分片在本地执行搜索并构建一个匹配文档的大小为 from + size 的优先队列(PS:在搜索的时候是会查询Filesystem Cache 的,但是有部分数据还在 Memory Buffer,所以搜索是近实时的)
- 每个分片返回各自优先队列中所有文档的 ID 和排序值给协调节点,它合并这些值到自己的优先队列中来产生一个全局排序后的结果列表
- 接下来就是取回阶段,协调节点辨别出哪些文档需要被取回并向相关的分片提交多个 GET 请求;每个分片加载并丰富文档,如果有需要的话,接着返回文档给协调节点,一旦所有的文档都被取回了,协调节点返回结果给客户端
Query Then Fetch 的搜索类型在文档相关性打分的时候参考的是本分片的数据,这样在文档数量较少的时候可能不够准确, DFS Query Then Fetch 增加了一个预查询的处理,询问 Term 和 Document frequency,这个评分更准确,但是性能会变差
4.5 ES 部署时 Linux 的优化方法?
- 硬件
- 内存:64GB 内存的机器非常理想,但是32GB 和 16GB 的机器也很常见;不要少于 8GB。
- 更快的CPUs 与 更多的核心:两者选其一的话,选择更多的核心更好,因为多个内核提供的额外的并发远胜过稍微快一点点的时钟频率
- 采用 SSD (固态硬盘)
- 配置
- 通过设置 gateway.recover_after_nodes、 gateway.expected_nodes、 gateway.recover_after_time 可以在集群重启的时候避免过多的分片交换,这可能会让数据恢复从数个小时缩短为几秒钟
- 使用单播(默认单播)代替组播,以防止节点无意中加入集群
- 其它
- 避免集群跨越多个数据中心,并绝对避免集群跨越大的地理距离;
- 保持 应用程序的 JVM 与 服务器的 JVM 是完全一样的;
- 不要随意修改垃圾回收器(CMS)和各个线程池的大小;
- Lucene 使用了大量的文件,并且 Elasticsearch 在节点和 HTTP 客户端之间进行通信也使用了大量的套接字,所有这一切都需要足够的文件描述符;
4.6 GC 方面使用 ES 时需要注意什么?
- 倒排词典的索引需要常驻内存,无法 GC,需要监控 data node 上 segment memory 增长趋势
- 各类缓存(field cache, filter cache, indexing cache, bulk queue 等等)要设置合理的大小,并且要应该根据最坏的情况来看 heap 是否够用,也就是各类缓存全部占满的时候,还有 heap 空间可以分配给其他任务
- 避免返回大量结果集的搜索与聚合
4.7 在并发情况下, Elasticsearch 如果保证读写一致?
- 通过版本号使用乐观并发控制
- 对于写操作,一致性级别支持 quorum/one/all,默认为 quorum,即只有当大多数分片可用时才允许写操作
- 对于读操作,若设置 replication 为 sync(默认),则使得操作在主分片和副本分片都完成后才会返回;若设置 replication 为 async,则可以通过设置搜索请求参数 _preference 为 primary 来查询主分片,确保文档是最新版本
4.8 Elasticsearch 中的倒排索引是什么?
ES中的倒排索引其实就是 lucene 的倒排索引,区别于传统的正向索引, 倒排索引会在存储数据时将关键词和数据进行关联,保存到倒排表中,然后查询时,将查询内容进行分词后在倒排表中进行查询,最后匹配数据即可。
其它
- ES 集群监控
- elasticsearch-head 插件
- Kibana
- 字典树:百度百科
Source:尚硅谷 ES 教程