es version并发版本控制

悲观锁(Pressimistic Locking)

加锁悲观策略:
并发控制而言,锁是一种悲观策略,会阻塞线程执行,本质上是将并发转变为串行来实现的,势必会影响吞吐量。并且线程的数量是有限的,依赖于操做系统,并且线程的建立和销毁带来的性能损耗是不能够忽略掉的。虽然如今基本都是用线程池来尽量的下降不断建立线程带来的性能损耗。html

对数据被外界(包括本系统当前的其余事务,以及来自外部系统的事务处理)修改持保守态度,所以,在整个数据处理过程当中,将数据处于锁定状态。悲观锁的实现,每每依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,不然,即便在本系统中实现了加锁机制,也没法保证外部系统不会修改数据)。例如: select * from table_name where id = "xxx" for update
这样查询出来的这一行数据就被锁定了,在这个update事务提交以前其余外界是不能修改这条数据的,可是这种处理方式效率比较低,通常不推荐使用。算法

 

乐观锁(Optimistic Locking)

无锁乐观策略:
它会假设对资源的访问时没有冲突的,既然没有冲突就不须要等待,线程不须要阻塞。那多个线程共同访问临界区的资源时,无锁的策略采用一种比较交换技术CAS(compare and swap)来鉴别线程冲突,一旦检测到冲突,就会重试当前操做指导没有冲突为止。数据库

相对悲观锁而言,乐观锁机制采起了更加宽松的加锁机制。悲观锁大多数状况下依靠数据库的锁机制实现,以保证操做最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销每每没法承受。如一个金融系统,当某个操做员读取用户的数据,并在读出的用户数据的基础上进行修改时(如更改用户账户余额),若是采用悲观锁机制,也就意味着整个操做过程当中(从操做员读出数据、开始修改直至提交修改结果的全过程,甚至还包括操做员中途去煮咖啡的时间),数据库记录始终处于加锁状态,能够想见,若是面对几百上千个并发,这样的状况将致使怎样的后果。 
乐观锁机制在必定程度上解决了这个问题。乐观锁,大可能是基于数据版本( Version )记录机制实现。何谓数据版本?即为数据增长一个版本标识,在基于数据库表的版本解决方案中,通常是经过为数据库表增长一个 “version” 字段来实现。读取出数据时,将此版本号一同读出,以后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,若是提交的数据版本号大于数据库表当前版本号,则予以更新,不然认为是过时数据。json

乐观锁的实现:并发

update account set field1 = ? and field2 = ? and version = version + 1 where version = ?app

 

 

对比:


与锁相比,CAS会使得程序设计比较负责,可是因为其优越的性能优点,以及天生免疫死锁(根本就没有锁,固然就不会有线程一直阻塞了),更为重要的是,使用无锁的方式没有所竞争带来的开销,也没有线程间频繁调度带来的开销,他比基于锁的方式有更优越的性能,因此在目前被普遍应用,咱们在程序设计时也能够适当的使用.框架

 

经验总结:


不过因为CAS编码确实稍微复杂,并且jdk做者自己也不但愿你直接使用unsafe(后面会讲到)来进行代码的编写,因此若是不能深入理解CAS以及unsafe仍是要慎用,使用一些别人已经实现好的无锁类或者框架就行了。curl

 

CAS算法:


一个CAS方法包含三个参数CAS(V,E,N)。V表示要更新的变量,E表示预期的值,N表示新值。只有当V的值等于E时,才会将V的值修改成N。若是V的值不等于E,说明已经被其余线程修改了,当前线程能够放弃此操做,也能够再次尝试次操做直至修改为功。基于这样的算法,CAS操做即便没有锁,也能够发现其余线程对当前线程的干扰(临界区值的修改),并进行恰当的处理。elasticsearch

 

es

_version : 第一次建立一个document的时候,_version内部的版本号就是1,之后的每个修改(包括删除)都会加1ide


curl -XPUT 'localhost:9200/blog/post/8?pretty' -H 'Content-Type: application/json' -d'
 {
   "title": "My BBB first blog entry"
 }'

{
  "_index" : "blog",
  "_type" : "post",
  "_id" : "8",
  "_version" : 1,
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "created" : true
}


update操做:下面至关于全量替换,
这个时候_version = _version+1
curl -XPUT 'localhost:9200/blog/post/8?pretty' -H 'Content-Type: application/json' -d'
 {
   "title": "My BBB first blog entry"
 }'

{
  "_index" : "blog",
  "_type" : "post",
  "_id" : "8",
  "_version" : 2,
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "created" : false
}

删除后_version = _version+1
curl -XDELETE 'localhost:9200/blog/post/8?pretty' -H 'Content-Type: application/json'
{
  "found" : true,
  "_index" : "blog",
  "_type" : "post",
  "_id" : "8",
  "_version" : 3,
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  }
}

curl -XPUT 'localhost:9200/blog/post/8?pretty' -H 'Content-Type: application/json' -d'
 {
   "title": "My first blog entry add again"
 }'

这时候的delete不是立马物理删除

 

 

版本控制携带version参数

官网说的很详细:

https://www.elastic.co/guide/cn/elasticsearch/guide/current/optimistic-concurrency-control.html

curl -XGET 'localhost:9200/blog/post/8?pretty&version=4' {   "_index" : "blog",   "_type" : "post",   "_id" : "8",   "_version" : 4,   "found" : true,   "_source" : {     "title" : "My first blog entry add again"   } }

相关文章
相关标签/搜索