ElasticSearch是多用户操作的 ,需要保证数据的一致性,它用乐观锁保证数据的一致性,用户每次操作一次文档,它的版本号就会自动加1,用户对文档操作时,不需要对文档加锁、解锁,只需要指定要操作的版本。当版本号一致时,ElasticSearch会允许该操作顺利执行,而当版本号存在冲突时,ElasticSearch会提示冲突并抛出异常。ElasticSearch的版本号的取值范围是1到2^63-1。
1、内部版本控制
使用的是_version,下面是个简单例子:
POST /lib/books/_bulk {"index":{"_id":1}} {"title":"Html5","price":45}
显示版本号是3,"_version": 3,结果如下:
{ "took": 19, "errors": false, "items": [ { "index": { "_index": "lib", "_type": "books", "_id": "1", "_version": 3, "result": "updated", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 7, "_primary_term": 1, "status": 200 } } ] }
现在将价格修改为50,执行下面的语句,从结果中看到"_version":4,版本号增加了1,
PUT /lib/books/1?version=3 { "title":"Html5", "price":50 }
{ "_index": "lib", "_type": "books", "_id": "1", "_version": 4, "result": "updated", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 8, "_primary_term": 1 }
现在版本号是4,如果执行版本号为5的操作,会报冲突,如下所示:
PUT /lib/books/1?version=5 { "title":"Html5", "price":50 }
{ "error": { "root_cause": [ { "type": "version_conflict_engine_exception", "reason": "[books][1]: version conflict, current version [4] is different than the one provided [5]", "index_uuid": "yL8koqQqQVqf3uoyvTcBHA", "shard": "3", "index": "lib" } ], "type": "version_conflict_engine_exception", "reason": "[books][1]: version conflict, current version [4] is different than the one provided [5]", "index_uuid": "yL8koqQqQVqf3uoyvTcBHA", "shard": "3", "index": "lib" }, "status": 409 }
2、外部版本控制
所谓外部版本号指的是ElasticSearch与关系型数据库一块使用时,关系型数据实现锁机制中的版本号。ElasticSearch在处理外部版本号时与对内部版本号的处理有些不同。它不再检查_version是否与请求中指定的数值相同,而是检查当前的_version是否比指定的数值小。如果请求成功,那么外部的版本号就会被存储到文档中的_version中。为了保持_version与外部版本控制的数据一致,使用version_type=external。
参考下面的例子,现在版本号是4,执行为版本号为5的操作,可以成功,版本号变为5
PUT /lib/books/1?version=5&version_type=external { "title":"Html5", "price":50 }
{ "_index": "lib", "_type": "books", "_id": "1", "_version": 5, "result": "updated", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 9, "_primary_term": 1 }
现在版本号是5,执行版本号是5的操作会报冲突,执行的只能大于当前的。如下:
PUT /lib/books/1?version=5&version_type=external { "title":"Html5", "price":50 }
{ "error": { "root_cause": [ { "type": "version_conflict_engine_exception", "reason": "[books][1]: version conflict, current version [5] is higher or equal to the one provided [5]", "index_uuid": "yL8koqQqQVqf3uoyvTcBHA", "shard": "3", "index": "lib" } ], "type": "version_conflict_engine_exception", "reason": "[books][1]: version conflict, current version [5] is higher or equal to the one provided [5]", "index_uuid": "yL8koqQqQVqf3uoyvTcBHA", "shard": "3", "index": "lib" }, "status": 409 }
现在版本号是5,执行一次版本号是12的,执行完后,版本号变为了12,如下:
PUT /lib/books/1?version=12&version_type=external { "title":"Html5", "price":50 }
{ "_index": "lib", "_type": "books", "_id": "1", "_version": 12, "result": "updated", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 10, "_primary_term": 1 }