前面《简单入门实战》一节中,有介绍bulk的使用示例,你们必定很奇怪,还有这么有趣的JSON格式,必须严格照他的换行来作,我想把JSON搞得美观可读性好一点,竟然给我报错!java
{"action": {"meta"}}\n {"data"}\n {"action": {"meta"}}\n {"data"}\n
它为何要这样规定?node
咱们想一想bulk设计的初衷,批处理的执行效率确定是第一优先级,此时效率>可读性,若是咱们容许随意换行,用标准格式的JSON串,会有什么区别?算法
若是是标准格式的JSON串,处理流程通常会是这样:json
这种方式惟一的缺点就是占用内存多,一份json串,解析为JSONArray对象,内存占用翻番,bulk里面多则几千条请求,若是JSON报文大一点,这内存耗费不是开玩笑的,若是bulk占用的内存过多,就可能会挤压其余请求的内存使用量,如搜索请求、数据分析请求等,总体性能会急速降低,严重的状况可能会触发Full GC,会致使整个JVM工做线程暂停。segmentfault
再看看现有的格式定义:除了delete操做占一行,其余操做都是占两行的,ES收到bulk请求时,就能够简单的按行进行切割,也不用转成json对象了,切割完的JSON读取里面的meta信息,直接路由到相应的shard,收集完响应返回便可。
这样的好处切割逻辑更简单,都是处理小json字符串,内存快拿快放,整个ES避免对内存的大块占用,尽量保证性能。api
增删改的过程总体与查询文档过程一致,只是多了一个数据同步的步骤,整个过程如图所示:数组
类似的步骤不赘述。
步骤3的前提是primary shard操做成功,异步请求,全部的replica都返回成功后,node2响应操做成功的消息给Coordinate Node,最后Coordinate Node向客户端返回成功消息,此时全部的primary shard和replica shard均已完成数据同步,数据是一致的。架构
当咱们使用客户端(Java或Restful API)向Elasticsearch搜索文档数据时,能够向任意一个node发送请求,此时接受请求的node就是Coordinate Node,整个过程如图所示:并发
注意一个问题,若是document还在创建索引过程当中,可能只有primary shard有,任何一个replica shard都没有,此时可能会没法读取到document,可是等document完成索引创建后,primary shard和replica shard就都有了,这个时间间隔,大概1秒左右。负载均衡
Elasticsearch在尝试执行一个写操做时,能够带上consistency参数,声明咱们的写一致性的级别,正确地使用这个级别,为了不因分区故障执行写操做,致使数据不一致,这个参数有三个值供选择:
这个大部分,叫规定数量(quorum),有个计算公式:
int( (primary + number_of_replicas) / 2 ) + 1
若是一个索引有3个primary shard,每一个shard拥有1个replica shard,共6个shard,这样number_of_replicas就是1,代入公式计算:
quorum = int ((3 + 1) / 2) + 1 = 3
因此6个shard中必须有3个是活跃的,才让你写,若是你只启用2个node,这样活跃的replica shard只会有1个,加上primarys shard ,结果最可能是2。这样是达不到quorun的值,所以将没法索引和删除任何文档。
此时你必须启动3个节点,才能知足quorum写一致性的要求。
若是写操做检查前,活跃的shard不够致使没法写入时,Elasticsearch会等待,但愿宕机的node可以恢复,默认60秒,可使用timeout参数修改默认值。
照上面的公式算,1个node的,1个索引1个primary shard,number_of_replicas为1的状况,计算公式:
quorum = int ((1 + 1) / 2) + 1 = 2
实际只有一个primary shard是活跃的,岂不是永远没法写入?我研发机器只启动一个node,不照样增删改查?
原来是Elasticsearch为了不单一node的没法写入问题,加了判断逻辑:只有number_of_replicas大于1的时候,quorum才会生效。
本篇从性能优先的角度简单对bulk的设计做了一些补充,并对文档查询,写操做的原理过程,一致性级别,quorum的计算作了一些简单讲解,谢谢。
专一Java高并发、分布式架构,更多技术干货分享与心得,请关注公众号:Java架构社区