Senior
There is a microservice for deducting funds from a user's balance. When replicating the service, a race condition problem occurs. How to solve this problem?
sobes.tech AI
Answer from AI
Race condition issues during fund deduction in a microservice with replication occur due to simultaneous access by multiple instances to the same data. To resolve this, the following approaches can be used:
- Optimistic Locking: store a record version or timestamp, and check that it hasn't changed during update. If it has changed, retry the operation.
- Database transactions and locks: use transactions with row locking (e.g.,
SELECT ... FOR UPDATE) to ensure sequential access. - Distributed locks: for example, via Redis with Redlock or Zookeeper, so that only one service can deduct funds at a time.
- Idempotent operations and queues: process deductions through message queues to ensure sequence and avoid parallel modifications.
Example with optimistic locking in Go (pseudo-code):
func DeductBalance(userID string, amount float64) error {
for i := 0; i < maxRetries; i++ {
user, err := db.GetUser(userID)
if err != nil {
return err
}
if user.Balance < amount {
return errors.New("insufficient funds")
}
newBalance := user.Balance - amount
// Update with version check
updated, err := db.UpdateBalanceIfVersionMatches(userID, newBalance, user.Version)
if err != nil {
return err
}
if updated {
return nil // success
}
// Otherwise, version changed, retry
}
return errors.New("failed to deduct funds due to conflict")
}