目录
[一、 架构的设计](#一、 架构的设计)
[1.1 一个节点只承担一个角色的配置](#1.1 一个节点只承担一个角色的配置)
[1.2 主节点设计](#1.2 主节点设计)
[二、 索引的设计](#二、 索引的设计)
[2.1 冷热数据分离](#2.1 冷热数据分离)
[1. 在配置文件中标记节点](#1. 在配置文件中标记节点)
[2. 设置索引分配到热节点上](#2. 设置索引分配到热节点上)
[2.2 节点数的选择](#2.2 节点数的选择)
[2.3 索引的拆分](#2.3 索引的拆分)
[2.4 索引分片的设计](#2.4 索引分片的设计)
一、 架构的设计
1.1 一个节点只承担一个角色的配置
有条件的情况下一个节点只承担一个角色的配置:
- 低 CPU、RAM 和磁盘的机器做 master 节点
- 高性能 CPU、中等配置的 RAM 做 ingest 节点
- 高性能 CPU、RAM、磁盘节点做 data 节点。
1.2 主节点设计
一个实时的master节点,多个备用master节点。避免脑裂的同时又做到高可用。
二、 索引的设计
2.1 冷热数据分离
将热点数据存储在磁盘性能较好的机器上,如固态硬盘,而冷数据存储在磁盘性能较差的机器上,具体操作如下:
1. 在配置文件中标记节点
bash
# 标记节点为热节点
node.tag: hot
# 标记节点为冷节点
node.tag: cold
node.max_local_storage_nodes: 2 #允许每个机器启动两个es进程(可选)
2. 设置索引分配到热节点上
bash
PUT /_template/logstash
{
"order": 0,
"template": "logstash*",
"settings": {
"index.routing.allocation.include.tag": "hot",
"index.refresh_interval": "30s",
"index.number_of_replicas": "1",
"index.number_of_shards": "1",
"index.translog.flush_threshold_ops": "30000"
}
}
"index.routing.allocation.include.tag": "hot": 表示新建索引将分配到 node.tag = hot 的节点下
3. 设置定时任务,定期将索引迁移到冷节点上
bash
PUT /index_name/_settings
{
"index.routing.allocation.include.tag" : "cold"
}
这样旧索引数据会自动迁移到 cold 集群上。
2.2 节点数的选择
节点数的选择与集群的用途相关,一般从用途上可分为两类:
**搜索:**固定大小的数据集
- 搜索的数据集增长相对比较缓慢
**日志:**基于时间序列的数据
- 使用ES存放日志与性能指标。数据每天不断写入,增长速度较快
- 结合Warm Node 做数据的老化处理
硬件配置:
- 选择合理的硬件,数据节点尽可能使用SSD
- 搜索等性能要求高的场景,建议SSD按照1∶10-20的比例配置内存和硬盘
- 日志类和查询并发低的场景,可以考虑使用机械硬盘存储,按照1:50的比例配置内存和硬盘
- 单节点数据建议控制在2TB以内,最大不建议超过5TB
- JVM配置机器内存的一半,JVM内存配置不建议超过32G
- 不建议在一台服务器上运行多个节点
内存大小要根据Node 需要存储的数据来进行估算
- 搜索类的比例建议: 1:16
- 日志类: 1:48------1:96之间
假设总数据量1T,设置一个副本就是2T总数据量
- 如果搜索类的项目,每个节点31*16 = 496 G,加上预留空间。所以每个节点最多400G数据,至少需要5个数据节点
- 如果是日志类项目,每个节点31*50= 1550 GB,2个数据节点即可
2.3 索引的拆分
当索引数据量较大时,我们可以结合索引的业务特性进行拆分
- 如果索引的数据随着时间推移,热度消退,比如日志类的索引,那么,可以考虑按时间命名索引。这样既能减少索引的大小,又能做到冷热数据分离处理。
- 如果索引的数据属于均匀分布,与时间无关,则应考虑根据查询特性,是否能根据某个常用的查询条件进行拆分。比如各个地域的订单统计,可以考虑根据地域查询索引。
- 如果某个常用的查询条件的值不固定,则可考虑启用Routing 功能,按照filter 字段的值分布到集群中不同的shard,降低查询时相关的shard数提高CPU利用率
bash
# 将相同字段值的数据路由到同一个分片中,不仅可以减少查询时CPU的计算消耗,还能增加聚合、算分等操作结果的准确性
# es分片路由的规则:
shard_num = hash(_routing) % num_primary_shards
# _routing字段的取值,默认是_id字段,可以自定义。
PUT /users
{
"settings": {
"number_of_shards":2
}
}
POST /users/_create/1?routing=lmj
{
"name":"lmj"
}
2.4 索引分片的设计
索引的分类
索引分片可以分为两类:
- 主分片: 主分片相当于将原有索引的数据拆分成若干个分片,起到水平分担压力的作用,主分片可读可写。
- **副本分片:**副本分片是主分片的数据备份,如果将索引的副本数设置为1,意味着该索引的每个主分片都有1个副本。副本分片只支持读取操作,不支持写入。
主分片数的影响
对于单个主分片来讲,一个请求过来,这个请求的压力只会打到某一个节点上,不能最大限度的发挥出集群的性能特性。但单个主分片在做聚合查询、评分时,不存在结果偏差,而多个主分片的索引可能会存在这种问题。如果将索引设置为多个主分片,在索引数据量比较大,单个请求比较耗性能时,这样设置会起到提升性能的作用,但会牺牲聚合查询、评分的结果准确性。而且,CPU的消耗随着主分片的线性递增,同时master节点管理分片的压力线性递增。所以在主分片过多的情况下集群的吞吐量可能反而下降。
副本分片的影响:
副本分片起到数据备份和分担查询压力的作用,一般至少要有一个副本分片,避免数据丢失。副本数有限的增加会提升集群的查询吞吐量(原理同主分片增加一致),但会牺牲写入的性能,因为数据从主分片同步到副本分片也有性能消耗。
主副分片数设计的原则:
从使用场景分析:
- 搜索类应用,单个分片不要超过20 GB
- 日志类应用,单个分片不要大于50 GB
从堆内存的角度分析:
- 在一个节点中的分片数小于20分片/每GB堆内存
在数据量较大时使用分片不仅能提升性能,在某个节点下线丢失副本时也能更快的恢复。同时主分片时在设计之初就要考虑数据的增长速度,因为主分片数一旦设定后续不可动态调整。对于副本分片,应当保证至少有一个副本分片,避免主分片数据丢失后无法恢复,同时,主副分片总数尽可能的略微大于节点总数,这样不仅能最大限度的发挥集群性能,还能保证在集群新增节点时,有多余的副本可用,不会导致索引在某一个时刻不可用。
本人近十年JAVA架构设计经验,长期从事IT技术资源整合。有志于自我技术提升、需要最新IT技术课程的小伙伴,可私信联系我 ,粉丝一律白菜价