标签: optimistic-locking

乐观与悲观锁定

我理解乐观和悲观锁定*之间的区别.现在有人可以向我解释我何时会使用其中任何一个?

这个问题的答案是否会根据我是否使用存储过程来执行查询而改变?

*但只是为了检查,乐观的意思是"在阅读时不要锁定桌子",悲观意味着"在阅读时锁定桌面".

sql-server locking optimistic-locking pessimistic-locking

510
推荐指数
12
解决办法
29万
查看次数

通过具体(Java)示例进行乐观锁定

我早上花了很多时间阅读谷歌在乐观锁定方面所做的所有热门文章,而对于我的生活,我仍然没有真正理解.

理解乐观锁定涉及添加用于跟踪记录的"版本"的列,并且该列可以是时间戳,计数器或任何其他版本跟踪构造.但我仍然不明白如何确保WRITE完整性(意味着如果多个进程同时更新同一个实体,那么之后,实体正确地反映了它应该处于的真实状态).

有人可以提供一个具体的,易于理解的例子,说明如何在Java中使用乐观锁定(可能是MySQL数据库).假设我们有一个Person实体:

public class Person {
    private String firstName;
    private String lastName;
    private int age;
    private Color favoriteColor;
}
Run Code Online (Sandbox Code Playgroud)

并且这些Person实例会持久化到peopleMySQL表:

