索引模板,一种复用机制,就像一些项目的开发框架如 Laravel 一样,省去了大量的重复,体力劳动。当新建一个 Elasticsearch 索引时,自动匹配模板,完成索引的基础部分搭建。
模板定义,看似复杂,拆分来看,主要为如下几个部分:
{ "order": 0, // 模板优先级 "template": "sample_info*", // 模板匹配的名称方式 "settings": {...}, // 索引设置 "mappings": {...}, // 索引中各字段的映射定义 "aliases": {...} // 索引的别名 }
模板优先级
一个模板可能绝大部分符合新建索引的需求,但是局部需要微调,此时,如果复制旧的模板,修改该模板后,成为一个新的索引模板即可达到我们的需求,但是这操作略显重复。此时,可以采用模板叠加与覆盖来操作。模板的优先级是通过模板中的 order 字段定义的,数字越大,优先级越高。
索引模板的匹配
索引模板中的 "template" 字段定义的是该索引模板所应用的索引情况。如 "template": "tete*" 所表示的含义是,当新建索引时,所有以 tete 开头的索引都会自动匹配到该索引模板。利用该模板进行相应的设置和字段添加等。
setting 部分
索引模板中的 setting 部分一般定义的是索引的主分片、拷贝分片、刷新时间、自定义分析器等。
前提条件:
只有候选主节点(master:true)的节点才能成为主节点。
最小候选主节点数(min_master_nodes)的目的是防止脑裂。
实现步骤:
【补充】master 节点的职责主要包括集群、节点和索引的管理,不负责文档级别的管理;data 节点可以关闭 http 功能。
【原因】
所谓集群脑裂,是指 Elasticsearch 集群中的节点(比如共 20 个),可能因为网络问题,其中的 10 个选了一个 master,另外 10 个选了另一个 master 的情况。
【解决】
当集群 master 候选数量不小于 3 个时,可以通过设置最少投票通过数量(discovery.zen.minimum_master_nodes:最小候选主节点数)超过所有候选节点一半以上来解决脑裂问题;
想了解应聘者之前公司接触的ES使用场景、规模,有没有做过比较大规模的索引设计、规划、调优
解答:
查看es集群状态:
curl -XGET http://localhost:9200/_cat/health?v 返回结果: { "cluster": "es-9pu872sa", #集群名称 "status": "green", #集群状态 green代表健康;yellow代表分配了所有主分片,但至少缺少一个副本,此时集群数据仍旧完整;red代表部分主分片不可用,可能已经丢失数据 "node.data": "8", #代表在线的数据节点的数量 "node.total": "11", #代表在线的节点总数量 "init": "0", #initializing_shards 初始化中的分片数量 正常情况为 0 "relo": "0", #relocating_shards 迁移中的分片数量,正常情况为 0 "pending_tasks": "0", #准备中的任务,任务指迁移分片等 正常情况为 0 "unassign": "0", #unassigned_shards 未分配的分片 正常情况为 0 "pri": "3699", #active_primary_shards 存活的主分片数量 正常情况下 shards的数量是pri的两倍 "shards": "4343", #active_shards 存活的分片数量 "active_shards_percent": "100.0%", #正常分片百分比 正常情况为 100% "max_task_wait_time": "-", #任务最长等待时间 "epoch": "1696748727", "timestamp": "07:05:27" }
模块运营ES集群11个节点,6个hot节点16C64G配置,5个warm节点4C16G。集群因为有部门内其他项目也在用,跟我们业务相关主要索引在8+个以上,例如模块运营,
主要业务索引:
菜单访问记录按天 mcs_menu_user_access-yyyyMMdd,
菜单访问统计按月 mcs_menu_user_access_aggregation-yyyyMM,
菜单访问小时统计按月 mcs_menu_user_access_aggregation_hour-yyyyMM,
事件访问明细索引 mcs_menu_user_access_action-yyyyMM
数据量计算:前提:公司菜单总数在2300个左右,公司员工访问总人数在5-6w左右
索引增量:根据日期,有的按月有的按天递增,每月递增33+索引以上。
菜单访问相关的数据量没那么大,索引分片在6个分片,为节省磁盘和性能没有副本
事件访问明细索引数据量笔记打,索引分片在12个,一样没有副本
保存近1年的数据,1年以前的数据删除。
这一年的数据做采取了冷热分离机制,热数据存储到SSD,提高检索效率;冷数据定期进行shrink操作,以缩减存储;近6个月的数据在hot节点,前6个月的数据移到warm节点
ES集群的索引写入及查询速度主要依赖于磁盘的IO速度,冷热数据分离的关键为使用SSD磁盘存储数据。若全部使用SSD,成本过高,且存放冷数据较为浪费,因而使用普通SATA磁盘与SSD磁盘混搭,可做到资源充分利用,性能大幅提升的目标。为了解决控制成本的前提下读写性能问题,Elasticsearch冷热分离架构应运而生。
冷数据索引:查询频率低,基本无写入,一般为当天或最近2天以前的数据索引
热数据索引:查询频率高,写入压力大,一般为当天数据索引
实现原理
Hot节点设置:索引节点(写节点),同时保持近期频繁使用的索引。 属于IO和CPU密集型操作,建议使用SSD的磁盘类型,保持良好的写性能;节点的数量设置一般是大于等于3个。将节点设置为hot类型:node.attr.box_type: hot
Warm节点设置: 用于不经常访问的read-only索引。由于不经常访问,一般使用普通的磁盘即可。内存、CPU的配置跟Hot节点保持一致即可;节点数量一般也是大于等于3个。将节点设置为warm类型:node.attr.box_type: warm
可以通过两种方式对数据进行冷热的那种处理
1、针对索引设置冷热属性:指定某个索引为热索引,另一个索引为冷索引。通过索引的分布来实现控制数据分布的目的。业务上根据实际情况对索引设置冷热属性,如果按照时间定期处理。
index.routing.allocation.include.{attribute}
表示索引可以分配在包含多个值中其中一个的节点上。index.routing.allocation.require.{attribute}
表示索引要分配在包含索引指定值的节点上(通常一般设置一个值)。index.routing.allocation.exclude.{attribute}
表示索引只能分配在不包含所有指定值的节点上。2、通过索引生命周期管理,ES (版本>=6.6) 提供了索引生命周期管理功能。索引生命周期管理可以通过 API 或者 kibana 界面配置,详情可参考 index-lifecycle-management。使用索引生命周期管理,可以实现索引数据的自动滚动跟过期,并结合冷热分离架构进行数据的降冷跟删除。 一般通过kibana界面去创建代理任务进行配置,实现索引的动态管理,索引的生命周期被分为:Hot phrase,Warm phase, Cold phase,Delete phrase四个阶段
可能存在的部分原因有以下几种:
解决方案
例如移动node-1的分片0到node-4
curl -XPOST 'http://localhost:9200/_cluster/reroute' -d '{ "commands":[{ "move":{ "index":"indexName", # 索引名 "shard": 0, # 需要移动的分片 "from_node":"node-1", # 从哪个节点移出来 "to_node":"node-4" # 需要移到哪个节点 }}]}'
优点:操作简单,恢复时间短;不必修改master node的配置,master node长期负载后高
缺点:索引大,移动时有很高的IO,索引容易损坏,需要做备份,不能解决master node既是数据节点又是负载均衡转发器的问题
【注意】分片和副本无法移动到同一个节点
删除原来的索引,重新建立索引,;利用elasticsearch dump等工具从另一个集群中把数据导入到新的索引中
优点:可以重新配置master node和data node,主从负载均匀
缺点:费时间,容易数据丢失,需要验证数据的一致性
使用命令恢复平衡
PUT_cluster/settings { "persistent": { "cluster.routing.rebalance.enable": "all" } }
原因
出现这个问题的原因是原有分片未正常关闭和清理,所以当分片要重新分配回出问题节点的时候没有办法获得分片锁。
这不会造成分片数据丢失,只需要重新触发一下分配。
unassigned 分片问题可能的原因如下:
解决方案如下:
执行修复命令: POST /_cluster/reroute?retry_failed
想了解ES的底层原理,不只是关注业务本身。
这里的索引文档应该理解为文档写入ES,创建索引的过程。这里说下单文档索引的过程
es的写入过程还是很复杂的,整个过程中还涉及到refresh刷新、强制flush一些操作,画个图可能更好理解一些
添加doc的流程:
translog 和 flush操作的作用
translog文件:为了保证数据安全而存在的机制,因为文档doc刚开始是写到内存中的,还没有入到磁盘。如果此时服务器宕机那么数据就丢失了。引入translog,文档写入buffer时是同时写入到translog文件中的,这个是落盘的。这样就能防止数据丢失,并且translog是追加的方式,因此性能比较好
flush操作:每隔30分钟或者translog日志文件达到一定大小(默认512M)的时候,就会触发一次flush操作,此时ES会执行一次flush操作先将segment刷到磁盘。原有translog文件已经落盘,会生成一份新的translog日志文件
近实时性-refresh操作
es接收数据请求时先存入buffer缓冲区中,默认每隔一秒会从buffer中将数据写入segment中,这个过程叫做refresh;
当一个文档写入Lucene后是不能被立即查询到的,Elasticsearch提供了一个refresh操作,会定时地为内存中新写入的数据生成一个新的segment,此时被处理的文档均可以被检索到。refresh操作的时间间隔由refresh_interval参数控制,默认为1s, 当然还可以在写入请求中带上refresh表示写入后立即refresh,另外还可以调用refresh API显式refresh。
产生的问题
于是这个过程中就产生了大量的segment,数量越多就会占用更多的内存,并且还会影响查询的效率,因为查询数据是要具体到分片上去的,其实就是遍历segment文件进行查询,segment越多就会影响性能
merge操作
由于refresh操作1秒钟执行一次,每次都会产生一个segment段,会产生大量的segment段。这对于查询性能来说影响很大,并且占用空间。因此ES会运行一个任务检测segment,对符合要求的segment段进行合并操作,提高查询速度。用户也可以手动调用_forcemerge API强制合并merge
设计阶段调优
写入调优思路
查询调优思路