Distributed Row Lock

Sagar Loke edited this page Feb 14, 2014 · 3 revisions
Clone this wiki locally

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).

Currently Distributed Row Lock recipe works if the CF is created with “WITH COMPACT STORAGE” (Storage pre 1.2 format).


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();
}