CREATE TABLE people (
    person_id PRIMARY KEY AUTO_INCREMENT,
    first_name VARCHAR(100) NOT NULL,
    last_name VARCHAR(100) NOT NULL,        # } I realize these column defs are not valid but this is just pseudo-code
    age INT NOT NULL,
    color_id FOREIGN KEY (colors) NOT NULL  # Say we also have a …
Run Code Online (Sandbox Code Playgroud)

java concurrency locking optimistic-locking

29
推荐指数
1
解决办法
2万
查看次数

分布式事务和/或群集中共享数据的Java解决方案

集群/分发Java服务器应用程序的最佳方法是什么?我正在寻找一种方法,允许您通过添加更多应用程序服务器和更多数据库服务器来水平扩展.

  • 您会建议采用哪些技术(软件工程技术或特定技术)来解决此类问题?
  • 您使用什么技术设计持久层以扩展到许多读取器/写入器扩展应用程序事务并扩展对共享数据的访问(最佳方法是消除共享数据;您可以应用哪些技术来消除共享数据).
  • 似乎需要使用不同的方法,具体取决于您的事务是读取还是写入繁重,但我觉得如果您可以优化"写入"繁重的应用程序,这对于"读取"也是有效的

"最佳"解决方案允许您为单个节点编写Java应用程序,并希望"隐藏"访问/锁定共享数据的大部分细节.

在分布式环境中,最困难的问题总是归结为多个事务访问共享数据.似乎有两种常见的并发事务方法.

  1. 显式锁(在分布式系统中的多个节点之间极易出错并且协调速度很慢)
  2. 软件事务内存(STM)AKA乐观并发,如果事务发现共享状态已更改(并且稍后可以重试事务),则在提交期间回滚事务.哪种方法可以更好地扩展,在分布式系统中有哪些权衡取舍?

我一直在研究扩展解决方案(以及提供如何扩展的示例的一般应用程序),例如:

  1. Terracotta - 通过使用Java的并发锁定机制(synchronized,ReentrantReadWriteLocks)扩展Java内存模型以包含分布式共享内存,提供"透明"扩展.
  2. 谷歌应用程序引擎的Java -让您可以在您分发哪个服务器处理事务写,将当中的"云"服务器进行分布式Java(或Python)的应用程序和使用BigTable的存储持久性数据(不知道你的交易是如何访问共享数据或处理锁定争用,以便能够有效扩展)
  3. 暗星MMO服务器 -暗星是Sun的开源MMO(大型多人在线),他们规模在一个线程事务的方式交易,允许一个给定的事务,只进行了一定的运行,并承诺,如果它需要长期将回滚游戏服务器(有点像软件事务内存).他们一直在研究支持多节点服务器设置以进行扩展.
  4. Hibernate的乐观锁定 - 如果你使用的是Hibernate,你可以使用它们的乐观并发支持来支持软件事务内存类型的行为
  5. Apache CouchDB应该自然地以网状配置"扩展"到许多读写器DB.(有一个很好的例子,说明如何管理锁定数据或确保事务隔离?):
  6. JCache - 通过将结果缓存到可以在Google appengine中使用的常见查询来扩展"读取"繁重的应用程序,以访问memcached并缓存其他经常读取的数据.

Terracotta似乎是最完整的解决方案,因为您可以"轻松"修改现有服务器应用程序以支持扩展(在定义@Root对象和@AutoLockRead/Write方法之后).问题是要真正从分布式应用程序中获得最大的性能,分布式系统的优化实际上并不是一个想法,你必须设计它,知道对象访问可能被网络I/O阻止.

为了正确扩展,似乎总是归结为分区数据和负载平衡事务,例如给定的"执行单元"(cpu core - > thread - >分布式应用程序节点 - > DB主节点)

似乎通过群集使任何应用程序可以正确扩展,您需要能够根据数据访问读/写对事务进行分区.人们提出了哪些解决方案来分发他们的应用程序数据(Oracle,Google BigTable,MySQL,数据仓库),以及一般如何管理分区数据(许多写入主数据库,以及更多读取数据库等).

在扩展数据持久层方面,在将数据划分给许多读者/多个编写者方面,哪种类型的配置最佳扩展(通常我会基于给定用户(或通常是您的任何核心实体)对数据进行分区"root"对象实体)由单个主DB拥有

java concurrency scalability transactions optimistic-locking

21
推荐指数
1
解决办法
5919
查看次数

如何在Rails应用程序中避免竞争条件?

我有一个非常简单的Rails应用程序,允许用户在一组课程中注册他们的出勤.ActiveRecord模型如下:

class Course < ActiveRecord::Base
  has_many :scheduled_runs
  ...
end

class ScheduledRun < ActiveRecord::Base
  belongs_to :course
  has_many :attendances
  has_many :attendees, :through => :attendances
  ...
end

class Attendance < ActiveRecord::Base
  belongs_to :user
  belongs_to :scheduled_run, :counter_cache => true
  ...
end

class User < ActiveRecord::Base
  has_many :attendances
  has_many :registered_courses, :through => :attendances, :source => :scheduled_run
end
Run Code Online (Sandbox Code Playgroud)

ScheduledRun实例具有有限数量的可用位置,一旦达到限制,就不能再接受更多的考勤.

def full?
  attendances_count == capacity
end
Run Code Online (Sandbox Code Playgroud)

attendances_count是一个计数器缓存列,包含为特定ScheduledRun记录创建的出勤关联数.

我的问题是,当一个或多个人同时尝试在课程中注册最后一个可用位置时,我不完全知道确保不会发生竞争条件的正确方法.

我的考勤控制器如下所示:

class AttendancesController < ApplicationController
  before_filter :load_scheduled_run
  before_filter :load_user, :only => :create

  def new
    @user = User.new
  end

  def …
Run Code Online (Sandbox Code Playgroud)

database activerecord ruby-on-rails optimistic-locking

20
推荐指数
1
解决办法
7617
查看次数

使用JPA / Hibernate在无状态应用程序中进行乐观锁定

我想知道在无法在请求之间保留具有特定版本的实体实例的系统中,实现乐观锁定(乐观并发控制)的最佳方法是什么。这实际上是一个非常常见的场景,但是几乎所有示例都基于在请求之间(在http会话中)保存已加载实体的应用程序。

如何在尽可能少的API污染的情况下实现乐观锁定?

约束条件

  • 该系统是根据域驱动设计原则开发的。
  • 客户端/服务器系统
  • 无法在请求之间保留实体实例(出于可用性和可伸缩性的原因)。
  • 技术细节应尽可能少污染域的API。

栈是带有JPA(休眠)的Spring,如果这有任何关系的话。

@Version仅使用时出现问题

在许多文档中,您似乎所需要做的就是用装饰一个字段,@Version并且JPA / Hibernate将自动检查版本。但是,只有将加载的对象及其当前版本保存在内存中,直到更新更改了同一实例,这才起作用。

@Version在无状态应用程序中使用时会发生什么:

  1. 客户端A使用加载项目id = 1并获取Item(id = 1, version = 1, name = "a")
  2. 客户B加载项目id = 1并获取Item(id = 1, version = 1, name = "a")
  3. 客户端A修改项目并将其发送回服务器: Item(id = 1, version = 1, name = "b")
  4. 服务器加载EntityManager返回的项目Item(id = 1, version = 1, name = "a"),它更改name和持久化Item(id = 1, version = 1, name = "b")。Hibernate将版本增加到 …

java hibernate jpa optimistic-locking optimistic-concurrency

20
推荐指数
1
解决办法
524
查看次数

Spring乐观锁定:如何重试事务方法直到提交成功

我使用Spring 2.5和Hibernate JPA实现Java和"容器"管理事务.

我有一个"用户提交后"方法,它在后台更新数据,无论是异常ConcurrencyFailureException还是StaleObjectStateException异常都需要提交,因为它永远不会显示给客户端.换句话说,需要将乐观锁定变为悲观.(如果方法执行需要更长的时间并且有人在其他事务中更改了数据,则可能发生)


我读了很多关于幂等的东西,如果异常搜索DEFAULT_MAX_RETRIES6.2.7则重试.示例第14.5章.重试.我也在这里这里找到了stackoverflow .

我试过这个:

public aspect RetryOnConcurrencyExceptionAspect {

    private static final int DEFAULT_MAX_RETRIES = 20;
    private int maxRetries = DEFAULT_MAX_RETRIES;

    Object around(): execution( * * (..) ) && @annotation(RetryOnConcurrencyException) && @annotation(Transactional) {

        int numAttempts = 0;
          RuntimeException failureException = null;
          do {
                numAttempts++;
                try {
                    return proceed(); 
                } 
                catch( OptimisticLockingFailureException ex ) {
                    failureException = ex;
                }
                catch(ConcurrencyFailureException ex) { …
Run Code Online (Sandbox Code Playgroud)

java spring transactions aspectj optimistic-locking

19
推荐指数
2
解决办法
1万
查看次数

由于乐观锁定失败,用于拒绝PUT的HTTP状态代码

假设我想实现某种乐观锁定并使用ETag来指示最新的资源状态.这意味着,客户端在进行更新If-Match时将使用标头PUT.

根据HTTP规范,412 Precondition failed如果为If-Match标头提供的ETag 与资源的当前状态不匹配,则服务器必须返回.

然而,409 Conflict似乎更接近我想要在语义上表达的内容,特别是因为它给出了在响应中包含的指南.

409如果未能匹配If-Match标题中提供的ETag,那么返回是否非常错误?

rest http optimistic-locking web

18
推荐指数
1
解决办法
7015
查看次数

锁定机制(悲观/乐观)与数据库事务隔离级别有何关系?

我正在编写一个Web应用程序,例如,两个不同的用户可以更新列表中的事情列表.我已经意识到,乐观锁定机制最有效,因为我不期望高争用.

我在看事务隔离级别,现在我有点困惑.看起来不同的事务隔离级别也解决了类似的问题.

这两个不同的概念如何相互关联?如果可能,举个简单的例子.

database concurrency optimistic-locking isolation-level pessimistic-locking

18
推荐指数
1
解决办法
3888
查看次数

MongoDB文档操作是原子的和隔离的,但它们是否一致?

我正在将我的应用程序从App Engine数据存储区移植到MongoDB后端,并对"文档更新"的一致性提出疑问.我知道一个文档的更新都是原子的和隔离的,但有没有办法保证它们在不同的副本集中"一致"?

在我们的应用程序中,许多用户可以(并且将会)在一次更新期间通过向其中插入一些嵌入文档(对象)来同时尝试更新一个文档.我们必须确保这些更新发生在所有副本逻辑一致的方式,即当一个用户"把"几嵌入文档到主文件,其他用户可以把自己嵌入文档的父文档中,直到我们确保他们已经阅读并收到第一个用户的更新.

所以我的意思是一致的是,我们需要一种方法来确保如果两个用户试图在一个文档进行更新恰好在同一时间,MongoDB中只允许这些更新要经过的一个,并丢弃另一个(或至少可以防止两者发生.我们不能在这里使用标准的"分片"解决方案,因为单个更新不仅仅包含增量或减量.

保证一个特定文档一致性的最佳方法是什么?

concurrency consistency optimistic-locking mongodb

17
推荐指数
2
解决办法
6249
查看次数

默认情况下,在Hibernate中乐观锁定

我有一个关于Hibernate中乐观锁定的问题.我试图深入了解Hibernate的乐观锁定,但我有一个疑问.Hibernate使用版本方法(整数或时间戳)来实现乐观锁定.要配置,您可以使用@Version注释(或xml配置)并创建版本属性.另一个选项是使用optimistic-lock ="all"属性进行配置而不进行版本控制.

我的问题是你没有定义任何版本控制属性,也没有指定一个乐观锁属性,在这种情况下哪个策略使用Hibernate?Pessimistc Locking我很确定不行,所以我认为这是乐观锁定但不知道如何.

非常感谢您的关注.

hibernate optimistic-locking

13
推荐指数
1
解决办法
2万
查看次数