易陆发现互联网技术论坛

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

ElasticSearch进阶篇集群+原理

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

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

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

x
ElasticSearch进阶篇集群+原理
1.相关概念解释
6 f- T# t$ G! P; s- r(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分布式架构原理
6 V! @  S( j4 _# i6 @$ v2.1shad与replica机制
7 s8 x' B6 c* o( Z+ ]/ R/ M(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分布式架构图

; W( b5 c5 e" |( U+ `; i3 R2.3容错机制6 i3 y$ h4 h- S& e9 B0 O% h
在集群中会有一个master负责当leader进行协调,比如上图的Node2为master, 那么当它挂了的时候会重现选举一个新的master,比如新选举的是Node3,这个时候replica 2这时候会变成primary.
当Node2恢复了的时候,这个时候node2的prinary会变成replica
2.4ES写入数据的过程
5 W$ k0 x2 t; U# V* y5 q  r: x2.4.1简单流程:
* |# l" E4 Q* \. T0 d# p客户端选择一个node发送请求过去,这个node就是coordinating node (协调节点); {4 |: a. n! e( M& E2 a. L2 n
coordinating node,对document进行路由,将请求转发给对应的node
& [# t3 l9 S9 N& z实际上的node上的primary shard处理请求,然后将数据同步到replica node) L% A" p: x7 @" S7 M& Y8 O
coordinating node,如果发现primary node和所有的replica node都搞定之后,就会返回请求到客户端, z4 H2 }: S  [& [- q
      这个路由简单的说就是取模算法,比如说现在有3太服务器,这个时候传过来的id是5,那么5%3=2,就放在第2太服务器
2.4.2写入数据底层原理:
" y1 b# x1 O  r, R+ A  v, t1 L  
数据先写入到buffer里面,在buffer里面的数据时搜索不到的,同时将数据写入到translog日志文件之中
3 c% T. h" X, \( i$ k9 D8 ?如果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之中的数据持久化到磁盘之中( H& _5 ]+ b4 e: H- }" |, G# ~, Y
重复以上的操作,每次一条数据写入buffer,同时会写入一条日志到translog日志文件之中去,这个translog文件会不断的变大,当达到一定的程度之后,就会触发commit操作。9 c% p1 v$ M3 b4 \0 E
将一个commit point写入到磁盘文件,里面标识着这个commit point 对应的所有segment file
5 r6 m, U% k& F5 D0 M6 P强行将OS cache 之中的数据都fsync到磁盘文件中去。: T' s3 @2 ~+ L5 ^4 o
解释:translog的作用:在执行commit之前,所有的而数据都是停留在buffer或OS cache之中,无论buffer或OS cache都是内存,一旦这台机器死了,内存的数据就会丢失,所以需要将数据对应的操作写入一个专门的日志问价之中,一旦机器出现宕机,再次重启的时候,es会主动的读取translog之中的日志文件的数据,恢复到内存buffer和OS cache之中。
* p  d+ m% o% O% C% `) K5 d  n7 a将现有的translog文件进行清空,然后在重新启动一个translog,此时commit就算是成功了,默认的是每隔30分钟进行一次commit,但是如果translog的文件过大,也会触发commit,整个commit过程就叫做一个flush操作,我们也可以通过ES API,手动执行flush操作,手动将OS cache 的数据fsync到磁盘上面去,记录一个commit point,清空translog文件
$ J2 n( x0 f6 R7 X. H0 t6 y) `补充:其实translog的数据也是先写入到OS cache之中的,默认每隔5秒之中将数据刷新到硬盘中去,也就是说,可能有5秒的数据仅仅停留在buffer或者translog文件的OS cache中,如果此时机器挂了,会丢失5秒的数据,但是这样的性能比较好,我们也可以将每次的操作都必须是直接fsync到磁盘,但是性能会比较差。; i7 R2 T! l5 o; c; f  L
如果时删除操作,commit的时候会产生一个.del文件,里面讲某个doc标记为delete状态,那么搜索的时候,会根据.del文件的状态,就知道那个文件被删除了。( b& [8 K& {" E0 b  q. a, j
如果时更新操作,就是讲原来的doc标识为delete状态,然后重新写入一条数据即可。
( F/ |' _2 D) S. }buffer每次更新一次,就会产生一个segment file 文件,所以在默认情况之下,就会产生很多的segment file 文件,将会定期执行merge操作
( z9 @7 {. I, U) V9 F/ Y每次merge的时候,就会将多个segment file 文件进行合并为一个,同时将标记为delete的文件进行删除,然后将新的segment file 文件写入到磁盘,这里会写一个commit point,标识所有的新的segment file,然后打开新的segment file供搜索使用。) u5 w2 e, x; E" k
2.5ES查询过程5 z5 j" l% _, x
2.5.1倒排序算法: ?* E* b3 @) ]( ^
查询有个算法叫倒排序:简单的说就是:通过分词把词语出现的id进行记录下来,再查询的时候先去查到哪些id包含这个数据,然后再根据id把数据查出来. 要是不理解的可以先去查下什么是倒排序
2.5.2查询过程
: w  [3 {2 |% Q6 u( P' K  q客户端发送一个请求给coordinate node5 ?2 }8 `) m! G5 U. Y6 F( P
协调节点将搜索的请求转发给所有的shard对应的primary shard 或replica shard9 [9 y: v' z6 M4 G$ `! f
query phase:每一个shard 将自己搜索的结果(其实也就是一些唯一标识),返回给协调节点,有协调节点进行数据的合并,排序,分页等操作,产出最后的结果& h; ^- E# j3 ^, H3 a1 \. D; r
fetch phase ,接着由协调节点,根据唯一标识去各个节点进行拉去数据,最总返回给客户端
6 w- E, `/ g; v4 M7 ]  A% L, E+ d2.5.3查询原理9 e5 h/ S& u& A
查询过程大体上分为查询和取回这两个阶段,广播查询请求到所有相关分片,并将它们的响应整合成全局排序后的结果集合,这个结果集合会返回给客户端。
查询阶段
当一个节点接收到一个搜索请求,这这个节点就会变成协调节点,第一步就是将广播请求到搜索的每一个节点的分片拷贝,查询请求可以被某一个主分片或某一个副分片处理,协调节点将在之后的请求中轮训所有的分片拷贝来分摊负载。1 X" ?, w/ m' e9 C+ l
每一个分片将会在本地构建一个优先级队列,如果客户端要求返回结果排序中从from 名开始的数量为size的结果集,每一个节点都会产生一个from+size大小的结果集,因此优先级队列的大小也就是from+size,分片仅仅是返回一个轻量级的结果给协调节点,包括结果级中的每一个文档的ID和进行排序所需要的信息。
6 j4 I4 {: }( \1 w8 t! `" j9 I0 @协调节点将会将所有的结果进行汇总,并进行全局排序,最总得到排序结果。% k, ^6 h4 |( w/ N0 a7 d
取值阶段
查询过程得到的排序结果,标记处哪些文档是符合要求的,此时仍然需要获取这些文档返回给客户端
9 V' Z- [; U" I9 p2 I协调节点会确定实际需要的返回的文档,并向含有该文档的分片发送get请求,分片获取的文档返回给协调节点,协调节点将结果返回给客户端
" [6 R) A, m6 M, ^& Z2.6更新过程: A& H0 J- t* X. {  H9 U/ ^
2.6.1document的全量替换. l8 r$ P  z! l& ]3 {+ U8 n1 i! j, W
这个就是用新的数据全部覆盖以前的数据
. _  a; h- z" Y" Q# g6 K6 Z: e重新创建一个document并把原来的标记为delete
1 f8 [: S, e7 Q8 w: X  n* a4 V+ ]partial update, 就是制定需要更新的字段.
         全量是把数据找出来,然后再java代码中进行修改,再放回去.
          partial是直接提交需要修改的字段然后直接修改,在一个shard中进行,内部也是全量替换.
% i. Q* G% k0 ^* d9 K5 f& \3 U
2.6.2强制创建' P/ {2 }1 I2 ]4 v
就是不管原来的数据,直接强制创建一个新的
2.7删除过程7 ?6 n, T5 s' }/ z# b, Z
当要进行删除document的时候,只是把它标记为delete,当数据到达一定的时候再进行删除, 有点像JVM中标记清除法
3.Es并发解决方案
. A- o* [1 S; s( s# e! Y1 D! f  u1 E为什么会出现并发问题,简单的说就是多个线程去操作同一个数据.
假如现在下单系统下2单,都要去减库存(100件),第一个线程进去减1件100-1=99,这时候还没更像到ES中,第二线程进去了,也要减一个库存100-1=99.现在系统卖出去2个,可是库存却还有99个,应该是98个
3.1解决方案-悲观锁
9 P2 |4 C% C3 |, L. e- A3.2解决方案-乐观锁! B0 I# V: c/ C% J& v
温馨提示,乐观锁会出现ABA情况
下面是2种解决方案,在网上找的图片:

2 p) {2 V" F3 w2 f

7 x5 c' y  H2 l. L, O. E! H) A
您需要登录后才可以回帖 登录 | 开始注册

本版积分规则

关闭

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

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

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

GMT+8, 2026-4-8 21:38 , Processed in 0.046654 second(s), 22 queries .

Powered by Discuz! X3.4 Licensed

© 2012-2025 Discuz! Team.

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