3.11 基于groovy脚本执行partial update
es有内置的脚本支持,可以基于groovy脚本实现复杂的操作
1.修改年龄
POST /lib/user/4/_update { "script": "ctx._source.age+=1" }
2.修改名字
POST /lib/user/4/_update { "script": "ctx._source.last_name+='hehe'" }
3.添加爱好
POST /lib/user/4/_update { "script": { "source": "ctx._source.interests.add(params.tag)", "params": { "tag":"picture" } } } 4.删除爱好
POST /lib/user/4/_update { "script": { "source": "ctx._source.interests.remove(ctx._source.interests.indexOf(params.tag))", "params": { "tag":"picture" } } }
5.删除文档
POST /lib/user/4/_update { "script": { "source": "ctx.op=ctx._source.age==params.count?'delete':'none'", "params": { "count":29 } } }
6.upsert
POST /lib/user/4/_update { "script": "ctx._source.age += 1",
"upsert": { "first_name" : "Jane", "last_name" : "Lucy", "age" : 20, "about" : "I like to collect rock albums", "interests": [ "music" ] } }
3.12 partial update 处理并发冲突
使用的是乐观锁:_version
retry_on_conflict:
POST /lib/user/4/_update?retry_on_conflict=3
重新获取文档数据和版本信息进行更新,不断的操作,最多操作的次数就是retry_on_conflict的值
3.13 文档数据路由原理解析
1.文档路由到分片上:
一个索引由多个分片构成,当添加(删除,修改)一个文档时,es就需要决定这个文档存储在哪个分片上,这个过程就称为数据路由(routing)
2.路由算法:
shard=hash(routing) % number_of_pirmary_shards
示例:一个索引,3个primary shard
(1)每次增删改查时,都有一个routing值,默认是文档的_id的值
(2)对这个routing值使用哈希函数进行计算
(3)计算出的值再和主分片个数取余数
余数肯定在0---(number_of_pirmary_shards-1)之间,文档就在对应的shard上
routing值默认是文档的_id的值,也可以手动指定一个值,手动指定对于负载均衡以及提高批量读取的性能都有帮助
3.primary shard个数一旦确定就不能修改了
3.14 文档增删改内部原理
1:发送增删改请求时,可以选择任意一个节点,该节点就成了协调节点(coordinating node)
2.协调节点使用路由算法进行路由,然后将请求转到primary shard所在节点,该节点处理请求,并把数据同步到它的replica shard
3.协调节点对客户端做出响应
3.15 写一致性原理和quorum机制
1.任何一个增删改操作都可以跟上一个参数 consistency
可以给该参数指定的值:
one: (primary shard)只要有一个primary shard是活跃的就可以执行
all: (all shard)所有的primary shard和replica shard都是活跃的才能执行
quorum: (default) 默认值,大部分shard是活跃的才能执行 (例如共有6个shard,至少有3个shard是活跃的才能执行写操作)
2.quorum机制:多数shard都是可用的,
int((primary+number_of_replica)/2)+1
例如:3个primary shard,1个replica
int((3+1)/2)+1=3
至少3个shard是活跃的
注意:可能出现shard不能分配齐全的情况
比如:1个primary shard,1个replica int((1+1)/2)+1=2 但是如果只有一个节点,因为primary shard和replica shard不能在同一个节点上,所以仍然不能执行写操作
再举例:1个primary shard,3个replica,2个节点
int((1+3)/2)+1=3
最后:当活跃的shard的个数没有达到要求时, es默认会等待一分钟,如果在等待的期间活跃的shard的个数没有增加,则显示timeout
put /index/type/id?timeout=60s
3.16 文档查询内部原理
第一步:查询请求发给任意一个节点,该节点就成了coordinating node,该节点使用路由算法算出文档所在的primary shard
第二步:协调节点把请求转发给primary shard也可以转发给replica shard(使用轮询调度算法(Round-Robin Scheduling,把请求平均分配至primary shard 和replica shard)
第三步:处理请求的节点把结果返回给协调节点,协调节点再返回给应用程序
特殊情况:请求的文档还在建立索引的过程中,primary shard上存在,但replica shar上不存在,但是请求被转发到了replica shard上,这时就会提示找不到文档