【问题标题】:Spring-data-aerospike | How to achieve transactional behaviour弹簧数据 aerospike |如何实现交易行为
【发布时间】:2020-10-24 21:58:43
【问题描述】:

用例:-

我们正在使用 Spring-data-aerospike 来获取和设置 aerospike 记录。 同时,我们有多个 Kafka 消费者正在尝试更新单个记录的不同字段。

问题:- 我们正面临着 Dirt-read 问题的挑战。记录正在被覆盖。

At t-0, Consumer-1 reads the Record-1, with intent to update the Field-name(mobileNumber). 
Record-1 looks like something :(custId:1, mobileNumber:1234567890, custType:PERMANENT)

At t-1, Consumer-2 reads the Record-1, with intent to update the Field-2(custType). 

At t-3, Consumer-2 commits the Record-1, with updated value for custType. 
Record-1 looks like something :(custId:1, mobileNumber:1234567890, custType:PERM_CHANGED_2)

At t-4, Consumer-1 commits the Record-1, with updated value for mobileNumber. 
Record-1 looks like something :(custId:1, mobileNumber:9988776655, custType:PERMANENNT)

这里的问题是:Consumer-2 更新的 'custType' 值在 t=4 时丢失了。

这里的代码-sn-p 看起来像:-


@Document(collection = "cust", expiration = 90, expirationUnit = TimeUnit.DAYS)
public class Customer {

   @Id
   @Field(value = "PK")
   private String custId;

   @Field(value = "mobileNumber")
   private String mobileNumber;

   @Field(value = "custType")
   private String custType;
 
}




@Repository
public interface CustomerRepository extends AerospikeRepository<Customer, String> {

  // Working.
  List<Customer> findById(String primaryKeyId);

}



@Autowired
AerospikeTemplate aerospikeTemplate;


@Transactional(isolation = Isloation.SERIALIZABLE, rollbackFor=Exception.class)
public ResponseDTO<String> updateCustomer(CustomerUpdateRequest custUpdateReqDTO) {
   Optional<Customer> cust = customerRepository.findById(custUpdateReqDTO.getCustId());
   // Update Business logic by consumers.
   aerospikeTemplate.update(cust);
}

这里的依赖看起来像:-

<dependency>
            <groupId>com.aerospike</groupId>
            <artifactId>aerospike-client</artifactId>
            <version>4.1.3</version>
        </dependency>

        <dependency>
            <groupId>com.aerospike</groupId>
            <artifactId>spring-data-aerospike</artifactId>
            <version>${aerospike.data.version}</version>
            <scope>system</scope>
            <systemPath>${basedir}/lib/spring-data-aerospike-2.0.0.RELEASE.jar</systemPath>
        </dependency>

        <dependency>
            <groupId>com.aerospike</groupId>
            <artifactId>aerospike-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.aerospike</groupId>
            <artifactId>aerospike-helper-java</artifactId>
            <version>1.2.2</version>
        </dependency>

问题:-

我们知道 Spring 事务与 RDBMS 一起工作!在这种情况下,让事务性属性在这里工作的方法是什么??

任何帮助或建议将不胜感激!

【问题讨论】:

  • 您需要为此使用乐观锁定,请阅读spring data/jpa optimistic locking。为此,您应该添加到您的文档类@Version private long version;。它会阻止并发更新,如果发生了,你会捕获OptimisticLockingFailureException并再次重试读取更新
  • 感谢您的回复。 @Version 的使用是否也适用于 aerospike 等 NoSql 数据库??
  • 是的,@Version 也适用于 spring-data-aerospike
  • 如果是spring-data-aerospike,则使用@Document 而不是@Entity@Version private long version; 开箱即用。
  • 仍然,如果没有乐观锁定,您将有竞争条件,不好的方法。奇怪的是,在您的情况下没有抛出异常,我之前使用过它并且效果很好。请做以下实验:手动设置版本= 5将文档保存在数据库中。然后尝试更新版本= 4的数据库中的相同记录。它不会抛出异常吗?

标签: spring-boot spring-data-jpa spring-transactions aerospike aerospike-ce


【解决方案1】:

我们使用aerospikeRepository.save 方法解决了这个问题。在这种情况下,如果超过 2 个消费者并行更新特定记录,它会向我们抛出 OptimisticLockingFailureException !!

虽然我们使用aerospikeTemplate.update 方法,但它不会抛出任何异常!

非常感谢您@VasylSarzhynskyi 的帮助。我们很高兴并非常感谢您的回复!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-03
    • 2020-11-11
    • 2021-08-14
    相关资源
    最近更新 更多