ElasticSearch版本控制

ElasticSearch版本控制

对人工智能感兴趣的同学,可以点击以下链接:

现在人工智能非常火爆,很多朋友都想学,但是一般的教程都是为博硕生准备的,太难看懂了。最近发现了一个非常适合小白入门的教程,不仅通俗易懂而且还很风趣幽默。所以忍不住分享一下给大家。点这里可以跳转到教程。

https://www.cbedai.net/u014646662

当使用 index API更新文档的时候, 我们读取原始文档, 做修改, 然后将整个文档(wholedocument)一次性重新索引。 最近的索引请求会生效——Elasticsearch中只存储最后被索引的任何文档。 如果其他人同时也修改了这个文档, 他们的修改将会丢失。

很多时候, 这并不是一个问题。 或许我们主要的数据存储在关系型数据库中, 然后拷贝数据到Elasticsearch中只是为了可以用于搜索。 或许两个人同时修改文档的机会很少。 亦或者偶尔的修改丢失对于我们的工作来说并无大碍。

但有时丢失修改是一个很严重的问题。 想象一下我们使用Elasticsearch存储大量在线商店的库存信息。 每当销售一个商品, Elasticsearch中的库存就要减一。一天, 老板决定做一个促销。 瞬间, 我们每秒就销售了几个商品。 想象两个同时运行的web进程, 两者同时处理一件商品的订单:

web_1 让 stock_count 失效是因为 web_2 没有察觉到 stock_count 的拷贝已经过期( 译者注: web_1 取数据, 减一后更新了 stock_count 。 可惜在 web_1 更新 stock_count 前它就拿到了数据, 这个数据已经是过期的了, 当 web_2 再回来更新 stock_count 时这个数字就是错的。 这样就会造成看似卖了一件东西, 其实是卖了两件, 这个应该属于幻读。 ) 。 结果是我们认为自己确实还有更多的商品, 最终顾客会因为销售给他们没有的东西而失望。

变化越是频繁, 或读取和更新间的时间越长, 越容易丢失我们的更改。
在数据库中, 有两种通用的方法确保在并发更新时修改不丢失:

悲观并发控制( Pessimistic concurrency control)

这在关系型数据库中被广泛的使用, 假设冲突的更改经常发生, 为了解决冲突我们把访问区块化。 典型的例子是在读一行数据前锁定这行, 然后确保只有加锁的那个线程可以修改这行数据。

乐观并发控制( Optimistic concurrency control)

被Elasticsearch使用, 假设冲突不经常发生, 也不区块化访问, 然而, 如果在读写过程中数据发生了变化, 更新操作将失败。 这时候由程序决定在失败后如何解决冲突。 实际情况中,可以重新尝试更新, 刷新数据( 重新读取) 或者直接反馈给用户。

乐观并发控制

Elasticsearch是分布式的。 当文档被创建、 更新或删除, 文档的新版本会被复制到集群的其它节点。 Elasticsearch即是同步的又是异步的, 意思是这些复制请求都是平行发送的, 并无序(out of sequence)的到达目的地。 这就需要一种方法确保老版本的文档永远不会覆盖新的版本。
上文我们提到 index 、 get 、 delete 请求时, 我们指出每个文档都有一个 _version 号码,这个号码在文档被改变时加一。 Elasticsearch使用这个 _version 保证所有修改都被正确排序。 当一个旧版本出现在新版本之后, 它会被简单的忽略。我们利用 _version 的这一优点确保数据不会因为修改冲突而丢失。 我们可以指定文档的 version 来做想要的更改。 如果那个版本号不是现在的, 我们的请求就失败了。

创建一篇博文


PUT /website/blog/1/_create
{
"title": "My first blog entry",
"text": "Just trying this out..."
}

查看

GET /website/blog/1

结果

一个新建的文档, 它的 _version 是 1,现在, 当我们通过重新索引文档保存修改时, 我们这样指定了 version 参数:
 

PUT /website/blog/1?version=1 

版本号一致,请求成功, 响应体告诉我们 _version 已经增加到 2 

依旧传递版本号为1,执行出错

如果不传递版本号,默认增加1

使用外部版本控制系统

一种常见的结构是使用一些其他的数据库做为主数据库, 然后使用Elasticsearch搜索数据,这意味着所有主数据库发生变化, 就要将其拷贝到Elasticsearch中。 如果有多个进程负责这些数据的同步, 就会遇到上面提到的并发问题。
如果主数据库有版本字段或一些类似于 timestamp 等可以用于版本控制的字段是你就可以在Elasticsearch的查询字符串后面添加 version_type=external 来使用这些版本号。 版本号必须是整数, 大于零小于 9.2e+18 ,就是Java中的正的 long 。外部版本号与之前说的内部版本号在处理的时候有些不同。 它不再检查 _version 是否与请求中指定的一致, 而是检查是否小于指定的版本。 如果请求成功, 外部版本号就会被存储到 _version 中。
外部版本号不仅在索引和删除请求中指定, 也可以在创建(create)新文档中指定。
例如, 创建一个包含外部版本号 10 的新博客, 我们可以这样做:
 

PUT /website/blog/2?version=5&version_type=external
{
"title": "My first external blog entry",
"text": "Starting to get the hang of this..."
}

如果你重新运行这个请求, 就会返回一个像之前一样的冲突错误, 因为指定的外部版本号不大于当前在Elasticsearch中的版本。
 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值