Skip to content

Distributed Row Lock

elandau edited this page May 22, 2012 · 1 revision

The distributed row lock performs a sequence of Write-Read-Write operations to effectively lock a row. The recipe also allows for reading the entire row (the read) and committing it back as part of the release mutation (the last write).


ColumnPrefixDistributedRowLock<String> lock = 
    new ColumnPrefixDistributedRowLock<String>(keyspace, LOCK_CF, "RowKeyToLock")
                .expireLockAfter(1, TimeUnit.SECONDS);
        
try {
    lock.acquire();
}
catch (StaleLockException e) {
    // The row contains a stale or abandoned lock
    // These can either be manually clean up or automatically
    // cleaned up (and ignored) by calling failOnStaleLock(false)
}
catch (BusyLockException e) {
    // The row is currently locked.  
}
finally {
    lock.release();
}

Read modify write


// Take a lock
ColumnPrefixDistributedRowLock<String> lock = 
    new ColumnPrefixDistributedRowLock<String>(keyspace, SOME_CF, "MyRowKey")
        .expireLockAfter(1, TimeUnit.SECONDS);
        
try {
    // Take the lock while reading ALL the columns in the row
    ColumnMap<String> columns = lock.acquireLockAndReadRow();
            
    // Modify a value and add it to a batch mutation
    int value = columns.get("SomeDataColumn").getIntegerValue() + 1;
    MutationBatch m = keyspace.prepareMutationBatch();
    m.withRow(LOCK_CF, rowKey)
        .putColumn("SomeDataColumn", value, null);
            
    // Write data AND release the lock
    lock.releaseWithMutation(m);
}
catch (Exception e) {
    lock.release();
}

Blocking lock

This variation of the recipe implements a backoff and retry mechanism for busy locks. The following example will use a bounded exponential backoff with time slices of 250 msec and maximum wait time of 10,000 msec with a maximum of 10 attempts. If the lock cannot be acquired a BusyLockException will be thrown.


ColumnPrefixDistributedRowLock<String> lock = 
    new ColumnPrefixDistributedRowLock<String>(keyspace, LOCK_CF, "RowKeyToLock")
        .withBackoff(new BoundedExponentialBackoff(250, 10000, 10))
        .expireLockAfter(1, TimeUnit.SECONDS);
        
try {
    lock.acquire();
}
catch (StaleLockException e) {
}
catch (BusyLockException e) {
}
finally {
    lock.release();
}