重启elasticsearch_重启2002
elasticsearch vm.max_map_count
另外一个可选的优化项是,对老的索引进行冻结,冻结索引是指把索引常驻内存的一些数据从内存中清理掉(比如FST, 元数据等), 从而降低内存使用量,而在查询已经冻结的索引时,会重新构建出临时的索引数据结构存放在内存中,查询完毕再清理掉;需要注意的是,默认情况下是无法查询已经冻结的索引的,需要在查询时显式的增加"ignore_throttled=false"参数。elasticsearch 启动时遇到的错误
重启elasticsearch_重启2002
重启elasticsearch_重启2002
通过增加warm的方式,客户的集群磁盘总量达到了780TB, 可以满足最多三个月的存储需求。但是客户的需求还没有满足:
问题翻译过来就是: elasticsearch 用户拥有的内存权限太小,至少需要 262144
解决:
切换到 root 用户
执行命令:
sysctl -w vm.max_map_count=262144
查看结果:
sysctl -a|grep vm.max_map_count
显示:
vm.max_map_count = 262144
上述方法修改之后,如果重启虚拟机将失效,所以:
解决办法:
在 /etc/sysctl.conf 文件添加一行
vm.max_map_count=262144
即可修改
elasticsearch6.3.2紧急修复删除node.lock文件导致translog文件损坏的问题
该方式需要我们的可以连接互联网测试索引,自己误作删除了node.lock文件(因为以前用solr的印象里面这个文件是可以随便删的…幸好是测试索引),造成了索引健康状态变红,重启无法recover这样一个现象。
4、虽然把上面的架构全部组合在一起可以形成一个强大的高可用,高负载的数据库系统,但是架构选择合适才是最重要的。混合架构虽然能够解决所有的场景的问题,但是也会面临更多的挑战,你以为的完美架构,背后其实有着更多的坑。错误日志栈主要是这个在跳,那么分析这个错误日志栈。translog文件记载出错,实际索引的offset和translog的offset不一样了,导致索引健康检查错误。首先最最的手段无非是重建索引,但还是希望有别的补救措施,积累一个排错经验。
translog文件是用来记载索引写入offset等信息,我的误作是删除node.lock后并重启。原因我推断是在失去锁的控制后,索引并没有在实际写入数据,但是translog文件却一直没有受到限制继续被一直写入。lucene系的产品都是数据先临时登录到translog在merge到索引这样一个过程。那么我们可以付出这样一个代价:放弃已经写到translog的数据,优先保护索引。也就是删除出错的translog,但这个过程不能直接用rm,需要使用lucene提供的translog工具。
Elasticsearch之存储原理
文档的更新作和删除是类似的:当一个文档被更新,旧版本的文档被标记为删除,新版本的文档在新的段中索引。倒排索引被写入磁盘后是不可变的,ES解决不变性和更新索引的方式是使用多个索引,利用新增的索引来反映修改,在查询时从旧的到新的依次查询,来一个结果合并。
另外,设置了ILM策略后,可以在索引模板里增加index.lifecycle.name配置,使得所有新创建的索引都可以和新添加的ILM策略关联,从而使得ILM能够正常运行。ES底层是基于Lucene,最核心的概念就是 Segment(段) ,每个段本身就是一个倒排索引。
ES中的Index由多个段的和 commit point(提交点) 文件组成。
提交点文件中有一个列表存放着所有已知的段,下面是一个带有1个提交点和3个段的Index示意图:
Doc会先被搜集到内存中的Buffer内,这个时候还无法被搜索到,如下图所示:
每隔一段时间,会将buffer提交,在flush磁盘后打开新段使得搜索可见,详细过程如下:
下面展示了这个过程完成后的段和提交点的状态:
通过这种方式,可以使得新文档从被索引到可被搜索间的时间间隔在数分钟,但是还不够快。因为磁盘需要 fsync ,这个就成为性能瓶颈。我们前面提到过Doc会先被从buffer刷入段写入文件系统缓存(很快),那么就自然想到在这个阶段就让文档对搜索可见,随后再被刷入磁盘(较慢)。
Lucene支持对新段写入和打开,可以使文档在没有完全刷入硬盘的状态下就能对搜索可见,而且是一个开销较小的作,可以频繁进行。
我们可以看到,新段虽然还没有被完全提交,但是已经对搜索可见了。
引入refresh作的目的是提高ES的实时性,使添加文档尽可能快的被搜索到,同时又避免频繁fsync带来性能开销,依靠的就是文件系统缓存OS cache里缓存的文件可以被打开(open/reopen)和读取,而这个os cache实际是一块内存区域,而非磁盘,所以作是很快的,这就是ES被称为近实时搜索的原因。
refresh默认执行的间隔是1秒,可以使用 refreshAPI 进行手动作,但一般不建议这么做。还可以通过合理设置 refresh_interval 在近实时搜索和索引速度间做权衡。
index segment刷入到os cache后就可以打开供查询,这个作是有潜在风险的,因为os cache中的数据有可能在意外的故障中丢失,而此时数据必备并未刷入到os disk,此时数据丢失将是不可逆的,这个时候就需要一种机制,可以将对es的作记录下来,来确保当出现故障的时候,已经落地到磁盘的数据不会丢失,并在重启的时候可以从作记录中将数据恢复过来。elasticsearch提供了translog来记录这些作,结合os cached segments数据定时落盘来实现数据可靠性保证(flush)。
文档被添加到buffer同时追加到translog:
每隔一段时间(例如translog变得太大),index会被flush到磁盘,新的translog文件被创建,commit执行结束后,会发生以下:
下面示意图展示了这个状态:
translog记录的是已经 在内存生成(segments)并存储到os cache但是还没写到磁盘的那些索引作 (注意,有一种解释说,添加到buffer中但是没有被存入segment中的数据没有被记录到translog中,这依赖于写translog的时机,不同版本可能有变化,不影响理解),此时这些新写入的数据可以被搜索到,但是当挂掉后这些未来得及落入磁盘的数据就会丢失,可以通过trangslog恢复。
当然translog本身也是磁盘文件,频繁的写入磁盘会带来巨大的IO开销,因此对translog的追加写入作的同样作的是os cache,因此也需要定时落盘(fsync)。translog落盘的时间间隔直接决定了ES的可靠性,因为宕机可能导致这个时间间隔内所有的ES作既没有生成segment磁盘文件,又没有记录到Translog磁盘文件中,导致这期间的所有作都丢失且无法恢复。
translog的fsync是ES在后台自动执行的,默认是每5秒钟主动进行一次translog fsync,或者当translog文件大小大于512MB主动进行一次fsync,对应的配置是 index.translog.flush_threshold_period 和 index.translog.flush_threshold_size 。
当 Elasticsearch 启动的时候, 它会从磁盘中使用一个提交点去恢复已知的段,并且会重放 translog 中所有在一次提交后发生的变更作。
translog 也被用来提供实时 CRUD 。当你试着通过ID来RUD一个Doc,它会在从相关的段检索之前先检查 translog 中的变更。
默认 translog 是每5秒或是每次请求完成后被 fsync 到磁盘(在主分片和副本分片都会)。也就是说,如果你发起一个index, delete, update, bulk请求写入translog并被fsync到主分片和副本分片的磁盘前不会反回200状态。
这样会带来一些性能损失,可以通过设为异步fsync,但是必须接受由此带来的丢失少量数据的风险:
flush 就是执行commit清空、干掉老translog的过程。默认每个分片30分钟或者是translog过于大的时候自动flush一次。可以通过flush API手动触发,但是只会在重启或关闭某个索引的时候这样做,因为这可以让未来ES恢复的速度更快(translog文件更小)。
满足下列条件之一就会触发冲刷作:
整体流程:
删除一个ES文档不会立即从磁盘上移除,它只是被标记成已删除。因为段是不可变的,所以文档既不能从旧的段中移除,旧的段也不能更新以反映文档的版本。
ES的做法是,每一个提交点包括一个 .del 文件(还包括新段),包含了段上已经被标记为删除状态的文档。所以,当一个文档被做删除作,实际上只是在 .del 文件中将该文档标记为删除,依然会在查询时被匹配到,只不过在最终返回结果之前会被从结果中删除。ES将会在用户之后添加更多索引的时候,在后台进行要删除内容的清理。
该文档的不同版本都会匹配一个查询,但是较旧的版本会从结果中删除。
通过每秒自动刷新创建新的段,用不了多久段的数量就爆炸了,每个段消费大量文件句柄,内存,cpu资源。更重要的是,每次搜索请求都需要依次检查每个段。段越多,查询越慢。
ES通过后台合并段解决这个问题。ES利用段合并的时机来真正从文件系统删除那些version较老或者是被标记为删除的文档。被删除的文档(或者是version较老的)不会再被合并到新的更大的段中。
可见,段合并主要有两个目的:
ES对一个不断有数据写入的索引处理流程如下:
合并过程如图:
从上图可以看到,段合并之前,旧有的Commit和没Commit的小段皆可被搜索。
段合并后的作:
合并完成后新的段可被搜索,旧的段被删除,如下图所示:
注意 :段合并过程虽然看起来很爽,但是大段的合并可能会占用大量的IO和CPU,如果不加以控制,可能会大大降低搜索性能。段合并的optimize API 不是非常特殊的情况下千万不要使用,默认策略已经足够好了。不恰当的使用可能会将你机器的资源全部耗尽在段合并上,导致无法搜索、无法响应。
ElasticSearch7.X解析/存储/检索word、pdf文档
XX公司运维老大:那不行,我们只想用成熟的ELK架构来做,再增加hadoop那一套东西,我们没那么多人力搞这个事!进入到es安装目录下的bin目录
执行./elasticsearch-plugin install ingest-attachment
集群模式下需要对每个进行安装,安装成功后重启该es。
以下作为kibana中作,且es版本为7.x 其他版本语法有略微别
需要将文件base64编码输入到接Elasticsearch 通过 AllocationDecider 策略来控制 shard 在集群内上的分布。口中
查询改存储结果如下
分布式搜索引擎elasticsearch的架构原理
bellen: 。。。分布式搜索引擎:把大量的索引数据拆散成多块,每台机器放一部分,然 后利用多台机器对分散之后的数据进行搜索,所有作全部是分布在多台机器上进行,形成了 完整的分布式的架构。
近实时,有两层意思:
集群包含多个,每个属于哪个集群都是通过一个配置来决定的,
Node 是集群中的一个,也有一个名称,默认是随机分配的。默认会去加入一个名 称为 elasticsearch 的集群。如果直接启动一堆,那么它们会自动组成一个elasticsearch 集群,当然一个也可以组成 elasticsearch 集群。
文档是 es 中最小的数据单元,一个 document 可以是1条、1条商品分类数据、1条 订单数据,通常用json 数据结构来表示。每个 index 下的 type,都可以存储多条 document。
1个 document 里面有多个 field,每个 field 就是1个数据字段。
es 集群多个,会自动选举1个为 ,这个 其实就是干一些管理 的工作的,比如维护索引元数据、负责切换 primary shard 和 replica shard 身份等。要是 宕机了,那么会重新选举1个为 。 如果是非 宕机了,那么会由 ,让那个宕机上的 primary shard 的身 份转移到其他机器上的 replica shard。接着你要是修复了那个宕机机器,重启了之后, 会控制将缺失的 replica shard 分配过去,同步后续修改的数据之类的,让集群恢复正常。 说得更简单1点,就是说如果某个非 宕机了,那么此上的 primary shard 不就 没了。那好, 会让 primary shard 对应的 replica shard(在其他机器上)切换为 primary shard。如果宕机的机器修复了,修复后的也不再是 primary shard,而是 replica shard。
索引可以拆分成多个 shard ,每个 shard 存储部分数据。拆分多个 shard是有好处的,一是支持横向扩展,比如你数据量是 3T,3 个 shard,每个 shard 就 1T 的数据, 若现在数据量增加到 4T,怎么扩展,很简单,重新建1个有 4 个 shard 的索引,将数据导进 去;二是提高性能,数据分布在多个 shard,即多台上,所有的作,都会在多台机器 上并行分布式执行,提高了吞吐量和性能。 接着就是这个 shard 的数据实际是有多个备份,就是说每个 shard 都有1个 primary shard ,负责写入数据,但是还有多个 replica shard 。 primary shard 写入数据之后, 会将数据同步到其他几个 replica shard上去。
通过这个 replica 的方案,每个 shard 的数据都有多个备份,如果某个机器宕机了,没关系啊, 还有别的数据副本在别的机器上,这样子就高可用了。
总结:分布式就是两点,1.通过shard切片实现横向扩展;2.通过replica副本机制,实现高可用
基本概念
写数据过程:客户端通过hash选择一个node发送请求,这个node被称做coordinating node(协调),协调对docmount进行路由,将请求转发给到对应的primary shard,primary shard 处理请求,将数据同步到所有的replica shard,此时协调,发现primary shard 和所有的replica shard都处理完之后,就反馈给客户端。
客户端发送get请求到任意一个node,然后这个就称为协调,协调对document进行路由,将请求转发到对应的node,此时会使用随机轮询算法,在primary shard 和replica shard中随机选择一个,让读取请求负载均衡,接收请求的node返回document给协调,协调,返回document给到客户端
es最强大的是做全文检索,就是比如你有三条数据
1.ja真好玩儿啊
2.ja好难学啊
3.j2ee特别牛
你根据ja来搜索,将包含ja的document给搜索出来。
更新/删除数据过程,首先还是write、merge作,然后flush过程中:
1、write过程和上面的一致;
所谓的倒排索引,就是把你的数据内容先分词,每句话分成一个一个的,然后记录好每一个对应出现在了哪些 id 标识的数据。
然后你可以从其他地根据这个 id 找到对应的数据就可以了,这个就是倒排索引的数据格式 以及搜索的方式,这种利倒排索引查找数据的式,也被称之为全文检索。
Inverted Index就是我们常见的倒排索引, 主要包括两部分:
一个有序的数据字典 Dictionary(包括单词 Term 和它出现的频率)。
与单词 Term 对应的 Postings(即存在这个单词的文件)
当我们搜索的时候,首先将搜索的内容分解,然后在字典里找到对应 Term,从而查找到与搜索相关的文件内容。
本质上,Stored Fields 是一个简单的键值对 key-value。默认情况下,Stored Fields是为false的,ElasticSearch 会存储整个文件的 JSON source。
哪些情形下需要显式的指定store属性呢?大多数情况并不是必须的。从_source中获取值是快速而且高效的。如果你的文档长度很长,存储 _source或者从_source中获取field的代价很大,你可以显式的将某些field的store属性设置为yes。缺点如上边所说:设你存 储了10个field,而如果想获取这10个field的值,则需要多次的io,如果从Stored Field 中获取则只需要一次,而且_source是被压缩过 的。
这个时候你可以指定一些字段store为true,这意味着这个field的数据将会被单独存储(实际上是存两份,source和 Stored Field都存了一份)。这时候,如果你要求返回field1(store:yes),es会分辨出field1已经被存储了,因此不会从_source中加载,而是从field1的存储块中加载。
Doc_values是存在磁盘的
在es中text类型字段默认只会建立倒排索引,其它几种类型在建立倒排索引的时候还会建立正排索引,当然es是支持自定义的。在这里这个正排索引其实就是Doc Value。
即上文所描述的动态索引
往 es 写的数据,实际2、如果你要储存会话信息,用户配置信息,购物车数据,建议使用NoSQL数据库;不过90%的企业或个人,数据库都是MySQL数据库。上都写到磁盘文件里去了,查询的时候,作系统会将磁盘文件里的数据自动缓存到 file cache 中去。
es 的搜索引擎依赖于底层的 file cache ,你如果给 file cache 更多的 内存,尽量让内存可以容纳所有的 idx segment file 索引数据文件,那么你搜索的时候就 基本都是走内存的,性能会非常高。 性能距究竟可以有多大?我们之前很多的测试和压测,如果走磁盘一般肯定上秒,搜索性能 是秒级别的,1秒、5秒、10秒。但如果是走 file cache ,是走纯内存的,那么一 般来说性能比走磁盘要高一个数量级,基本上就是毫秒级的,从几毫秒到几百毫秒不等。
那如何才能节约file cache这部分的空间呢?
当写数据到ES时就要考虑到最小化数据,当一行数据有30几个字段,并不需要把所有的数据都写入到ES,只需要把关键的需要检索的几列写入。这样能够缓存的数据就会越多。 所以需要控制每台机器写入的数据小于等于或者略大于file cache空间。 如果要搜索海量数据,可以考虑用ES+Hbase架构。用Hbase存储海量数据,然后ES搜索出doc id后,再去Hbase中根据doc id查询指定的行数据。
当每台机器写入的数据大于cache os太多时,导致太多的数据无法放入缓存,那么就可以把一部分热点数据刷入缓存中。
对于那些你觉得比较热的、经常会有人访问的数据,做个专门的缓存预热系统,就是 对热数据每隔一段时间,就提前访问一下,让数据进入 file cache 里去。这样下 次别人访问的时候,性能肯定会好很多。
把热数据和冷数据分开,写入不同的索引里,然后确保把热索引数据刷到cache里。
在ES里不要用复杂的关联表的作。当需要这样的场景时,可以在创建索引的时候,就把数据关联好。比如在mysql中需要根据关联ID查询两张表的关联数据:select A.name ,B.age from A join B where A.id = B.id,在写入ES时直接去把相关联数据放到一个document就好。
es 的分页是较坑的,为啥呢?举个例子吧,如你每页是 10 条数据,你现在要查询第 100 页,实际上是会把每个 shard 上存储的前 1000 条数据都查到1个协调上,如果你有个 5 个 shard,那么就有 5000 条数据,接着协调对这 5000 条数据进行一些合并、处理,再获取到 最终第 100 页的 10 条数据。
分布式的,你要查第 100 页的 10 条数据,不可能说从 5 个 shard,每个 shard 就查 2 条数据, 到协调合并成 10 条数据吧?你必须得从每个 shard 都查 1000 条数据过来,然后根据 你的需求进行排序、筛选等等作,再次分页,拿到里面第 100 页的数据。你翻页的时 候,翻的越深,每个 shard 返回的数据就越多,而且协调处理的时间越长,非常坑爹。所 以用 es 做分页的时候,你会发现越翻到后面,就越是慢。
我们之前也是遇到过这个问题,用 es 作分页,前几页就几十毫秒,翻到 10 页或者几十页的时 候,基本上就要 5~10 秒才能查出来一页数据了。
解决方案吗?
1)不允许深度分页:跟产品说,你系统不允许翻那么深的页,默认翻的越深,性能就越;
2)在APP或者公众号里,通过下拉来实现分页,即下拉时获取到页,可以通过scroll api来实现;
scroll 会1次性给你生成所有数据的1个快照,然后每次滑动向后翻页就是通过游标 scroll_id 移动获取下一页,性能会比上面说的那种分页性能要高很多很 多,基本上都是毫秒级的。 但是,唯1的缺点就是,这个适合于那种类似微博下拉翻页的,不能随意跳到任何一页的场 景。也就是说,你不能先进到第 10 页,然后去第 120 页,然后再回到第 58 页,不能随意乱跳 页。所以现在很多APP产品,都是不允许你随意翻页的,也有一些网站,做的就是你只能往 下拉,一页一页的翻。
初始化时必须指定 scroll 参数,告诉 es 要保存此次搜索的上下文多长时间。你需要确保用户不会持续不断翻页翻几个小时,否则可能因为超时而失败。
除了用 scroll api ,也可以用 search_after 来做, search_after 的思想是使用前一页的结果来帮助检索下一页的数据,显然,这种方式也不允许你随意翻页,你只能一页一页往后 翻。初始化时,需要使用一个唯1值的字段作为 sort 字段。
elasticsearch , kibana 设置权限
Doc_values 本质上是一个序列化的 列式存储,这个结构非常适用于聚合(aggregations)、排序(Sorting)、脚本(scripts access to field)等作。而且,这种存储方式也非常便于压缩,特别是数字类型。这样可以减少磁盘空间并且提高访问速度,ElasticSearch 可以将索引下某一个 Document Value 全部读取到内存中进行作.以上配置好后,重启登录kibana就需要用户名,密码。登录用户名称:elastic;密码:自己设置的。
XX公司运维老大:不要讲你们的PPT了,先告诉我你们能给我们带来什么!1.访问Mament->Security->Roles,创建一个角色。
输入Role name ,选择Inds,就可以访问指定的Index.
2.访问Mament->Security->User,创建一个用户。
选择刚刚创建的角色
PB级大规模Elasticsearch集群运维与调优实践
某中型互联网公司的游戏业务,使用了腾讯云的Elasticsearch产品,采用ELK架构存储业务日志。因为游戏业务本身的日志数据量非常大(写入峰值在100w qps),在服务客户的几个月中,踩了不少坑,经过数次优化与调整,把客户的ES集群调整的比较稳定,避免了在业务高峰时客户集群的读写异常,并且降低了客户的资金成本和使用成本。下面把服务客户过程中遇到的典型问题进行梳理,总结经验,避免再次踩坑。
解决方案架构师A: bellen, XX要上线一款新游戏,日志存储决定用ELK架构,他们决定在XX云和我们之间二选一,我们首先去他们公司和他们交流一下,争取拿下!
bellen: 好,随时有空!
。。。
和架构师一起前往该公司,跟负责底层组件的运维部门的负责人进行沟通。
bellen: 。。单个集群 shard 超过 10 万,这些作会明显变慢。集群在恢复过程中,会频繁更显状态,引起恢复过程漫长。。呃,我们有很多优势。。。比如灵活地扩容缩容集群,还可以一键平滑升级集群版本,并且提供有跨机房容灾的集群从而实现高可用。。
XX公司运维老大:你说的这些别的厂商也有,我就问一个问题,我们现在要存储一年的游戏日志,不能删除数据,每天就按10TB的数据量算,一年也得有个3PB多的数据,这么大的数量,都放在SSD云盘上,我们的成本太高了,你们有什么方案既能够满足我们存储这么大数据量的需求,同时能够降低我们的成本吗?
bellen: 我们本身提供的有冷热模式的集群,热采用SSD云硬盘,冷采用SATA盘,采用ES自带的ILM索引生命周期管理功能定期把较老的索引从热迁移到冷上,这样从整体上可以降低成本。另外一方面,也可以定期把更老的索引通过snapshot快照备份到COS对象存储中,然后删除索引,这样成本就更低了。
XX公司运维老大:存储到COS就是冷存储呗,我们需要查询COS里的数据时,还得再把数据恢复到ES里?这样不行,速度太慢了,业务等不了那么长时间,我们的数据不能删除,只能放在ES里!你们能不能给我们提供一个API, 让老的索引数据虽然存储在COS里,但是通过这个API依然可以查询到数据,而不是先恢复到ES, 再进行查询?
bellen: 。。。呃,这个可以做,但是需要时间。是否可以采用hadoop on COS的架构,把存量的老的索引数据通过工具导入到COS,通过hive去查询,这样成本会非常低,数据依然是随时可查的。
bellen: 好吧,那可以先搞一个集群测试起来,看看性能怎么样。关于存量数据放在COS里但是也需要查询的问题,我们可以先制定方案,尽快实施起来。
XX公司运维老大:行吧,我们现在按每天10TB数据量预估,先购买一个集群,能撑3个月的数据量就行,能给一个集群配置的建议吗?
bellen: 目前支持单磁盘6TB, cpu和内存的话可以放到8核32G单,单跑2w qps写入没有问题,后面也可以进行纵向扩容和横向扩容。
XX公司运维老大:好,我们先测试一下。
N 天后,架构师A直接在微信群里反馈:"bellen, 客户反馈这边的ES集群性能不行啊,使用logstash消费kafka中的日志数据,跑了快一天了数据还没追平,这是线上的集群,麻烦紧急看一下吧。。"
我一看,一脸懵, 什么时候已经上线了啊,不是还在测试中吗?
XX公司运维小B: 我们购买了8核32G10的集群,单磁盘6TB, 索引设置的10分片1副本,现在使用logstash消费kafka中的数据,一直没有追平,kafka中还有很多数据积压,感觉是ES的写入性能有问题。
随后我立即查看了集群的数据,发现cpu和load都很高,jvm堆内存使用率平均都到了90%,jvm gc非常频繁了,部分因为响应缓慢,不停的离线又上线。。
经过沟通,发现用户的使用姿势是filebeat+kafka+logstash+elasticsearch, 当前已经在kafka中存储了有10天的日志数据,启动了20台logstash进行消费,logstash的batch size也调到了5000,性能瓶颈是在ES这一侧。客户8核32G10的集群,理论上跑10w qps没有问题,但是logstash消费积压的数据往ES写入的qps远不止10w,所以是ES扛不住写入压力了,所以只能对ES集群进行扩容,为了加快存量数据的消费速度,先纵向扩容单的配置到32核64GB,之后再横向增加,以保证ES集群能够支持100w qps的写入(这里需要注意的是,增加后索引的分片数量也需要调整)。
所以一般新客户接入使用ES时,必须要事先评估好配置和集群规模,可以从以下几个方面进行评估:
上述场景2遇到的问题是业务上线前没有对集群配置和规模进行合理的评估,导致上线后ES集群负载就很高,通过合理的扩容处理,集群最终抗住了写入压力。但是又有新的问题出现了。
经过分析客户logstash的配置文件,发现问题出现的原因主要是:
分析后,对kafka和logstash进行了如下优化:
通过上述优化,最终使得logstash机器资源都被充分利用上,很快消费完堆积的kafka数据,待消费速度追平生成速度后,logstash消费kafka一直稳定运行,没有出现积压。
另外,客户一开始使用的是5.6.4版本的logstash,版本较老,使用过程中出现因为单个消息体过长导致logstash抛异常后直接退出的问题:
通过把logstash升级至高版本6.8避免了这个问题(6.x版本的logstash修复了这个问题,避免了crash)。
客户的游戏上线有一个月了,原先预估每天最多有10TB的数据量,实际则是在运营活动期间每天产生20TB的数据,原先6TB60=360TB总量的数据盘使用率也达到了80%。针对这种情况,我们建议客户使用冷热分离的集群架构,在原先60个热的基础上,增加一批warm存储冷数据,利用ILM(索引生命周期管理)功能定期迁移热上的索引到warm上。
XX公司运维老大:给我们一个能存放一年数据的方案吧,总是通过加扩容磁盘的方式不是长久之计,我们得天天盯着这个集群,运维成本很高!并且一直加,ES会扛不住吧?
bellen: 可以尝试使用我们新上线的支持本地盘的机型,热支持7.2TB的本地SSD盘,warm支持48TB的本地SATA盘。一方面热的性能相比云盘提高了,另外warm可以支持更大的磁盘容量。单可以支持的磁盘容量增大了,数量就不用太多了,可以避免踩到因为数量太多而触发的坑。
XX公司运维老大:现在用的是云盘,能替换成本地盘吗,怎么替换?
bellen: 不能直接替换,需要在集群中新加入带本地盘的,把数据从老的云盘迁移到新的上,迁移完成后再剔除掉旧的,这样可以保证服务不会中断,读写都可以正常进行。
XX公司运维老大:好,可以实施,尽快搞起来!
云盘切换为本地盘,是通过调用云服务后台的API自动实施的。在实施之后,触发了数据从旧迁移到新的流程,但是大约半个小时候,问题又出现了:
XX公司运维小B: bellen, 快看一下,ES的写入快掉0了。
通过查看集群,发现写入qps直接由50w降到1w,写入拒绝率猛增,通过查看集群日志,发现是因为当前小时的索引没有创建成功导致写入失败。
紧急情况下,执行了以下作定位到了原因:
经过了这次扩容作,总结了如下经验:
在稳定运行了一阵后,集群又出问题了。。
XX公司运维小B: bellen, 昨晚凌晨1点钟之后,集群就没有写入了,现在kafka里有大量的数据堆积,麻烦尽快看一下?
通过cerebro查看集群,发现集群处于yellow状态,然后发现集群有大量的错误日志:
然后再进一步查看集群日志,发现有" not discovered yet..."之类的错误日志,检查三个,发现有两个挂掉,只剩一个了,集群无法选主。
登陆到挂了了机器上,发现保活程序无法启动es进程,直觉是es进程oom了;此时也发现磁盘使用率, 检查了JVM堆内存快照文件目录,发现有大量的快照文件,于是删除了一部分文件,重启es进程,进程正常启动了;但是问题是堆内存使用率太高,gc非常频繁,响应非常慢,大量的创建索引的任务都超时,阻塞在任务队列中,集群还是无法恢复正常。
看到集群的配置是16核32GB内存,JVM实际只分配了16GB内存,此时只好通过对原地增加内存到64GB(虚拟机,使用的腾讯云CVM, 可以调整机器规格,需要重启),机器重启之后,修改了es目录jvm.options文件,调整了堆内存大小,重新启动了es进程。
3个都恢复正常了,但是分片还需要进行恢复,通过GET _cluster/health看到集群当前有超过10w个分片,而这些分片恢复还需要一段时间,通过调大"cluster.routing.allocation.node_concurrent_recoveries", 增大分片恢复的并发数量。实际上5w个主分片恢复的是比较快的了,但是副本分片的恢复就相对慢很多,因为部分副本分片需要从主分片上同步数据才能恢复。此时可以采取的方式是把部分旧的索引副本数量调为0, 让大量副本分片恢复的任务尽快结束,保证新索引能够正常创建,从而使得集群能够正常写入。
总结这次故障的根本原因是集群的索引和分片数量太多,集群元数据占用了大量的堆内存,而本身的JVM内存只有16GB(数据有32GB), 频繁full gc导致异常,从而最终导致整个集群异常。所以要解决这个问题,还是得从根本上解决集群的分片数量过多的问题。
目前日志索引是按照小时创建,60分片1副本,每天有24602=2880个分片,每个月就产生86400个分片,这么多的分片可能会带来的问题。有以下几种方式解决分片数量过多的问题:
和客户沟通过后,客户表示可以接受方式1和方式2,但是方式3和4不能接受,因为考虑到存在磁盘故障的可能性,必须保留一个副本来保证数据的可靠性;另外还必须保证所有数据都是随时可查询的,不能关闭。
在场景5中,虽然通过临时给增加内存,抗住了10w分片,但是不能从根本上解决问题。客户的数据是保留一年的,如果不进行优化,集群必然扛不住数十万个分片。所以接下来需要着重解决集群整体分片数量过多的问题,在场景5的提到了,用户可以接受开启shrink以及降低索引创建粒度(经过调整后,每两个小时创建一个索引),这在一定程度上减少了分片的数量,能够使集群暂时稳定一阵。
辅助客户在kibana上配置了如下的ILM策略:
在warm phase, 把创建时间超过360小时的索引从hot迁移到warm上,保持索引的副本数量为1,之所以使用360小时作为条件,而不是15天作为条件,是因为客户的索引是按小时创建的,如果以15天作为迁移条件,则在每天凌晨都会同时触发15天前的24个索引一共24120=2880个分片同时开始迁移索引,容易引发场景4中介绍的由于迁移分片数量过多导致创建索引被阻塞的问题,所以以360小时作为条件,则在每个小时只会执行一个索引的迁移,这样把24个索引的迁移任务打平,避免其它任务被阻塞的情况发生。
同时,也在warm phase阶段,设置索引shrink,把索引的分片数缩成5个,因为老的索引已经不执行写入了,所以也可以执行force merge, 强制把segment文件合并为1个,可以获得更好的查询性能。
客户使用的ES版本是6.8.2, 在运行ILM的过程中, 也发现一些问题:
这是因为shrink作需要新把索引完整的一份数据都迁移到一个上,然后在内存中构建新的分片元数据,把新的分片通过软链接指向到几个老的分片的数据,在ILM中执行shrink时,ILM会对索引进行如下配置:
问题是索引包含副本,而主分片和副本分片又不能在同一个上,所以会出现部分分片无法分配的情况(不是全部,只有一部分),这里应该是触发了6.8版本的ILM的bug,需要查看源码才能定位解决这个bug,目前还在研究中。当前的workaround是通过脚本定期扫描出现unassigned shards的索引,修改在JAVA环境下,仅需要在原有的存储过程中,配置上管道组件即可其settings:
优先保证分片先从hot迁移到warm,这样后续的shrink才能顺利执行(也可能执行失败,因为60个分片都在一个上,可能会触发rebalance, 导致分片迁移走,shrink的前置条件又不满足,导致执行失败)。要完全规避这个问题,还得在ILM策略中设置,满足创建时间超过360个小时的索引,副本直接调整为0,但是客户又不接受,没办法。
在场景5和6中,介绍了10w个分片会给集群带来的影响和通过开启shrink来降低分片数量,但是仍然有两个需要重点解决的问题:
可以估算一下,按小时建索引,60分片1副本,一年的分片数为24120365=1051200个分片,执行shrink后分片数量2410350 + 2412015 = 127200(15天内的新索引为了保障写入性能和数据可靠性,仍然保持60分片1副本,旧的索引shrink为5分片1副本), 仍然有超过10w个分片。结合集群一年总的存储量和单个分片可以支持的数据量大小进行评估,我们期望集群总体的分片数量可以稳定为6w~8w,怎么优化?
可以想到的方案是执行数据冷备份,把比较老的索引都冷备到其它的存储介质上比如HDFS,S3,腾讯云的COS对象存储等,但是问题是这些冷备的数据如果也要查询,需要先恢复到ES中才可查,恢复速度比较慢,客户无法接受。由此也产生了新的想法,目前老的索引仍然是1副本,可以把老索引先进行冷备份,再把副本调为0,这样做有以下几点好处:
经过和客户沟通,客户接受了上述方案,把老索引冷备到腾讯云的对象存储COS中,实施步骤为:
其中步骤1的实施可以通过脚本实现,本案例中采用腾讯云SCF云函数进行实施,方便快捷可。实施要点有:
在实施完步骤1之后,就可以批量把对索引进行过备份的索引副本数都调为0, 这样一次性释放了很多磁盘空间,并且显著降低了集群整体的分片数量。
接下来实施步骤2,需要每天执行一次快照,多创建时间较久的索引进行备份,实施比较简单,可以通过crontab定时执行脚本或者使用腾讯云SCF执行。
步骤2实施之后,就可以修改ILM策略,开启cold phase, 修改索引副本数量为0:
此处的timing是创建时间20天后,需要保证步骤2中对过去老索引数据备份先执行完成才可以进入到cold phase.
通过老索引数据冷备并且降低索引副本,我们可以把集群整体的分片数量维持在一个较低的水位,但是还有另外一个问题待解决,也即shrink失败的问题。刚好,我们可以利用对老索引数据冷备并且降低索引副本的方案,来解决shrink失败的问题。
在场景5中有提到,shrink失败归根接地是因为索引的副本数量为1, 现在我们可以吧数据备份和降低副本提前,让老索引进入到ILM的warm phase中时已经是0副本,之后再执行shrink作就不会有问题了;同时,因为副本降低了,索引从hot迁移到warm迁移的数据量也减少了一半,从而降低了集群负载,一举两得。
因此,我们需要修改ILM策略,在warm phase就把索引的副本数量调整为0, 然后去除cold phase。
经过上述优化,我们最终解决了集群整体分片数量过多和shrink失败的问题。在实施过程中引入了额外的定时任务脚本实施自动化快照,实际上在7.4版本的ES中,已经有这个功能了,特性名称为 SLM (快照生命周期管理),并且可以结合ILM使用,在ILM中增加了"wait_for_snapshot"的ACTION, 但是却只能在delete phase中使用,不满足我们的场景。
在上述的场景4-7中,我们花费大量的精力去解决问题和优化使用方式,保证ES集群能够稳定运行,支持PB级别的存储。溯本回原,如果我们能有一个方案使得客户只需要把热数据放在SSD盘上,然后冷数据存储到COS/S3上,但同时又使冷数据能够支持按需随时可查,那我们前面碰到的所有问题都迎刃而解了。可以想象得到的好处有:
而这正是目前es开源社区正在开发中的Searchable Snapshots功能,从 Searchable Snapshots API 的文档上可以看到,我们可以创建一个索引,将其挂载到一个指定的快照中,这个新的索引是可查询的,虽然查询时间可能会慢点,但是在日志场景中,对一些较老的索引进行查询时,延迟大点一般都是可以接受的。
所以我认为,Searchable Snapshots解决了很多痛点,将会给ES带了新的繁荣!
经历过上述运维和优化ES集群的实践,我们总结到的经验有:
从一开始和客户进行接触,了解客户诉求,逐步解决ES集群的问题,最终使得ES集群能够保持稳定,这中间的经历让我真真正正的领悟到"实践出真知",只有不断实践,才能对异常情况迅速做出反应,以及对客户提的优化需求迅速反馈。
高可用 Elasticsearch 集群的分片管理 (Shard)
一个 shard 本质上就是一个 Lucene 索引,也是 Elasticsearch 分布式化 Lucene 的关键抽象,是 Elasticsearch 管理 Lucene 文件的最小单位。
所以,Elasticsearch 提供了大量的接口,可以对集群内的 shard 进行管理。
将分片从一个移动到另一个,在使用 Elasticsearch 中,鲜有需要使用该接口去移动分片,更多的是使用 AllocationDecider 参数以及平衡参数去自动调整 shard 的位置。
在一些特别的情况下,例如发现大部分热点数据集中在几个,可以考虑手工 move 一下。
explain api 是 Elasticsearch 5.x 以后加入因为kafka积压的数据比较多,客户使用logstash消费kafka数据时,反馈有两个问题:的非常实用的运维接口,可以用来诊断 shard 为什么没有分配,以及 shard 为什么分配在某个。
如果不提供参数调用该 api,Elasticsearch 返回个 unassigned shard 未分配的原因。
在索引过程中,Elasticsearch 首先在 primary shard 上执行索引作,之后将作发送到 replica shards 执行,通过这种方式使 primary 和 replica 数据同步。
对于同一个分片的所有 replicas,Elasticsearch 在集群的全局状态里保存所有处于同步状态的分片,称为 in-sync copies。
如果修改作在 primary shard 执行成功,在 replica 上执行失败,则 primary 和 replica 数据就不在同步,这时 Elasticsearch 会将修改作失败的 replica 标记为 stale,并更新到集进行 refresh 作,清空buffer,文档可被搜索但尚未 flush 到磁盘。translog不会清空:群状态里。
当由于某种原因,对于某个 shard 集群中可用数据只剩 stale 分片时,集群会处于 red 状态,并不会主动将 stale shard 提升为 primary shard,因为该 shard 的数据不是的。这时如果不得不将 stale shard 提升为主分片,需要人工介入:
当由于 lucene index 损坏或者磁盘故障导致某个分片的主副本都丢失时,为了能使集群恢复 green 状态,的方法是划分一个空 shard。
一定要慎用该作,会导致对应分片的数据完全清空。
一般来说,增加主分片数量可以增加写入速度和查询速度,因为数据分布到了更多的,可以利用更多的计算和 IO 资源。增加副分片数量可以提升查询速度,并发的查询可以在多个分片之间轮询。
但是 shard 管理并不是 “免费” 的,shard 数量过多会消耗更多的 cpu、内存资源,引发一系列问题,主要包括如下几个方面。
任一时刻,一个集群中只有一个是 , 负责维护集群的状态信息,而且状态的更新是在单线程中运行的,大量的 shard 会导致集群状态相关的修改作缓慢,比如创建索引、删除索引,更新 setting 等。
我们曾经在单个集群维护 30 多万分片,集群完全重启有时候需要2-4个小时的时间,对于业务来说是难以忍受的。
查询很多小分片会降低单个 shard 的查询时间,但是如果分片过多,会导致查询任务在队列中排队,最终可能会增加查询的整体时间消耗。
Elasticsearch 协调接收到查询后,会将查询分发到查询涉及的所有 shard 并行执行,之后协调对各个 shard 的查询结果进行归并。
如果有很多小分片,增加协调的内存压力,同时会增加整个集群的 cpu 压力,甚至发生拒绝查询的问题。因为我们经常会设置参与搜索作的分片数上限,以保护集群资源和稳定性,分片数设置过大会更容易触发这个上限。
分片平衡对 Elasticsearch 稳定高效运行至关重要。下面介绍 Elasticsearch 提供的分片平衡参数。
当使用 cluster.routing.allocation.balance.shard 和 index.routing.allocation.total_shards_per_node 不能使分片平衡时,就需要通过该参数来控制分片的分布。
所以,我们的经验是: 创建索引时,尽量将该值设置的小一些,以使索引的 shard 比较平均的分布到集群内的所有。
但是也要使个别离线时,分片能分配到在线,对于有 10 个几点的集群,如果单个索引的主副本分片总数为 10,如果将该参数设置成 1,当一个离线时,集群就无法恢复成 Green 状态了。
所以我们的建议一般是保证一个离线后,也可以使集群恢复到 Green 状态。
Elasticsearch 内部的平衡策略都是基于 shard 数量的,所以在运行一段时间后,如果不同索引的 shard 物理大小距很大,最终会出现磁盘使用不平衡的情况。
所以,目前来说避免该问题的以办法是让集群内的 shard 物理大小尽量保持相近。
主对 shard 的管理是一种代价相对比较昂贵的作,因此在满足需求的情况下建议尽量减少 shard 数量,将分片数量和分片大小控制在合理的范围内,可以避免很多问题。
下一节我们将介绍 分片内部的段合并 相关问题。
elasticsearch索引主要实现方式
Elasticsear下面是一个已经将Docs刷入段,但还没有完全提交的示意图:ch是什么?
Elasticsearch是位于ElasticStack核心的分布式搜索和分析引擎。Logstash和Beats有助于收集、聚合和丰富您的数据并将其存储在Elasticsearch中。Kibana使您能够以交互方式探索、可视化和分享对数据的见解,并管理。
Elasticsearch是一个分布式文档存储。Elasticsearch存储的是序列化为JSON文档的复杂数据结构,而不是以列行数据的形式存储信息。当集群中有多个Elasticsearch时,存储的文档分布在整个集群中,可以立即从任何访问。
Elasticsearch是由ShayBanon发起的一个开源搜索项目,2010年2月发布。迄今,该项目已发展成为搜索和数据分析解决方案领域的主要一员,广泛应用于声名卓著或鲜为人知的搜索应用程序。
Elasticsearch是一个高度可扩展的开源全文搜索和分析引擎。它可以在很短的时间内存储,搜索和分析大量的数据。它通常作为具有复杂搜索场景情况下的核心发动机。
搜索引擎,不支持join表等作。主要用于全文检索。不适合做数据库。
如何选择合适的数据库解决方案?
1、如果有强大的技术团队,关系型和非关系型数据库都可选择。一般来讲,非关系型数据库需要更多管理维护的时间。
3、(一)、Access(二)SQL(三)MySQL,Access是一种桌面数据库,只适合数据量少的应用,在处理少量数据和单机访问的数据库时是很好的,效率也很高。但是它的同时访问客户端不能多于4个。
5、例如,如果你需要的是数据分析仓库,关系数据库可能不是一个适合的选择;如果你处理事务的应用要求严格的数据完整性和一致性,就不要考虑NoSQL了。不要重新发明轮子在过去的数十年,开源数据库技术迅速发展壮大。
6、本文首先讨论了基于第三范式的数据库表的基本设计,着重论述了建立主键和索引的策略和方案,然后从数据库表的扩展设计和库表对象的放置等角度概述了数据库管理系统的优化方案。
ElasticSearch倒排索引及其原理
1、倒排索引采用ImmutableDesign,一旦生成,不可更改。Segment写入磁盘的过程相对耗时,所以借助文件系统缓存,Refresh时,先将Segment写入文件缓存中,以开放查询。
2、之前我们已经了解过,Elasticsearch是一个基于Lucene实现的分布式全文检索引擎,其实Elasticsearch倒排索引就是Lucene的倒排索引。
3、所谓的倒排索引,就是把你的数据内容先分词,每句话分成一个一个的,然后记录好每一个对应出现在了哪些id标识的数据。
4、可以将对es的作记录下来,来确保当出现故障的时候,已经落地到磁盘的数据不会丢失,并在重启的时候可以从作记录中将数据恢复过来。
5、Elasticsearch中使用一种称为倒排索引的结构,适用于快速的全文搜索。一个倒排索引由文档中所有不能重复词的列表构成,对于其中每个词,有一个包含它的文档列表。
elasticsearch-倒排索引原理
1、倒排索引采用ImmutableDesign,一旦生成,不可更改。Segment写入磁盘的过程相对耗时,所以借助文件系统缓存,Refresh时,先将Segment写入文件缓存中,以开放查询。
2、Elasticsearch中使用一种称为倒排索引的结构,适用于快速的全文搜索。一个倒排索引由文档中所有不能重复词的列表构成,对于其中每个词,有一个包含它的文档列表。
3、elasticsearch提供了translog来记录这些作,结合oscachedsegments数据定时落盘来实现数据可靠性保证(flush)。文档被添加到buffer同时追加到translog:进行refresh作,清空buffer,文档可被搜索但尚未flush到磁盘。
4、如果Elasticsearch密钥库受密码保护,则必须先输入密钥库密码,然后才能为内置用户设置密码。为弹性用户设置密码后,密码不再有效,无法使用该命令。在某些情况下,分片副本的Lucene索引或事务日志可能会损坏。
5、Elasticsearch的查询原理是将查询的与倒排索引中的词条进行匹配,查询的与倒排索引中的词条必须完全相同视为匹配,否则不匹配。这意味着在插入文档时是否进行分析和查询时是否进行分析将产生非常不同的结果。
6、财务平台亿级数据量毫秒级查询优化之elasticsearch原理解析_wang123459的博客-CSDN博客_elasticsearch查询优化mysql底层B-tree支持矮胖,高胖的时候就很难受,说白了就是数据量多会增加IO作。ES底层倒排索引。
Elasticsearch
一般情况下如果es服务正常启动,可以通过接口的方式获取elasticsearch版本信息:c://10.1:9200上述命令可以得到elasticsearch的服务状态和其他信息包括版本号。
Elasticsearch是位于Elast2、refresh过程有点区别icStack核心的分布式搜索和分析引擎。Logstash和Beats有助于收集、聚合和丰富您的数据并将其存储在Elasticsearch中。
ElasticSearch是一个基于Lucene的搜索。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTfulweb接口。Elasticsearch是用Ja开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。
Elasticsearch架构简单介绍如下。索引索引(index)是Elasticsearch对逻辑数据的逻辑存储,所以它可以分为更小的部分。你可以把索引看成关系型数据库的表。然而,索引的结构是为快速有效的全文索引准备的,特别是它不存储原始值。
如何用elasticsearch5.2实现全文索引
1、安装ik分词器到elasticsearch很简单,它有个插件目录ysis-ik,和一个配置目录ik,分别拷贝到plugins和conf目录就可以了。
2、ES使用倒序索引来加速全文索引。一个倒序索引由两部分组成:如果我们想要搜索quickbrown,我们仅仅只需要找每一个term出现的文档即可。如下图:每一个文档都匹配到了,但是个比第二个要匹配的多。
3、每次将文本类型数据插入Elasticsearch索引时,都会对其进行分析,然后存储在反向索引中。根据分析器的配置方式,这会影响您的搜索功能,因为分析器也适用于全文搜索。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系 836084111@qq.com 删除。