- 环境准备:安装 Memcached 服务器和 Java 客户端库。
- Java 客户端选择:介绍最流行的客户端库
Xmemcached。 - 核心操作:连接、增删改查、过期时间等。
- 高级特性:CAS(Check-And-Set)、计数器、分布式锁等。
- 完整示例代码。
环境准备
1 安装 Memcached 服务器
如果你还没有 Memcached 服务器,可以按照以下步骤安装(以 Linux 为例):

# 1. 安装 Memcached sudo apt-get update sudo apt-get install memcached # 2. 启动 Memcached 服务 # -d: 以守护进程方式运行 # -m: 分配给 Memcached 的内存大小(MB),这里分配 512MB # -p: 监听的端口,默认是 11211 # -u: 运行 Memcached 的用户 sudo memcached -d -m 512 -p 11211 -u root
你的 Memcached 服务器已经在 0.0.1:11211 上运行了。
2 准备 Java 开发环境
确保你已经安装了 JDK 和 Maven(或 Gradle),我们将使用 Maven 来管理项目依赖。
Java 客户端选择
在 Java 生态中,有几个成熟的 Memcached 客户端库,其中最推荐的是 Xmemcached。
- Xmemcached:
- 优点:性能极高,基于 NIO,支持连接池,功能全面,社区活跃,是目前的主流选择。
- 维护者:来自中国的淘宝团队,对中文文档和社区支持较好。
- SpyMemcached:
- 优点:老牌客户端,非常稳定。
- 缺点:基于传统的阻塞 I/O,性能相比 Xmemcached 稍差。
我们选择 Xmemcached 进行后续讲解。

