1:ES的分布式架构原理?
ES是分布式存储,多分区(shard),多备份的集群结构。
存储索引,只能通过primary shard(主节点)进行存储数据,读取是既可以从primary(主节点)也可以从replica(备份节点)进行读取。
ES集群有多个节点,会自动选举一个master节点,主要负责维护元数据,负责切换primary shard 和 replica shard,进行故障转移。
问题1:master节点宕机,如何处理?
会重新选举一个master节点,新的master节点会把宕机的master上面的primary shard 调整成 replica shard,保证能够正常的读写,并且把其他机器上面的该备份的replica shard 调整成primary shard。
问题2:非master节点宕机,如何处理?
如果是非master节点宕机,master会让宕机节点上的primary shard的身份转移到其他机器上面的replica shard,接着修复当前宕机的机器,master节点会把缺失的replica shard分配过去,同步缺失数据,让集群恢复正常。
2:ES的写数据流程
1:集群会任意挑选一个节点,就做协调节点,协调节点会hash数据,计算出当前数据的对应shard
2:协调节点会将数据路由到该shard的primary shard ,写入数据
3:primary shard 会同步数据到该shard的replica shard
4:全部写完,协调节点会通知客户端,写入完成
1:写入内存buffer中,同时写入translog日志(保证节点所在机器宕机,当前进程的数据不会丢失)
2:如果buffer快满了,或者到一定的时间,就会将buffer中的数据refresh到一个磁盘中的os cache中,每隔1秒,把buffer中的数据refresh到磁盘中的os cache中。
只要数据refresh到os cache,那么客户端就可以查询到数据。
只要数据被refresh到os cache中,buffer中的数据就会被清空。
3:ES一直重复写入数据,buffer会每隔一秒清空,但是translog日志是一直增加,逐渐增大的,到一定程度,就会执行commit操作。
commit操作的步骤: 1:写commit point (用于标识当前commit对应的多个segment file)
2:将os cache数据fsync强刷到磁盘中去(一个一个的segment file文件中)
3:清空translog日志文件
commit执行条件: 1:每隔30分钟
2:手动commit
问题1:ES为什么是准实时的?
ES数据是每隔一秒把数据从buffer中refresh到segment file中(首先会先进入os cache中),默认一秒,所以是准实时的,当然也可以自己手动refresh。
问题2:translog日志的作用?
因为os cache 和 buffer都是内存文件,一旦存储当前数据的节点所在机器宕机,那么数据就会丢失,translog日志是持久化到机器上,可以用于后面的数据恢复。
问题3:ES会存在5秒的数据丢失,为什么?
因为数据被写入translog日志并不是直接写入translog日志,而是先写入os cache中,然后每隔5秒刷到磁盘中。中间有5秒的数据是存在内存中的。
3:ES的删数据流程
删除数据,标识为.del,标识这条数据被删除了。这样数据就不能搜索到
物理删除:merge操作
当segment file 到一定的程度,会自动触发merge操作,把一堆小segment file 合并成一个大的segment file,并且被标识为.del的数据不会被merge,merge之后的文件就不存在.del文件。
4:ES的读数据流程
1:客户端发送一个get请求,会随意请求到一个机器,这个机器的节点会作为协调节点;
2:协调节点根据document id,hash计算出这个doucment所在的shard节点,路由到目标节点;
3:这个shard会获取数据,给到协调节点,返回给客户端
5:ES的搜索流程
1:客户端发送一个搜索请求,随意请求一个机器,这个机器所在的节点作为协调节点;
2:协调节点会把所有请求发送到集群里面所有shard的primary shard或者replica shard;
3:这些shard会返回匹配的所有的document id,再次根据document id到这些shard里面查询完整数据;
4:筛选最匹配的数据进行返回。
6:如何提升ES的搜索性能
1:filesystem cache (影响最大因素)
写入ES的数据,都是写到磁盘中,磁盘中的segmen file文件会被缓存到filesystem cache中。
filesystem cache内存越高,性能越高。
2:只对用于检索的数据进行存储到ES中,减少数据占用ES机器上filesystem cache的宝贵空间。
一般使用ES + Hbase的架构
一般在ES中按照搜索条件查询获取document id,按照通过document id在Hbase中查询详情,效率会很高。
建议:写入ES中的数据小于等于或者略大于ES集群设置的filesystem cache的内存容量。
3:数据预热
已经按照上述最优方案处理,ES的整体数据依然大于filesystem cache的大小,这种情况,如何处理?
把用户经常访问的数据,通过程序定时调用,热数据进入filesystem cache中。这样后面的人访问,会直接从filesystem cache中获取。
4:冷热分离
(类似于mysql的水平拆分)
热数据和冷数据在不同的索引上,保证热数据一直停留在filesystem cache中,确保热数据的访问性能会很高。冷数据保存在磁盘中,反正访问频率低。
5:document模型设计
尽量避免在搜索时,做复杂的操作。
6:分页性能优化
因为查询很深的数据分页情况下,shard会查询大量的数据,返回到协调节点,进行筛选排序,再进行分页,返回到客户端。
翻的越深,性能越低。
解决方案:
1)不允许深度分页/默认深度分页性能很差
2)APP推荐页的下拉分页,使用scroll api
类似于一次性生成所有数据的快照,然后每次翻页就是通过游标移动,获取下一页。
5台ES机器,64G内存,每天500M的数据进入ES,稳定上线几个月,目前还剩余100+G内存可供使用。几个索引,每个索引是8个shard。