目录
1. CAS 命令简介
CAS(Check And Set)是 Memcached 提供的一种原子性操作,它允许客户端基于现有的值进行条件性更新。在使用 CAS 时,操作会首先验证当前值是否与给定的版本号(CAS 版本号)匹配,若匹配则更新,否则操作失败。这是确保在并发环境下数据一致性的一种方式。
CAS 常用于避免“丢失更新”(lost updates)的情况,在多线程环境下非常有效。
2. CAS 命令的语法
cas <key> <flags> <exptime> <bytes> <cas_unique> [noreply]
<data>
<key>
:要更新的键(必须已存在)。<flags>
:用户自定义标志(通常设为 0)。<exptime>
:过期时间(秒),0 代表永不过期。<bytes>
:数据大小(字节数)。<cas_unique>
:CAS 唯一版本号(由 Memcached 自动生成并返回)。[noreply]
(可选):如果指定,则服务器不会返回响应。<data>
:实际更新的数据(必须与<bytes>
指定的大小匹配)。
3. CAS 命令的参数说明
参数 | 说明 | 示例 |
---|---|---|
<key> | 需要更新的键 | counter |
<flags> | 自定义标志(通常为 0) | 0 |
<exptime> | 过期时间(无效,在 cas 中忽略) | 0 |
<bytes> | 数据大小(字节数) | 2 |
<cas_unique> | CAS 唯一版本号 | 1234567890 |
[noreply] | 可选,不返回响应 | noreply |
<data> | 更新的数据 | 10 |
4. 使用 Telnet 进行 CAS 操作
4.1 连接 Memcached
telnet 127.0.0.1 11211
4.2 先存储一个初始值(使用 set
)
set counter 0 0 1
5
4.3 获取当前的 CAS 唯一版本号
get counter
返回结果:
VALUE counter 0 1 1234567890
5
END
1234567890
是 CAS 唯一版本号。
4.4 使用 cas
更新数据
cas counter 0 0 1 1234567890
10
返回结果:
STORED
4.5 如果 CAS 唯一版本号不匹配(操作失败)
cas counter 0 0 1 9876543210
20
返回结果:
EXISTS
表示 CAS 唯一版本号不匹配,更新失败。
5. 不同编程语言的 CAS 示例
5.1 PHP cas
示例
<?php
$memcached = new Memcached();
$memcached->addServer("127.0.0.1", 11211);
// 先存储一个值
$memcached->set("counter", 5);
// 获取 CAS 唯一版本号
$cas_token = null;
$memcached->get("counter", null, $cas_token);
// 使用 CAS 更新数据
if ($memcached->cas($cas_token, "counter", 10)) {
echo "Value updated successfully";
} else {
echo "CAS failed";
}
// 获取数据
echo $memcached->get("counter");
?>
5.2 Python cas
示例
from pymemcache.client import base
client = base.Client(('127.0.0.1', 11211))
# 先存储一个值
client.set('counter', 5)
# 获取 CAS 唯一版本号
current_value, cas_token = client.gets('counter')
# 使用 CAS 更新数据
if client.cas('counter', 10, cas_token=cas_token):
print("Value updated successfully")
else:
print("CAS failed")
# 获取数据
print(client.get('counter').decode('utf-8'))
5.3 Java cas
示例
import net.spy.memcached.MemcachedClient;
import net.spy.memcached.CASResponse;
import java.io.IOException;
import java.net.InetSocketAddress;
public class MemcachedTest {
public static void main(String[] args) throws IOException {
MemcachedClient client = new MemcachedClient(new InetSocketAddress("127.0.0.1", 11211));
// 先存储一个值
client.set("counter", 0, 5);
// 获取 CAS 唯一版本号
CASResponse response = client.gets("counter");
Object casToken = response.getCAS();
// 使用 CAS 更新数据
boolean success = client.cas("counter", 0, 10, casToken);
if (success) {
System.out.println("Value updated successfully");
} else {
System.out.println("CAS failed");
}
// 获取数据
System.out.println(client.get("counter"));
client.shutdown();
}
}
5.4 Node.js cas
示例
const Memcached = require('memcached');
const memcached = new Memcached("127.0.0.1:11211");
// 先存储一个值
memcached.set("counter", 5, 0, function(err) {
if (err) console.error(err);
// 获取 CAS 唯一版本号
memcached.get("counter", function(err, data) {
const casToken = data.cas;
// 使用 CAS 更新数据
memcached.cas("counter", 10, casToken, function(err, result) {
if (err) {
console.error(err);
} else {
console.log(result ? "Value updated successfully" : "CAS failed");
}
});
// 获取数据
memcached.get("counter", function(err, data) {
if (err) console.error(err);
console.log(data);
});
});
});
发表回复