创建 Maven 项目并添加依赖
在你的 pom.xml 文件中添加 Xmemcached 的依赖:
<dependencies>
<!-- Xmemcached 客户端 -->
<dependency>
<groupId>com.googlecode.xmemcached</groupId>
<artifactId>xmemcached</artifactId>
<version>2.4.7</version> <!-- 建议使用最新版本 -->
</dependency>
<!-- 为了方便演示,添加一个日志实现 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.11</version>
</dependency>
</dependencies>
核心操作详解
1 建立连接
Xmemcached 使用 MemcachedClient 类作为客户端核心,最佳实践是使用 MemcachedClientBuilder 来构建客户端,因为它可以方便地配置连接池、超时等参数。
import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.MemcachedClientBuilder;
import net.rubyeye.xmemcached.XMemcachedClientBuilder;
import net.rubyeye.xmemcached.auth.AuthInfo;
import net.rubyeye.xmemcached.utils.AddrUtil;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.TimeoutException;
public class MemcachedConnection {
public static void main(String[] args) {
MemcachedClient memcachedClient = null;
try {
// 1. 创建 MemcachedClientBuilder
// AddrUtil.getAddresses("host1:port1 host2:port2 ...") 用于配置多个 Memcached 节点
MemcachedClientBuilder builder = new XMemcachedClientBuilder(
AddrUtil.getAddresses("127.0.0.1:11211")
);
// 2. 可选:设置连接池大小
builder.setConnectionPoolSize(10);
// 3. 可选:设置超时时间(毫秒)
builder.setOpTimeout(1000); // 操作超时
builder.setConnectTimeout(2000); // 连接超时
// 4. 构建并启动客户端
memcachedClient = builder.build();
// 5. 测试连接是否成功
System.out.println("连接成功!");
} catch (IOException e) {
System.err.println("创建 Memcached 客户端失败: " + e.getMessage());
} finally {
// 6. 关闭客户端,释放资源
if (memcachedClient != null) {
try {
memcachedClient.shutdown();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
2 基本 CRUD 操作
Xmemcached 的 API 设计得非常简洁,所有操作都是异步的,返回一个 Future 对象,但也可以通过 get() 方法同步等待结果。
// 假设 memcachedClient 已经成功创建
// 1. 设置值 (set)
// set(key, expiration, value)
// expiration: 过期时间,单位是秒,0 表示永不过期。
try {
memcachedClient.set("user:1001", 3600, "张三");
System.out.println("设置键 'user:1001' 成功");
} catch (Exception e) {
e.printStackTrace();
}
// 2. 获取值 (get)
try {
String value = memcachedClient.get("user:1001");
System.out.println("获取键 'user:1001' 的值: " + value);
} catch (Exception e) {
e.printStackTrace();
}
// 3. 添加值 (add)
// 只有当键不存在时才添加,如果键已存在则操作失败
try {
// 第一次添加成功
boolean added = memcachedClient.add("session:abc123", 1800, "user_data_123");
System.out.println("添加 'session:abc123' 是否成功: " + added);
// 第二次添加会失败,因为键已存在
added = memcachedClient.add("session:abc123", 1800, "new_data");
System.out.println("再次添加 'session:abc123' 是否成功: " + added);
} catch (Exception e) {
e.printStackTrace();
}
// 4. 替换值 (replace)
// 只有当键存在时才替换,如果键不存在则操作失败
try {
boolean replaced = memcachedClient.replace("user:1001", 3600, "李四");
System.out.println("替换 'user:1001' 是否成功: " + replaced);
} catch (Exception e) {
e.printStackTrace();
}
// 5. 删除值 (delete)
try {
memcachedClient.delete("user:1001");
System.out.println("删除键 'user:1001' 成功");
} catch (Exception e) {
e.printStackTrace();
}
// 再次获取,验证是否已删除
try {
String value = memcachedClient.get("user:1001");
System.out.println("删除后获取 'user:1001' 的值: " + value); // 输出 null
} catch (Exception e) {
e.printStackTrace();
}
高级特性
1 CAS (Check-And-Set) 乐观锁
CAS 是 Memcached 的重要特性,用于防止并发更新导致的数据覆盖问题,它通过一个唯一的 cas 值来实现。

流程:
gets(key)获取值和其对应的cas值。- 在客户端修改值。
cas(key, expiration, newValue, casValue)尝试用新值更新,只有当casValue与服务器端的当前cas值匹配时,更新才会成功。
try {
// 1. 初始化一个计数器
memcachedClient.set("counter:page_view", 0, 100L);
// 2. 获取初始值和 CAS 值
CASValue<Long> casValue = memcachedClient.gets("counter:page_view");
long currentValue = casValue.getValue();
long currentCas = casValue.getCas();
System.out.println("当前计数器值: " + currentValue + ", CAS: " + currentCas);
// 3. 模拟并发更新:增加 1
long newValue = currentValue + 1;
// 4. 尝试使用 CAS 更新
boolean casResult = memcachedClient.cas("counter:page_view", 0, newValue, currentCas);
System.out.println("CAS 更新是否成功: " + casResult);
if (casResult) {
System.out.println("更新成功!新值为: " + newValue);
} else {
System.out.println("更新失败!可能是其他线程先更新了。");
}
} catch (Exception e) {
e.printStackTrace();
}
2 计数器
Xmemcached 提供了原子性的 incr 和 decr 方法,非常适合实现计数器。
try {
// 1. 初始化一个计数器(如果不存在)
memcachedClient.set("counter:downloads", 0, 1000L);
// 2. 增加 5
long newCount = memcachedClient.incr("counter:downloads", 5);
System.out.println("增加 5 后,下载次数为: " + newCount);
// 3. 减少 2
newCount = memcachedClient.decr("counter:downloads", 2);
System.out.println("减少 2 后,下载次数为: " + newCount);
} catch (Exception e) {
e.printStackTrace();
}
3 分布式锁
虽然 Redis 是分布式锁的首选,但 Memcached 也可以通过 add 命令实现一个简单的分布式锁。
原理:add 命令在键不存在时才能成功,当多个线程/服务同时尝试 add 一个锁键时,只有一个能成功,获得锁,其他未成功的线程需要不断重试(自旋锁)或等待,释放锁时,直接 delete 即可。
public class MemcachedLock {
private final MemcachedClient memcachedClient;
private final String lockKey;
private final long lockTimeout; // 锁的超时时间,防止死锁
public MemcachedLock(MemcachedClient client, String key, long timeout) {
this.memcachedClient = client;
this.lockKey = key;
this.lockTimeout = timeout;
}
/**
* 尝试获取锁
* @return 是否成功获取锁
*/
public boolean tryLock() {
try {
// add 命令只在键不存在时才成功
return memcachedClient.add(lockKey, (int) (lockTimeout / 1000), "locked");
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 释放锁
*/
public void unlock() {
try {
memcachedClient.delete(lockKey);
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 使用示例
// MemcachedClient client = ...; // 已创建的客户端
// MemcachedLock lock = new MemcachedLock(client, "resource_lock_123", 5000); // 5秒锁超时
//
// if (lock.tryLock()) {
// System.out.println("成功获取锁,执行业务逻辑...");
// try {
// // 模拟耗时操作
// Thread.sleep(3000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// lock.unlock(); // 释放锁
// System.out.println("业务逻辑执行完毕,已释放锁。");
// } else {
// System.out.println("获取锁失败,资源正忙。");
// }
完整示例代码
下面是一个整合了连接、基本操作和 CAS 的完整示例。
import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.MemcachedClientBuilder;
import net.rubyeye.xmemcached.XMemcachedClientBuilder;
import net.rubyeye.xmemcached.utils.AddrUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class MemcachedExample {
private static final Logger logger = LoggerFactory.getLogger(MemcachedExample.class);
public static void main(String[] args) {
MemcachedClient memcachedClient = null;
try {
// 1. 创建客户端
MemcachedClientBuilder builder = new XMemcachedClientBuilder(
AddrUtil.getAddresses("127.0.0.1:11211")
);
builder.setConnectionPoolSize(5);
memcachedClient = builder.build();
logger.info("成功连接到 Memcached 服务器。");
// 2. 基本操作
basicOperations(memcachedClient);
// 3. CAS 操作
casOperation(memcachedClient);
} catch (IOException e) {
logger.error("创建或关闭 Memcached 客户端时发生 IO 异常", e);
} finally {
if (memcachedClient != null) {
try {
memcachedClient.shutdown();
logger.info("Memcached 客户端已关闭。");
} catch (Exception e) {
logger.error("关闭 Memcached 客户端时发生异常", e);
}
}
}
}
private static void basicOperations(MemcachedClient client) throws TimeoutException, InterruptedException, IOException {
logger.info("--- 开始基本操作演示 ---");
String key = "user:profile:101";
String value = "Java Developer";
// 设置
client.set(key, 3600, value);
logger.info("设置键 '{}': {}", key, value);
// 获取
String getValue = client.get(key);
logger.info("获取键 '{}': {}", key, getValue);
// 替换
String newValue = "Senior Java Developer";
client.replace(key, 3600, newValue);
logger.info("替换键 '{}' 为: {}", key, newValue);
getValue = client.get(key);
logger.info("替换后获取键 '{}': {}", key, getValue);
// 删除
client.delete(key);
logger.info("删除键 '{}'", key);
getValue = client.get(key);
logger.info("删除后获取键 '{}': {}", key, getValue); // 应为 null
logger.info("--- 基本操作演示结束 ---\n");
}
private static void casOperation(MemcachedClient client) throws TimeoutException, InterruptedException, IOException {
logger.info("--- 开始 CAS 操作演示 ---");
String counterKey = "product:view_count:888";
// 初始化计数器
client.set(counterKey, 0, 100L);
logger.info("初始化计数器 '{}': 100", counterKey);
// 获取初始 CAS 值
CASValue<Long> casValue = client.gets(counterKey);
long currentValue = casValue.getValue();
long currentCas = casValue.getCas();
logger.info("当前计数器值: {}, CAS: {}", currentValue, currentCas);
// 模拟并发更新:增加 1
long newValue = currentValue + 1;
logger.info("尝试将计数器从 {} 更新为 {}", currentValue, newValue);
// 尝试 CAS 更新
boolean casResult = client.cas(counterKey, 0, newValue, currentCas);
if (casResult) {
logger.info("CAS 更新成功!新值为: {}", newValue);
} else {
logger.info("CAS 更新失败!可能是其他线程先更新了。");
}
// 验证最终值
Long finalValue = client.get(counterKey);
logger.info("计数器 '{}' 的最终值为: {}", counterKey, finalValue);
logger.info("--- CAS 操作演示结束 ---");
}
}
- 核心类:
MemcachedClient是操作的核心,通过MemcachedClientBuilder进行配置和构建。 - 基本操作:
set,get,add,replace,delete方法非常直观。 - 高级特性:
- CAS:通过
gets和cas方法实现乐观锁,保证数据并发安全。 - 计数器:
incr/decr是原子操作,性能高。 - 分布式锁:利用
add的特性实现,简单但有效。
- CAS:通过
- 最佳实践:
- 连接管理:使用单例模式管理
MemcachedClient,避免频繁创建和销毁。 - 异常处理:妥善处理
TimeoutException,InterruptedException,IOException。 - 序列化:
Xmemcached默认使用 Java 序列化,性能较差,对于高性能场景,建议配置Kryo或FST等高效的序列化方案。 - 过期时间:合理设置过期时间,防止缓存雪崩和穿透。
- 连接管理:使用单例模式管理
希望这份详细的指南能帮助你顺利地在 Java 项目中集成和使用 Memcached!
