易陆发现互联网技术论坛

 找回密码
 开始注册
查看: 1321|回复: 0
收起左侧

ElasticSearch进阶篇集群+原理

[复制链接]
发表于 2021-12-16 17:01:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?开始注册

x
ElasticSearch进阶篇集群+原理
1.相关概念解释: @. c( B5 {' S& _
(1)Near Realtime(NRT):近实时,两个意思,从写入数据到数据可以被搜索到有一个小延迟(大概1秒);基于es执行搜索和分析可以达到秒级
(2)Cluster:集群,包含多个节点,每个节点属于哪个集群是通过一个配置(集群名称,默认是elasticsearch)来决定的,对于中小型应用来说,刚开始一个集群就一个节点很正常
(3)Node:节点(简单理解为集群中的一个服务器),集群中的一个节点,节点也有一个名称(默认是随机分配的),节点名称很重要(在执行运维管理操作的时候),默认节点会去加入一个名称为“elasticsearch”的集群,如果直接启动一堆节点,那么它们会自动组成一个elasticsearch集群,当然一个节点也可以组成一个elasticsearch集群
(4)Index:索引(简单理解就是一个数据库),包含一堆有相似结构的文档数据,比如可以有一个客户索引,商品分类索引,订单索引,索引有一个名称。一个index包含很多document,一个index就代表了一类类似的或者相同的document。比如说建立一个product index,商品索引,里面可能就存放了所有的商品数据,所有的商品document。
(5)Type:类型(简单理解就是一张表),每个索引里都可以有一个或多个type,type是index中的一个逻辑数据分类,一个type下的document,都有相同的field,比如博客系统,有一个索引,可以定义用户数据type,博客数据type,评论数据type。
(6)Document&field:文档(就是一行数据),es中的最小数据单元,一个document可以是一条客户数据,一条商品分类数据,一条订单数据,通常用JSON数据结构表示,每个index下的type中,都可以去存储多个document。一个document里面有多个field,每个field就是一个数据字段。
(7)shard:单台机器无法存储大量数据,es可以将一个索引中的数据切分为多个shard,分布在多台服务器上存储。有了shard就可以横向扩展,存储更多数据,让搜索和分析等操作分布到多台服务器上去执行,提升吞吐量和性能。每个shard都是一个lucene index。
(8)replica:任何一个服务器随时可能故障或宕机,此时shard可能就会丢失,因此可以为每个shard创建多个replica副本。replica可以在shard故障时提供备用服务,保证数据不丢失,多个replica还可以提升搜索操作的吞吐量和性能。primary shard(建立索引时一次设置,不能修改,默认5个),replica shard(随时修改数量,默认1个),默认每个索引10个shard,5个primary shard,5个replica shard,最小的高可用配置,是2台服务器。
2ElasticSearch分布式架构原理1 o2 m5 P9 P' o, y
2.1shad与replica机制& n: z+ ?5 _2 s# z" N$ ~* G
(1)一个index包含多个shard,也就是一个index存在多个服务器上
(2)每个shard都是一个最小工作单元,承载部分数据,比如有三台服务器,现在有三条数据,这三条数据在三台服务器上各方一条.
(3)增减节点时,shard会自动在nodes中负载均衡
(4)primary shard和replica shard,每个document肯定只存在于某一个primary shard以及其对应的replica shard中,不可能存在于多个primary shard
(5)replica shard是primary shard的副本,负责容错,以及承担读请求负载
(6)primary shard的数量在创建索引的时候就固定了,replica shard的数量可以随时修改
(7)primary shard的默认数量是5,replica默认是1,默认有10个shard,5个primary shard,5个replica shard
(8)primary shard不能和自己的replica shard放在同一个节点上(否则节点宕机,primary shard和副本都丢失,起不到容错的作用),但是可以和其他primary shard的replica shard放在同一个节点上
2.2分布式架构图
" d1 ]- }6 h  U. K) V" Q5 M5 g
2.3容错机制
0 A2 {. k/ J( p7 A* x+ }在集群中会有一个master负责当leader进行协调,比如上图的Node2为master, 那么当它挂了的时候会重现选举一个新的master,比如新选举的是Node3,这个时候replica 2这时候会变成primary.
当Node2恢复了的时候,这个时候node2的prinary会变成replica
2.4ES写入数据的过程
' Z, u/ ~4 f1 f. i0 J! Z' A2.4.1简单流程:8 `! k7 V# ^! ?$ f2 _
客户端选择一个node发送请求过去,这个node就是coordinating node (协调节点)# j: F% f$ i2 g1 O; ?# d8 v
coordinating node,对document进行路由,将请求转发给对应的node1 E+ O. }! u' L- Z  V' A" i
实际上的node上的primary shard处理请求,然后将数据同步到replica node
6 B1 n7 l$ U7 L: H9 X$ Hcoordinating node,如果发现primary node和所有的replica node都搞定之后,就会返回请求到客户端
$ P- X" b& B+ O2 Z) m6 O, h; C7 S/ T      这个路由简单的说就是取模算法,比如说现在有3太服务器,这个时候传过来的id是5,那么5%3=2,就放在第2太服务器
2.4.2写入数据底层原理:
( c! e5 a" o+ H4 n  
数据先写入到buffer里面,在buffer里面的数据时搜索不到的,同时将数据写入到translog日志文件之中4 {, ^' w0 I, q0 q) Y
如果buffer快满了,或是一段时间之后(定时),就会将buffer数据refresh到一个新的OS cache之中,然后每隔1秒,就会将OS cache的数据写入到segment file之中,但是如果每一秒钟没有新的数据到buffer之中,就会创建一个新的空的segment file,只要buffer中的数据被refresh到OS cache之中,就代表这个数据可以被搜索到了。当然可以通过restful api 和Java api,手动的执行一次refresh操作,就是手动的将buffer中的数据刷入到OS cache之中,让数据立马搜索到,只要数据被输入到OS cache之中,buffer的内容就会被清空了。同时进行的是,数据到shard之后,就会将数据写入到translog之中,每隔5秒将translog之中的数据持久化到磁盘之中
1 Q0 K# @4 l8 a/ e0 c重复以上的操作,每次一条数据写入buffer,同时会写入一条日志到translog日志文件之中去,这个translog文件会不断的变大,当达到一定的程度之后,就会触发commit操作。$ Z) W1 U' M+ H8 S7 _( A7 T4 z1 k
将一个commit point写入到磁盘文件,里面标识着这个commit point 对应的所有segment file$ W8 d3 n# j. B
强行将OS cache 之中的数据都fsync到磁盘文件中去。
& z0 e# q7 a. b5 B) I解释:translog的作用:在执行commit之前,所有的而数据都是停留在buffer或OS cache之中,无论buffer或OS cache都是内存,一旦这台机器死了,内存的数据就会丢失,所以需要将数据对应的操作写入一个专门的日志问价之中,一旦机器出现宕机,再次重启的时候,es会主动的读取translog之中的日志文件的数据,恢复到内存buffer和OS cache之中。$ ^& G/ Y8 ]" l/ G9 _; e
将现有的translog文件进行清空,然后在重新启动一个translog,此时commit就算是成功了,默认的是每隔30分钟进行一次commit,但是如果translog的文件过大,也会触发commit,整个commit过程就叫做一个flush操作,我们也可以通过ES API,手动执行flush操作,手动将OS cache 的数据fsync到磁盘上面去,记录一个commit point,清空translog文件
) v0 M5 O3 i8 `6 |3 l' z+ X补充:其实translog的数据也是先写入到OS cache之中的,默认每隔5秒之中将数据刷新到硬盘中去,也就是说,可能有5秒的数据仅仅停留在buffer或者translog文件的OS cache中,如果此时机器挂了,会丢失5秒的数据,但是这样的性能比较好,我们也可以将每次的操作都必须是直接fsync到磁盘,但是性能会比较差。  [6 \7 m8 f. h' a( w! I
如果时删除操作,commit的时候会产生一个.del文件,里面讲某个doc标记为delete状态,那么搜索的时候,会根据.del文件的状态,就知道那个文件被删除了。# A2 S* O: x6 B# W+ P$ A
如果时更新操作,就是讲原来的doc标识为delete状态,然后重新写入一条数据即可。
8 e. E1 O( {, Sbuffer每次更新一次,就会产生一个segment file 文件,所以在默认情况之下,就会产生很多的segment file 文件,将会定期执行merge操作7 m# _( j+ n, O) `
每次merge的时候,就会将多个segment file 文件进行合并为一个,同时将标记为delete的文件进行删除,然后将新的segment file 文件写入到磁盘,这里会写一个commit point,标识所有的新的segment file,然后打开新的segment file供搜索使用。
8 T  C6 i* z- l, m5 \2.5ES查询过程
( N  p4 f* z0 _4 N+ l  J+ r2.5.1倒排序算法. e0 j& y' @5 r7 L
查询有个算法叫倒排序:简单的说就是:通过分词把词语出现的id进行记录下来,再查询的时候先去查到哪些id包含这个数据,然后再根据id把数据查出来. 要是不理解的可以先去查下什么是倒排序
2.5.2查询过程% D  ~1 {( |. o' Y5 F) N
客户端发送一个请求给coordinate node+ B( S+ |; u1 L: T3 m# M
协调节点将搜索的请求转发给所有的shard对应的primary shard 或replica shard& @! d: G! p: ~' D* }
query phase:每一个shard 将自己搜索的结果(其实也就是一些唯一标识),返回给协调节点,有协调节点进行数据的合并,排序,分页等操作,产出最后的结果
( i/ K; Q& Y* W2 f$ {fetch phase ,接着由协调节点,根据唯一标识去各个节点进行拉去数据,最总返回给客户端8 N& K% i( n* K1 w0 H
2.5.3查询原理* k, `. V; U' g4 @5 @
查询过程大体上分为查询和取回这两个阶段,广播查询请求到所有相关分片,并将它们的响应整合成全局排序后的结果集合,这个结果集合会返回给客户端。
查询阶段
当一个节点接收到一个搜索请求,这这个节点就会变成协调节点,第一步就是将广播请求到搜索的每一个节点的分片拷贝,查询请求可以被某一个主分片或某一个副分片处理,协调节点将在之后的请求中轮训所有的分片拷贝来分摊负载。
, x  g' T  ]# `( \" _( g. |每一个分片将会在本地构建一个优先级队列,如果客户端要求返回结果排序中从from 名开始的数量为size的结果集,每一个节点都会产生一个from+size大小的结果集,因此优先级队列的大小也就是from+size,分片仅仅是返回一个轻量级的结果给协调节点,包括结果级中的每一个文档的ID和进行排序所需要的信息。
7 i3 E" r4 t  y1 C$ h7 T" \3 ]' ]协调节点将会将所有的结果进行汇总,并进行全局排序,最总得到排序结果。
  ~; u, O" D& E( w取值阶段
查询过程得到的排序结果,标记处哪些文档是符合要求的,此时仍然需要获取这些文档返回给客户端
  U" v& S$ a, Z0 V7 G3 M协调节点会确定实际需要的返回的文档,并向含有该文档的分片发送get请求,分片获取的文档返回给协调节点,协调节点将结果返回给客户端9 _  N$ }8 A- |, K; m0 ^; x
2.6更新过程
, k" m$ j$ z( ?  Q6 p9 W) N/ x/ _2.6.1document的全量替换
+ p* r  y0 _% J1 @这个就是用新的数据全部覆盖以前的数据
6 |& e2 U! N9 z9 I$ H- O重新创建一个document并把原来的标记为delete! {9 E. ]: E- _2 i) d. ]( p
partial update, 就是制定需要更新的字段.
         全量是把数据找出来,然后再java代码中进行修改,再放回去.
          partial是直接提交需要修改的字段然后直接修改,在一个shard中进行,内部也是全量替换.
: U% W7 x' D0 Z- @7 ~
2.6.2强制创建1 w  O% ~" ^9 [* j1 p
就是不管原来的数据,直接强制创建一个新的
2.7删除过程$ u' i0 I# ^2 h5 {! A: ~& T
当要进行删除document的时候,只是把它标记为delete,当数据到达一定的时候再进行删除, 有点像JVM中标记清除法
3.Es并发解决方案: e% y- _9 G9 `1 ~$ T' B
为什么会出现并发问题,简单的说就是多个线程去操作同一个数据.
假如现在下单系统下2单,都要去减库存(100件),第一个线程进去减1件100-1=99,这时候还没更像到ES中,第二线程进去了,也要减一个库存100-1=99.现在系统卖出去2个,可是库存却还有99个,应该是98个
3.1解决方案-悲观锁; `7 t9 y9 o. o1 J6 R7 ?
3.2解决方案-乐观锁4 ]$ ~5 s% `  }1 ]( A& W9 |, [
温馨提示,乐观锁会出现ABA情况
下面是2种解决方案,在网上找的图片:
$ |! @, P9 W5 G
  {3 r; g; y2 J. U4 m
您需要登录后才可以回帖 登录 | 开始注册

本版积分规则

关闭

站长推荐上一条 /4 下一条

北京云银创陇科技有限公司以云计算运维,代码开发

QQ|返回首页|Archiver|小黑屋|易陆发现技术论坛 ( 蜀ICP备2026014127号-1 )点击这里给我发消息

GMT+8, 2026-4-8 21:40 , Processed in 0.049524 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

© 2012-2025 Discuz! Team.

快速回复 返回顶部 返回列表