_version元数据:第一次创建一个document的时候,它的_version内部版本号就是1;以后每次对这个document执行修改或者删除的时候,都会对这个_version版本号自动加1,哪怕是删除操作,也会对这条数据的版本号加1.
创建一个document:
PUT test_index/test_type/1
{
"test_field":"test1"
}
运行结果:
{
"_index": "test_index",
"_type": "test_type",
"_id": "1",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 16,
"_primary_term": 1
}
测试删除:
DELETE test_index/test_type/1
运行结果:
{
"_index": "test_index",
"_type": "test_type",
"_id": "1",
"_version": 2,
"result": "deleted",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 17,
"_primary_term": 1
}
测试修改:
PUT test_index/test_type/1
{
"test_field":"test123"
}
运行结果
{
"_index": "test_index",
"_type": "test_type",
"_id": "1",
"_version": 3,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 18,
"_primary_term": 1
}
我们发现,在删除一个document之后,可以一个从一个侧面证明,它不是立刻物流删除的,因为它的版本号等信息还是保留着的,先删除一条document,再重新创建document,其实会在delete version基础之上,再把version加1
首先我们创建一条document field=test1,现在有2个线程,线程A先修改数据,把field修改成test2,线程B后修改,将数据修改成test3,这两条线程现在的version都是1,但是A线程虽然是先操作的,但是并不一定先对数据就行修改,因为在es后台shard同步replica是基于多线程异步请求的,也就是说,多个线程修改请求都是乱序的,没有顺序的,所以可能会出现B线程先到,A线程反而后到。
(1)第一种情况:如果B线程(后修改的)先到,携带的版本号是1,对数据进行修改时,把field修改成test3,此时version版本变成2,而这个时候A线程(先修改的)也到了,此时携带的版本号还是1,对数据就行修改时,此时就会比较version版本号,如果相等,就可以正常修改成功。如果version版本不同,说明版本已经被其他人修改过了,然而发现线程A就先就行修改的,这个时候说明这个数据是旧数据了,es就会把这条数据扔掉。此时最终结果就是一个正确的状态,field=test3。
(2)第二种情况:如果A线程(先修改的)先到了,携带的版本号是1,对数据进行修改,此时执行写操作的时候,会判断当前的版本号跟es的版本号,此时es的版本号1,显然版本号一样,写操作成功,此时field被修改成test2,此时es的版本号变成2,而这个时候线程B到了,携带的版本号还是1,对数据进行修改,同样先判定版本号,发现版本号不同,说明这条数据已经被人修改过了,此时,会重新读取es的数据版本,此时B线程也变成2,再次执行上述操作,发现版本号一样,执行写操作,此时最终结果就是一个正确的状态,数据修改成test3
总体而言:es不会让旧的数据覆盖新数据