IQ Framework

IQ-Twemcached provides strong consistency by differentiating between a read and a write session. A read session uses IQget and IQset (instead of get and set). Depending how a write session performs its KVS update, it uses different commands:

  • Invalidate: A write session uses QaReg prior to its RDBMS transaction commit to invalidate a key. Once its transaction commits, it issues DaR to delete its impacted key-value pairs and release its Q leases.
  • Refresh: A write session implements R-M-W using QaRead-M-SaR. QaRead retrieves the value of its referenced key and obtains a Q lease on it. This must be performed either prior or during its RDBMS transaction. Note that QaRead may cause the calling session to abort and restart. Once its RDBMS transaction commits then it must issue a SaR to place its changes into effect and release its Q leases.
  • Incremental update: Write sessions use an IQ version of the existing commands, namely, IQAppend/IQPrepend/IQIncr/IQDecr. A session ends explicity by issuing either Commit or Abort.

Tables 1, 2, and 3 show the behavior of these new commands with alternative cache states with invalidate and refresh, respectively. Their rows correspond to the new commands. Their columns correspond to the state of the key referenced by the commands. Note that a key without a value may have a lease on it, e.g., a read session has observed a miss for the key and has been granted an I lease to populate the cache. The leases shown in the last two columns are assumed to belong to a session different than the one issuing the command (When a session repeats IQ commands that request an I or Q lease repeatedly, the IQ-Twemcached server allows the session to proceed forward if its existing lease is compatible with its command and upgrades an existing lease should the command require a stronger lease).

Key-value state
No value, no lease Has value, no lease I lease Q lease
Cmd
IQGet Miss, grant I lease Return value Back-off Two possible cases:
1. No value, back off
2. Has value, return value
IQSet IQ-Twemcached server ignores
the value and returns NOT_STORED
Two possible cases:
1. Valid lease, update/insert value
2. Invalid lease, ignore value
IQ-Twemcached server ignores
the value and returns NOT_STORED
QaReg Grant Q lease Grant Q lease Grant Q lease Grant Q lease
DaR Ignore delete Ignore delete Ignore delete Two possible cases:
1. Valid lease, delete value
2. Invalid lease, ignore delete
Table 1. Invalidation State Table

Key-value state
No value, no lease Has value, no lease I lease Q lease
Cmd
IQGet Miss, grant I lease Return value Back-off Two possible cases:
1. No value, back off
2. Has value, return value
IQSet IQ-Twemcached server ignores
the value and returns NOT_STORED
Two possible cases:
1. Valid lease, update/insert value
2. Invalid lease, ignore the value
IQ-Twemcached server ignores
the value and returns NOT_STORED
QaRead Grant Q lease Grant Q lease Grant Q lease IQ-Twemcached server returns
a special error code that causes
the IQ-Whalin client to raise an
exception. The session may either
(a) abort and return or (b) abort and retry
SaR IQ-Twemcached server ignores the value and returns NOT_STORED Two possible cases:
1. Valid lease, swap value
2. Invalid lease, ignore update value
Table 2. Refresh State Table

The truth table with Incremental Update is similar to that with Refresh with the following two differences:

  1. Replace QaRead with an incremental update action such as IQappend, IQincrement, etc., and
  2. Replace SaR with Commit.

More details about the implementation of these commands in IQ-Twemcached can be found here.

Document about race conditions that cause stale data and how IQ-Twemcached prevents them can be found here.

IQ-Whalin Client

This is a Java client-side software that supports developers write applications that communicate with the cache server. It provides API to support both the Invalidation and Refresh techniques.

Here is the link to the full documentation of this Java library.

Samples

The following sample shows how to use the IQ-Whalin Client to connect and issue requests to cache servers. Firstly, with both Invalidation and Refresh techniques, MemcachedClient object is created with a list of cache servers provided, each with ip address and port number:

                                            // specify a list of cache server
                                            String[] serverList = {
                                                "10.0.0.210:11211",
                                                "10.0.0.215:11211",
                                                "10.0.0.220:10001"
                                            }

                                            // create socket pool with a name
                                            SocketIOPool pool = SocketIOPool.getInstance("test");
                                            pool.setServers(serverList);

                                            // set other properties
                                            // ...

                                            pool.initialize();

                                            // initialize a new MemcachedClient object
                                            MemcachedClient mc = new MemcachedClient("test");
                                        

A read session on key key1 based on Invalidation technique is executed as follows.

                                            // request the cache for value
                                            Object value = mc.iqget(key1);

                                            if (value == null) {
                                                // query DBMS to compute value
                                                // ...

                                                // assume the value is computed
                                                // set new value to the cache
                                                mc.iqset(key1, value);
                                            } 

                                            return value;
                                        

In a write session, developers should know in advance what keys are affected by updating to the DBMS so that it will request leases for those items before performing updates to the DBMS, and release them when the updates to the DBMS success.
The code below is for Invalidation technique

                                            /* for example, in this case key1 is affected by an update to the DBMS */

                                            // generate a unique id for this session
                                            String sessId = UUID.randomUUID().toString();

                                            // request Q lease for key1
                                            boolean hasLease = mc.quarantineAndRegister(sessId, key1);

                                            if (hasLease) {
                                                // performing updates to DBMS
                                                // ...

                                                mc.deleteAndRelease(sessId);
                                            }
                                        
With Refresh technique, it is done by
                                            
                                            try {
                                                // request Q lease
                                                Object oldValue = mc.quarantineAndRead(key1);

                                                // performing updates to DBMS
                                                // ...
                                                Object newValue = updateChanges(oldValue);

                                                // update value in the cache
                                                mc.swapAndRelease(key1, newValue);
                                            } catch (IQException e) {
                                                // handle when mc fails to return lease
                                                // ...
                                            }
                                        

In the IQ-Whalin Client source code, we provide a list of examples for testing that cover all usages of the IQ-Whalin Client. Specific samples that use IQ-Whalin Client in BG benchmark are also included in the download page.