Use Case :-
We are using Spring-data-aerospike to get and set the aerospike record. At the same time we have multiple Kafka consumers who are trying to update the different fields of a single record.
Problem :- We are facing the challenge of Dirt-read problem. The records are getting overwritten.
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)
The problem here is : The updated value of 'custType' by Consumer-2 got lost at t=4.
Here is code-snippet looks like :-
@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);
}
Here is dependencies looks like :-
<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>
Questions :-
We are aware that spring transactional works with RDBMS !! Whats the way to get the transactional property working here in this scenario ??
Any help or suggestions shall be highly appreciated !
We solved it using the aerospikeRepository.save
method. In this case, its throwing us the OptimisticLockingFailureException, if a particular record is being updated by more than 2 consumers parallelly !!
While we use the aerospikeTemplate.update
method, it doesn't throws any exception !
Thank you very much for your assistance @VasylSarzhynskyi. We are glad and highly appreciate your response !