版本控制:数据库
在关系数据库管理系统里,悲观并发控制(又名“悲观锁”,Pessimistic Concurrency Control,缩写“PCC”)是一种并发控制的方法。当咱们在读取一个数据前先锁定这一行,而后确保只有读取到数据的这个线程能够修改这一行数据。架构
ES使用的是乐观并发控制(又名”乐观锁”,Optimistic Concurrency Control,缩写”OCC)。 ES不会阻止某一数据的访问,然而,若是基础数据在咱们读取和写入的间隔中发生了变化,更新就会失败,这时候就由程序来决定如何处理这个冲突。它能够从新读取新数据来进行更新,又或者将这一状况直接反馈给用户。并发
ES中的乐观锁curl
当咱们发送get请求的时候 post /exindex/exindex/AVyAgBvA9tISzc84d_4i/返回值为:post
{ "_index": "exindex", "_type": "exindex", "_id": "AVyAgBvA9tISzc84d_4i", "_version": 1, "found": true, "_source": { "school": "支付宝在扣款事务提交以前,向实时消息服务请求发送消息", "name": "sony", "age": "14" } }
这里_version是1,咱们从ES中查询到一条记录,修改完成之后从新PUT创建索引,这时候咱们要把_version做为一个参数传递过去,ES会用该参数和实际的数据进行比对,若是相同则进行重建索引,若是不一样则返回错误信息。请求url 带上本次版本号,而且指定docId,请求以下:
curl -XPUT http://121.49.129.155:9200/exindex/exindex/AVyAgBvA9tISzc84d_4i?version=1 -d' { "name": "Jane", "age": 80, "school": "清华大学" }'
文档修改结束后,返回成功后再次查询后获得的版本号已经变动完毕,_version已经变动为2url
{ "_index": "exindex", "_type": "exindex", "_id": "AVyAgBvA9tISzc84d_4i", "_version": 2, "found": true, "_source": { "name": "Jane", "age": 80, "school": "清华大学" } }
当咱们再次传递版本号为_version=1去尝试更新文档的时候,会报出版本冲突错误 "error":{"root_cause":[{"type":"version_conflict_engine_exception","reason":"[exindex][AVyAgBvA9tISzc84d_4i]: version conflict, current [2] ,当咱们将版本号变动_version=2做为参数传递后,再次修改文档更新成功,版本号自动增长。线程
{ "_index": "exindex", "_type": "exindex", "_id": "AVyAgBvA9tISzc84d_4i", "_version": 3, "found": true, "_source": { "name": "Jane", "age": 80, "school": "北京大学" } }
使用外部版本号控制系统版本控制
一种比较常见的架构应用就是使用一些其余的数据库做为主应用数据库,es只是做为一个检索引擎使用,这也就不可避免的考虑到数据的一致性,数据的版本问题也就出现了。code
若是你的数据库已经存在了版本号,或者是能够表明版本timestamp的时间戳。这时就能够在es的查询url后面添加version_type=external来使用这些号码。 注意:版本号码必需要是大于0小于9223372036854775807(Java中long的最大正值)的整数。索引
外部版本号与以前说的内部版本号在处理的时候有些不一样。它再也不检查_version是否与请求中指定的一致,而是检查是否小于指定的版本。若是请求成功,外部版本号就会被存储到_version中。
例如,建立一个包含外部版本号为5的新的文档,咱们能够这样作: curl -XPOST '/testindex/fulltext/1?version=5&version_type=external' -d'{"title":"external log","content":"hello es"}'
查询返回的结果为:
{ "_index": "testindex", "_type": "fulltext", "_id": "1", "_version": 5, "found": true, "_source": { "title": "external log", "content": "hello es" } }
如今咱们更新文档将文档的版本号指定为8:
{ "_index": "testindex", "_type": "fulltext", "_id": "1", "_version": 8, "found": true, "_source": { "title": "external log second operate", "content": "hello es" } }
版本号已经变动为"_version": 8,从新执行请求,返回的异常一样为版本冲突错误。
总结:在实际开发中根据不一样的业务场景使用不一样的版本控制,这个仍是须要业务场景具体选择。