顿搜
09. ES集群相关概念介绍——ElasticSearch基础专栏
一、客户端节点
当主节点和数据节点都设置为false的时候,客户端节点只能处理路由请求、搜索、分发索引等操作
从本质上来说,客户端节点表现为智能负载平衡器。
独立的客户端节点在一个比较大的集群中是非常有用的,主要负责协调主节点和数据节点,
客户端节点加入集群后可以得到集群的状态,根据集群的状态可以直接进行路由请求。
二、数据节点
数据节点是存储索引数据的节点,主要对文档进行增删改查操作、聚合操作等。
数据节点对CPU、内存、IO资源要求较高,在优化的时候需要监控数据节点的状态,当资源不够的时候,需要在集群中添加新的数据节点。
三、主节点
主节点的主要职责是处理和集群操作相关的内容,如创建索引、删除索引、把分片分配给相关的节点等。
稳定的主节点对集群的健康是非常重要的,默认情况下,集群中的任何一个节点都有可能被选为主节点。
因为索引数据和搜索查询等操作会占用大量的CPU、内存、IO资源,所以为了确保集群的稳定性,分离主节点和数据节点是一个比较好的选择。
也就是说,主节点在进行配置时把node.data参数设置为false,表示主节点不会存储索引数据。
在一个生产环境集群中,我们可以对节点的职责进行划分,建议集群中设置3个以上的节点作为主节点,当现有的主节点出现故障时,这些节点可以被选举成为主节点,从而维护整个集群的状态。然后可以根据数据量设置一批数据节点,这些节点只负责存储数据,如果集群中索引数量较大,推荐在集群中再设置一批客户端节点(在配置文件中设置node.master: false和node.data: false),这些节点只负责处理用户请求,实现请求转发、负载均衡等功能。
四、节点发现
当新节点加入后,此节点会通过多播寻找集群中其他的节点并和发现的节点建立连接
实际上用户并不需要知道哪个节点是主节点,所有的操作请求可以分发到任意的节点上,而Elasticsearch内部会完成这些让用户感到“不明觉历”的工作
五、节点故障
当主节点发现超过3次Ping不通某一个节点,就会认为此节点宕机
| 配置 | 说明 |
|---|---|
| ping_interval | 节点多久Ping 一次的时间间隔,默认为 1秒 |
| ping_timeout | 等待响应时间的超时时间,默认为 30秒 |
| ping_retries | 失败或超时后重试的次数,默认为 3 次 |
六、集群状态更新
主节点是唯一一个能够更新集群状态的节点
一个时间段内主节点只能更新一个集群状态,并且将更改的集群状态发送给其他节点,当其他节点接收到状态时,先确认收到消息,但是此时并不更新到最新状态。
如果主节点在规定时间(discovery.zen.commit_timeout默认30秒)内没有收到大多数节点(大多数节点数量=discovery.zen.minimum_master_nodes参数的值)的确认,那么集群状态更新请求不会被通过。
一旦足够的节点响应了更新的消息,新的集群状态才会被提交,并且会发送一条消息给所有的节点。随后这些节点开始在内部更新至新的集群状态
当集群状态有了新的变化,都是主节点主动通知其他节点来同步集群状态的信息。
七、主节点选举
其他节点超过3次都没有Ping通主节点,则认为当前主节点出现了异常,集群会重新选举新的主节点
如果一些节点的node.master参数事先被配置为true,则表示这种节点在主节点发生故障的时候会参加选举
在多个节点选举的过程中,节点唯一标识值越小,则越有可能被选举为主节点
八、分片设置
PUT /dbindex/_settings
{
"number_of_shards": 1,
"number_of_replicas": 4
}如果有索引已经建立,那么修改的时候只能修改副本分片的数量,主分片数量不可以修改
- 避免分片过大
因为这样会对集群“从故障中恢复”造成不利的影响。尽管并没有关于分片大小的固定限值,但是开发和运维人员通常将50GB作为分片上限,而且这一限值在各种用例中都已得到了验证。
- 分片不可过小
分片过小会导致“段”(Segment,Elasticsearch中存储数据的空间块)过小,进而导致开销增加。用户要尽量将分片的平均大小控制在几GB到几十GB。对于时序型数据而言,分片大小通常介于20GB~40GB。
- 文档归并
由于单个分片的开销取决于“段”的数量和“段”的大小,因此通过文档归并(forcemerge)操作强制将较小的“段”合并为较大的“段”。这样做能够减少开销并改善查询的性能。
- 分片数量限制
每个节点上可以存储的分片数量与可用的堆内存大小成正比,但是Elasticsearch并未强制规定固定限值。
推荐将单个分片存储索引数据的大小控制在20GB左右,绝对不要超过50GB,分片的数量可以根据如下公式计算: 分片数量= 数据总量 / 20GB
九、段合并
在Elasticsearch中,写入和打开一个新段(Segment)的过程叫作刷新(Refresh)。
刷新操作并不需要每秒进行一次。如果有业务正在使用Elasticsearch索引中大量的日志文件,此时用户想要优化数据写入性能,可以通过设置refresh_interval参数进行优化,以降低索引的刷新频率,提高数据写入的性能
PUT /dbindex
{
"settings": {
"refresh_interval": "30s" // 设置时间时间为30秒,表示每30秒进行一次刷新
}
}
PUT /dbindex/_settings
{
"refresh_interval":-1 // 关闭自动刷新操作
}
PUT /dbindex/_settings
{
"refresh_interval":"1s" //开启刷新且刷新时间为1秒
}十、别名
10.1 索引别名
POST /_aliases
{
"actions" : [ // 给索引库test1创建别名alias1
{ "add" : { "index" : "test1", "alias" : "alias1" } }
]
}
POST /_aliases
{
"actions" : [ // 删除索引库对应的别名
{ "remove" : { "index" : "test1", "alias" : "alias1" } }
]
}
POST /_aliases
{
"actions" : [ // 一个别名关联多个索引库
{ "add" : { "indices" : ["test1", "test2"], "alias" : "alias1" } }
]
}
POST /_aliases
{
"actions" : [ // 索引别名指向新的索引库
{ "remove" : { "index" : "test1", "alias" : "alias1" } },
{ "add" : { "index" : "test2", "alias" : "alias1" } }
]
}以上语句先进行索引别名移除,然后创建索引别名。这个操作是具有原子性的,因此不需要担心短时间内别名不指向一个索引库
10.2 索引模板别名
索引模板为索引库指定别名,需要使用aliases关键字
PUT _template/templateds
{
"template": "log*",
"order": 0,
"settings": {
"number_of_shards":2
},
"aliases": {
"log-query":{} // 别名名称
},
"mappings": {
"properties": {
"name": {
"type": "keyword"
},
"id": {
"type": "long"
}
}
}
}
- 以上语句创建了一个名为templateds的索引模板名,索引模板的匹配值是"log*"
- 根据这个模板创建的索引,它们的别名都是log-query
POST / log1/_doc/1
{
"person_name": "张三",
"id": 1
}
POST / log2/_doc/1
{
"person_name": "李四",
"id": 2
}会自动为log1索引库和log2索引库创建相同的索引映射信息,而且log1和log2索引库的别名都是log-query
我们需要同时查询两个索引库的数据时,可以使用别名通过一条语句来查询
POST /log -query/_search
{
"size": 10
}十一、滚动查询
当索引库中数据量特别大的时候,深度分页的操作会给Elasticsearch集群的性能带来极大损耗。为了解决这个问题,Elasticsearch提供了滚动查询来避免这种情况
举例: 滚动查询,每次查询返回2条文档,并且数据量不能超过1MB,也就是说当一条文档信息超过1MB的时候,只会返回1条文档信息
POST /scrolldb/_search?scroll=1m
{
"size": 2,
"query": {
"match_all": {
}
}
}返回结果
{
#下次进行滚动查询需要带的标识
"_scroll_id" : "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFjZnWUJ1RTJYUmZhTzhCMVNUemNIX2cAAAAAAAFmQxZ5UWdMX25LNlJYR1JMeHltWlhkcVVR",
"took" : 4,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "scrolldb",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"name" : "张三",
"age" : 12
}
},
{
"_index" : "scrolldb",
"_type" : "_doc",
"_id" : "2",
"_score" : 1.0,
"_source" : {
"name" : "李四",
"age" : 10
}
}
]
}
}使用滚动查询返回信息的scroll_id继续查询,直到查不出为止,一般情况下当查询结果数量小于第一次查询执行的size时,结束查询
POST /_search/scroll
{
"scroll" : "1m",
"scroll_id" : " FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFjZnWUJ1RTJYUmZhTzhCMVNUemNIX2cAAAAAAAFmQxZ5UWdMX25LNlJYR1JMeHltWlhkcVVR "
}十二、跨集群查询
Elasticsearch集群可以处理容量在PB以上的数据,集群的规模可以是成百上千个节点。而跨集群查询允许用户查询多个集群中的数据
十三、 SQL语句
POST /_sql?format=txt
{
"query":"select * from sqldbindex" // 使用SQL操作Elasticsearch中的数据
}
- SQL语句中的表名称就是Elasticsearch中索引库的名称
十四、集群配置
#集群名称,需要保证3台服务器配置的名称一致
cluster.name: elasticsearch
#节点名称,不能重复
node.name: node-001
# 指定该节点是否有资格被选举成为主节点
node.master: true
#指定主节点的IP地址和端口号
cluster.initial_master_nodes: ["192.168.3.201:9300"]
# 指定该节点是否存储索引数据,默认为true
node.data: true
#配置本机的IP地址
network.host: 192.168.3.201
# 指定HTTP端口
http.port: 9200
# 设置节点间交互的TCP端口,默认是9300
transport.tcp.port: 9300
#设置集群中节点的初始列表,可以通过这些节点来自动发现新加入集群的节点
discovery.zen.ping.unicast.hosts:["192.168.3.201:9300","192.168.3.202:9301","192.168.3.203:9300"]
#跨域等配置
http.cors.enabled: true
http.cors.allow-origin: "*"
## 内存, 禁用swap
bootstrap.memory_lock: true