Memcached's CAS protocol
1. What is the CAS protocol
Many Chinese materials will not tell you what the full name of CAS is, but don't put it CAS is an acronym for the Chinese Academy of Sciences. Google.com, what is CAS? CAS is short for Check And Set.
2. The original text of the CAS protocol
http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt
3. The basic principle of CAS The
basic principle is very simple. In a word, it is the "version number" . Each stored data object has one more version number. We can understand from the following example:
if CAS is not used, there are the following scenarios: in the
first step, A takes out the data object X; in
the second step, B takes out the data object X; in
the third step, B modifies the data object X, and put it into the cache; in
the fourth step, A modifies the data object X and puts it into the cache.
We can find that data write conflicts will occur in the fourth step.
If the CAS protocol is adopted, the situation is as follows.
In the first step, A takes out data object X and obtains CAS-ID1; in
the second step, B takes out data object X and obtains CAS-ID2;
In the third step, B modifies the data object X, and checks whether the CAS-ID is consistent with the CAS-ID of the data in the cache space before writing to the cache. The result is "consistent", and the modified X with CAS-ID2 is written to the cache.
The fourth step, A modifies the data object Y, and checks whether the CAS-ID is consistent with the CAS-ID of the data in the cache space before writing to the cache. If the result is "inconsistent", the write is rejected and the storage failure is returned.
In this way, the CAS protocol uses the idea of "version number" to solve the conflict problem.
CAS program example of Memcached
1. Non-CAS
First look at an example of a Memcached program that is not CAS. For the problem prototype of the example, see the previous blog post.
Program example:
package com.sinosuperman.memcached; import java.io.IOException; import java.net.InetSocketAddress; import net.spy.memcached.MemcachedClient; public class Test { public static void main(String[] args) throws IOException { MemcachedClient cache = new MemcachedClient(new InetSocketAddress("127.0.0.1", 11211)); cache.set("x", 1800, "Love"); String obj1 = (String) cache.get("x"); String obj2 = (String) cache.get("x"); obj2 = "Michael"; cache.set("x", 1800, obj2); System.out.println("Non-CAS 2:\t" + obj2); System.out.println("Non-CAS 1:\t" + obj1); } }
operation result:
2011-12-18 23:12:39.836 INFO net.spy.memcached.MemcachedConnection: Added {QA sa=/127.0.0.1:11211, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue 2011-12-18 23:12:39.843 INFO net.spy.memcached.MemcachedConnection: Connection state changed for sun.nio.ch.SelectionKeyImpl@b09e89 Non-CAS 2: Michael Non-CAS 1: Love
It can be seen that when multiple clients operate, the problem of writing inconsistency will definitely occur.
2. CAS
program example:
package com.sinosuperman.memcached; import java.io.IOException; import java.net.InetSocketAddress; import net.spy.memcached.CASValue; import net.spy.memcached.MemcachedClient; public class Test { @SuppressWarnings("unchecked") public static void main(String[] args) throws IOException { MemcachedClient cache = new MemcachedClient(new InetSocketAddress("127.0.0.1", 11211)); cache.set("y", 1800, "Love"); CASValue casValue1 = cache.gets("y"); CASValue casValue2 = cache.gets("y"); cache.cas("y", casValue2.getCas(), casValue2.getValue()); System.out.println("CAS 2:\t" + casValue2.getCas()); System.out.println("Value 2:\t" + casValue2.getValue()); System.out.println("CAS 1:\t" + casValue1.getCas()); System.out.println("Value 1:\t" + casValue1.getValue()); } }
operation result:
2011-12-18 23:07:14.528 INFO net.spy.memcached.MemcachedConnection: Added {QA sa=/127.0.0.1:11211, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue 2011-12-18 23:07:14.541 INFO net.spy.memcached.MemcachedConnection: Connection state changed for sun.nio.ch.SelectionKeyImpl@1621e42 CASE 2: 11 Value 2: Love CASE 1:11 Value 1: Love