- 核心概念
- 节点类型
- 分片
- 集群搭建
- ES安全认证
- 集群内部安全通信
- 生产环境常见集群部署方式
- 单一角色
- 增加节点水平扩展
- 读写分离架构
- 异地多活架构
- Hot & Warm 架构
- 集群容量规划
- 产品信息库搜索
- 时间序列的数据
核心概念
-
ES集群架构的优势
- 提高系统的可用性,部分节点停止服务,整个集群的服务不受影响
- 存储的水平扩容
-
集群
- 配置文件或者在命令行中
-E cluster.name=es-cluster
设定集群名(默认 elasticsearch) - 不同的集群通过不同的名字来区分
- 配置文件或者在命令行中
-
节点
- 节点是一个 Elasticsearch 的实例(JAVA 进程)
- 每一个节点在启动之后,会分配一个UID,保存在data目录下
- 节点名通过配置文件或者启动时
-E node.name=node1
指定
节点类型
-
节点类型
- Master Node:主节点
- Master eligible nodes:可以参与选举的合格节点
- Data Node:数据节点
- Coordinating Node:协调节点
- 其他节点
-
Master eligible nodes 和 Master Node
- 每个节点启动后,默认就是一个Master eligible节点(设置
node.master : false
禁止) - Master-eligible节点可以参加选主流程,成为Master节点
- 当第一个节点启动时候,它会将自己选举成Master节点
- 每个节点上都保存了集群的状态,只有Master节点才能修改集群的状态信息
- 所有的节点信息
- 所有的索引和其相关的Mapping与Setting信息
- 分片的路由信息
- Master Node的职责
- 处理创建,删除索引等请求,负责索引的创建与删除
- 决定分片被分配到哪个节点
- 维护并且更新Cluster State
- Master Node的最佳实践
- Master节点非常重要,在部署上需要考虑解决单点的问题
- 为一个集群设置多个Master节点,每个节点只承担Master的单一角色
- 选主的过程
- 互相Ping对方,Node ld 低的会成为被选举的节点
- 其他节点会加入集群,但是不承担Master节点的角色
- 一旦发现被选中的主节点丢失,就会选举出新的Master节点
- 每个节点启动后,默认就是一个Master eligible节点(设置
-
Data Node & Coordinating Node
- Data Node
- 可以保存数据的节点,叫做Data Node,负责保存分片数据
- 节点启动后,默认就是数据节点(
node.data : false
禁止) - 由Master Node决定如何把分片分发到数据节点上
- 通过增加数据节点可以解决数据水平扩展和解决数据单点问题
- Coordinating Node
- 负责接受Client的请求, 将请求分发到合适的节点,最终把结果汇集到一起
- 每个节点默认都起到了Coordinating Node的职责
- Data Node
-
其他节点类型
- Hot & Warm Node:不同硬件配置的Data Node,用来实现Hot & Warm架构,降低集群部署的成本
- Ingest Node:数据前置处理转换节点,支持pipeline管道设置,可以使用ingest对数据进行过滤、转换等操作
- Machine Learning Node:负责跑机器学习的Job,用来做异常检测
- Tribe Node:连接到不同的Elasticsearch集群,并且支持将这些集群当成一个单独的集群处理
分片
- 分片 (Primary Shard & Replica Shard)
- 主分片(Primary Shard)
- 用以解决数据水平扩展的问题
- 通过主分片,可以将数据分布到集群内的所有节点之上
- 一个分片是一个运行的Lucene的实例
- 主分片数在索引创建时指定,后续不允许修改,除非Reindex
- 用以解决数据水平扩展的问题
- 副本分片(Replica Shard)
- 用以解决数据高可用的问题
- 副本分片是主分片的拷贝
- 副本分片数,可以动态调整
- 增加副本数,还可以在一定程度上提高服务的可用性
- 读取的吞吐
- 用以解决数据高可用的问题
- 主分片(Primary Shard)
# 指定索引的主分片和副本分片数
PUT /blogs
{"settings":{"number_of_shards":3,"number_of_replicas":1}}
- 分片的设定:需要提前做好容量规划
- 分片数设置过小
- 导致后续无法增加节点实现水平扩展
- 单个分片的数据量太大,导致数据重新分配耗时
- 分片数设置过大
- 影响搜索结果的相关性打分,影响统计结果的准确性
- 单个节点上过多的分片,会导致资源浪费,同时也会影响性能
- 7.0 开始,默认主分片设置成 1,解决了over-sharding(分片过度)的问题
- 分片数设置过小
集群搭建
- 配置文件
elasticsearch.yml
# 指定集群名称,集群内的节点必须一致
cluster.name: es‐cluster
# 指定节点名称,每个节点名字唯一
node.name: node‐1
# 是否有资格为master节点,默认为true
node.master: true
# 是否为data节点,默认为true
node.data: true
# 绑定ip,开启远程访问,可以配置0.0.0.0
network.host: 0.0.0.0
# 用于节点发现
discovery.seed_hosts: ["es‐node1", "es‐node2", "es‐node3"]
# 7.0新引入的配置项,初始仲裁,仅在整个集群首次启动时才需要初始仲裁
# 该选项配置为node.name的值,指定可以初始化集群节点的名称
cluster.initial_master_nodes: ["node‐1","node‐2","node‐3"]
# 解决跨域问题
http.cors.enabled: true
http.cors.allow‐origin: "*"
GET /_cat/nodes?v # 查看节点信息
GET /_cat/health?v # 查看集群当前状态:红、黄、绿
GET /_cat/shards?v # 查看各shard的详细情况
GET /_cat/shards/{index}?v # 查看指定分片的详细情况
GET /_cat/master?v # 查看master节点信息
GET /_cat/indices?v # 查看集群中所有index的详细信息
GET /_cat/indices/{index}?v # 查看集群中指定index的详细信息
-
集群 status
- Green: 主分片与副本都正常分配
- Yellow: 主分片全部正常分配,有副本分片未能正常分配
- Red: 有主分片未能分配
- 例如,当服务器的磁盘容量超过85%时,去创建了一个新的索引
-
Cerebro 客户端:可以查看分片分配和通过图形界面执行常见的索引操作
ES安全认证
- ES敏感信息泄露的原因
- Elasticsearch在默认安装后,不提供任何形式的安全防护
- 不合理的配置导致公网可以访问ES集群
elasticsearch.yml -> server.host=0.0.0.0
- 公网解决方法
- 设置nginx反向代理
- Security插件
- X-Pack的Basic版
集群内部安全通信
- 集群内部的数据是通过9300端口进行传输的,需要对数据加密
- 解决方案: 为节点创建证书(TLS 协议要求Trusted Certificate Authority (CA)签发x.509的证书)
- 证书认证的不同级别
- Certificate:节点加入需要使用相同CA签发的证书
- Full Verification:节点加入集群需要相同CA签发的证书,还需要验证Host name 或IP地址
- No Verification:任何节点都可以加入,开发环境中用于诊断目的
- 生成节点证书
- 将证书拷贝到集群内的其他节点作为通信依据
# 为集群创建一个证书颁发机构
bin/elasticsearch‐certutil ca
# 为集群中的每个节点生成证书和私钥
bin/elasticsearch‐certutil cert ‐‐ca elastic‐stack‐ca.p12
# 移动到config目录下
mv *.p12 config/
- 配置节点间通信
elasticsearch.yml
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.client_authentication: required
xpack.security.transport.ssl.keystore.path: elastic‐certificates.p12
xpack.security.transport.ssl.truststore.path: elastic‐certificates.p12
- 开启并配置X-Pack的认证
elasticsearch.yml
xpack.security.enabled: true
- 为内置账号添加密码
bin/elasticsearch‐setup‐passwords interactive
- interactive:给用户手动设置密码
- auto:自动生成密码
- 配置 Kibana
kibana.yml
elasticsearch.username: "kibana_system"
elasticsearch.password: "123456"
- 配置 Cerebro
conf/application.conf
hosts = [{
host = "http://192.168.65.174:9200"
name = "es‐cluster"
auth = {
username = "elastic"
password = "123456"
}}]
生产环境常见集群部署方式
单一角色
- 在开发环境中,一个节点可承担多种角色
- 在生产环境中
- 建议设置单一角色的节点
- 根据数据量,写入和查询的吞吐量,选择合适的部署方式
- 一个节点只承担一个角色的配置
Master | Data | Ingest | Coordinate |
---|---|---|---|
node.master: true | node.master: false | node.master: false | node.master: false |
node.ingest: false | node.ingest: false | node.ingest: true | node.ingest: false |
node.data: false | node.data: true | node.data: false | node.data: false |
- 单一角色职责分离的好处
- master eligible nodes(使用低配置的CPU,RAM和磁盘): 负责集群状态(cluster state)的管理
- data nodes(使用高配置的CPU,RAM和磁盘): 负责数据存储及处理客户端请求
- ingest nodes(使用高配置CPU; 中等配置的RAM; 低配置的磁盘):负责数据处理
- Coordinating Only Nodes(使用高配置CPU; 高配置的RAM; 低配置的磁盘)
- 建议为一些大的集群配置Coordinating Only Nodes
- 扮演Load Balancers,降低Master和 Data Nodes的负载
- 负责搜索结果的Gather/Reduce
- 有时候无法预知客户端会发送怎么样的请求,比如大量占用内存的操作
- 单一 master eligible nodes(从高可用&避免脑裂的角度出发)
- 一般在生产环境中配置3台
- 一个集群只有1台活跃的主节点(master node)
- 负责分片管理,索引创建,集群管理等操作
- 如果和数据节点或者Coordinate节点混合部署,可能影响Master节点,导致集群的不稳定
- 数据节点相对有比较大的内存占用
- Coordinate节点有时候可能会有开销很高的查询,导致OOM
增加节点水平扩展
- 增加节点水平扩展场景
- 当磁盘容量无法满足需求时,可以增加数据节点
- 磁盘读写压力大时,增加数据节点
- 当系统中有大量的复杂查询及聚合时候,增加Coordinating节点,增加查询的性能
读写分离架构
异地多活架构
- 全局流量管理(GTM)和负载均衡(SLB)的区别
- GTM 是通过DNS将域名解析到多个IP地址,不同用户访问不同的IP地址,来实现应用服务流量的分配
- 同时通过健康检查动态更新DNS解析IP列表,实现故障隔离以及故障切换
- 最终用户的访问直接连接服务的IP地址,并不通过GTM
- SLB 是通过代理用户访问请求的形式将用户访问请求实时分发到不同的服务器
- 最终用户的访问流量必须要经过SLB
- 相同Region使用SLB进行负载均衡;不同region的多个地址,则可以使用GTM进行负载均衡
- GTM 是通过DNS将域名解析到多个IP地址,不同用户访问不同的IP地址,来实现应用服务流量的分配
- ES 跨集群复制 (Cross-Cluster Replication):ES 6.7的的一个全局高可用特性
- CCR 允许不同的索引复制到一个或多个ES 集群中
Hot & Warm 架构
-
为什么要设计 Hot & Warm 架构
- ES数据通常不会有 Update 操作
- 适用于Time based索引数据,同时数据量比较大的场景
- 引入Warm节点,低配置大容量的机器存放老数据,以降低部署成本
-
两类数据节点,不同的硬件配置
- Hot 节点 (通常使用SSD)︰索引不断有新文档写入
- 用于数据的写入
- lndexing 对 CPU和IO都有很高的要求,所以需要使用高配置的机器
- 存储的性能要好,建议使用SSD
- Warm 节点 (通常使用HDD)︰索引不存在新数据的写入,同时也不存在大量的数据查询
- 用于保存只读的索引,比较旧的数据
- 通常使用大容量的磁盘
- Hot 节点 (通常使用SSD)︰索引不断有新文档写入
-
配置 Hot & Warm 架构:使用Shard Filtering实现Hot&Warm node间的数据迁移
node.attr
来指定node属性:hot或是warm- 在index的settings里通过
index.routing.allocation
来指定索引(index)到一个满足要求的node
-
使用 Shard Filtering 的步骤
- 标记节点 (Tagging):需要通过“node.attr”来标记一个节点
- 节点的attribute可以是任何的key/value
- 可以通过elasticsearch.yml或者通过-E命令指定
- 配置索引到 Hot Node
- 创建索引时候,指定将其创建在 hot 节点上
- 配置索引到 Warm Node
Index.routing.allocation
是一个索引级的 dynamic setting- 可以通过API在后期进行设定
- 标记节点 (Tagging):需要通过“node.attr”来标记一个节点
# 标记一个 Hot 节点
elasticsearch.bat ‐E node.name=hotnode ‐E cluster.name=esc ‐E http.port=9200 ‐E path.data=hot_data ‐E node.attr.my_node_type=hot
# 标记一个 warm 节点
elasticsearch.bat ‐E node.name=warmnode ‐E cluster.name=esc ‐E http.port=9201 ‐E path.data=warm_data ‐E node.attr.my_node_type=warm
# 查看节点
GET /_cat/nodeattrs?v
# 配置到 Hot 节点
PUT /index‐2022‐05
{"settings":{"number_of_shards":2,"number_of_replicas":0,
"index.routing.allocation.require.my_node_type":"hot"}}
# 查看索引文档的分布
GET _cat/shards/index‐2022‐05?v
# 配置到 warm 节点
PUT /index‐2022‐05/_settings
{"index.routing.allocation.require.my_node_type":"warm"}
GET _cat/shards/index‐2022‐05?v
集群容量规划
- 规划上需要保持一定的余量,当负载出现波动,节点出现丢失时,还能正常运行
- 做容量规划时,一些需要考虑的因素
- 机器的软硬件配置
- 单条文档的大小 │ 文档的总数据量 │ 索引的总数据量 | Time base数据保留的时间 | 副本分片数
- 评估业务的性能需求
- 数据吞吐及性能需求
- 数据的格式和数据的Mapping
- 实际的查询和聚合
- ES集群常见应用场景
- 搜索: 固定大小的数据集
- 搜索的数据集增长相对比较缓慢
- 日志: 基于时间序列的数据
- 使用ES存放日志与性能指标。数据每天不断写入,增长速度较快
- 结合Warm Node 做数据的老化处理
- 搜索: 固定大小的数据集
- 硬件配置
- 选择合理的硬件,数据节点尽可能使用SSD
- 搜索等性能要求高的场景,建议SSD
- 按照 1∶10 的比例配置内存和硬盘
- 日志类和查询并发低的场景,可以考虑使用机械硬盘存储
- 按照 1:50 的比例配置内存和硬盘
- 单节点数据建议控制在2TB以内,最大不建议超过5TB
- JVM配置机器内存的一半,JVM内存配置不建议超过32G
- 不建议在一台服务器上运行多个节点
- 内存大小要根据 ode 需要存储的数据来进行估算
- 搜索类的比例建议 1:16
- 日志类 1:48-1:96 之间
- 部署方式
- 如果需要考虑可靠性高可用,建议部署3台单一的Master节点
- 如果有复杂的查询和聚合,建议设置Coordinating节点
- 集群扩容
- 增加 Coordinating / Ingest Node 解决CPU和内存开销的问题
- 增加数据节点解决存储的容量的问题
- 为避免分片分布不均的问题,要提前监控磁盘空间,提前清理数据或增加节点
产品信息库搜索
- 特性
- 被搜索的数据集很大,但是增长相对比较慢(不会有大量的写入)。更关心搜索和聚合的读取性能
- 数据的重要性与时间范围无关。关注的是搜索的相关度
- 估算索引的的数据量,然后确定分片的大小
- 单个分片的数据不要超过20 GB
- 可以通过增加副本分片,提高查询的吞吐量
- 如果单个索引数据量非常大,可以考虑将索引拆分成多个索引
- 如果业务上有大量的查询是基于一个字段进行Filter,该字段又是一个数量有限的枚举值
- 例如订单所在的地区。可以考虑以地区进行索引拆分
- 如果业务上有大量的查询是基于一个字段进行Filter,该字段数值并不固定
- 启用Routing功能,按照filter字段的值分布到集群中不同的shard
- 降低查询时相关的shard数提高CPU利用率
- 启用Routing功能,按照filter字段的值分布到集群中不同的shard
- 如果要对多个索引进行查询,还是可以在查询中指定多个索引得以实现
- 如果业务上有大量的查询是基于一个字段进行Filter,该字段又是一个数量有限的枚举值
- es分片路由的规则
shard_num = hash(_routing) % num_primary_shards
_routing
字段的取值,默认是_id
字段,可以自定义
PUT /users
{"settings":{"number_of_shards":2}}
POST /users/_create/1?routing=fox
{"name":"fox"}
时间序列的数据
- 相关场景:
- 日志/指标/安全相关的事件
- 舆情分析
- 特性:
- 每条数据都有时间戳,文档基本不会被更新 (日志和指标数据)
- 用户更多的会查询近期的数据,对旧的数据查询相对较少
- 对数据的写入性能要求比较高
- 创建基于时间序列的索引:
- 在索引的名字中增加时间信息
- 按照每天/每周/每月的方式进行划分
- 这样做的好处:更加合理的组织索引,例如随着时间推移,便于对索引做的老化处理
- 可以利用 Hot & Warm 架构
- 备份和删除以及删除的效率高
- Delete By Query 执行速度慢,底层也不会立刻释放空间
- 基于Date Math方式建立索引
# PUT /<logs‐{now/d}
PUT /%3Clogs‐%7Bnow%2Fd%7D%3E
# POST /<logs‐{now/d}>/_search
POST /%3Clogs‐%7Bnow%2Fd%7D%3E/_search
- 基于Index Alias索引最新的数据
PUT /logs_2022‐05‐27
PUT /logs_2022‐05‐26
# 可以每天晚上定时执行
POST /_aliases
{"actions":[{
"add":{"index":"logs_2022‐05‐27","alias":"logs_write"}},{
"remove":{"index":"logs_2022‐05‐26","alias":"logs_write"}}]}
GET /logs_write