1. Memcached 简介
- 是一个免费开源的、高性能的、具有分布式内存对象的缓存系统,它通过减轻数据库负载加速动态 Web 应用。
- 本质上就是一个内存 key-value 缓存。
- 协议简单,使用的是基于文本行的协议。
- 不支持数据的持久化,服务器关闭之后数据全部丢失。
- Memcached 简洁而强大,便于快速开发,上手较为容易。
- 没有安全机制。
2. Memcached 设计理念
- 简单的键/值存储。
- 服务器不关心您的数据是什么样的,只管数据存储。
- 服务端功能简单,很多逻辑依赖客户端实现。
- 客户端专注如何选择读取或写入的服务器,以及无法联系服务器时要执行的操作。
- 服务端专注如何存储和管理合适清除或重用内存。
- Memcached 实例之间没有通信机制。
- 每个命令的复杂度为 O(1)。
- 慢速机器上的查询应该在 1ms 一下运行。高端服务器的吞吐量可以达到每秒数百万。
- 缓存自动清除机制。
- 缓存失效机制。
3. 安装和测试
代码语言:javascript复制yum install libevent-devel
wget https://memcached.org/latest
mv latest memcached-1.6.6.tar.gz
tar -zxf memcached-1.6.6.tar.gz
cd memcached-1.6.6
./configure --prefix=/usr/local/memcached
make && sudo make install
# 启动并使用 memcached
cd /usr/local/memcached
./bin/memcached -m 64 -p 11211 -u root -vvv
# 使用 memcached
# telnet memcached_server_ip port
telnet localhost 11211
常用启动参数
参数 | 说明 |
---|---|
-p <num> | 监听的 TCP 端口(默认:11211) |
-U <num> | 监听的 UDP 端口(默认:11211,0 表示不监听) |
-l <ip_addr> | 监听的 IP 地址(默认:INADDR_ANY,所有地址) |
-d | 作为守护进程来运行 |
-u <username> | 设定进程所属用户(仅 root 用户可以使用) |
-m <num> | 所有 slab class 可用内存的上限(默认:64MB) |
-v | 提示信息(在事件循环中打印错误/警告信息) |
-vv | 详细信息(还打印客户端命令/响应) |
-vvv | 超详细信息(还打印内部状态的变化) |
4. 常用命令
数据处理命令
分组 | 命令 | 描述 |
---|---|---|
存储命令 | set | 用于将 value 存储在指定的 key 中。key 已经存在,更新该 key 所对应的原来的数据。 |
存储命令 | add | 用于将 value 存储在指定的 key 中,存在则不更新。 |
存储命令 | replace | 替换已经存在的 key 的 value,不存在,则替换失败。 |
存储命令 | append | 命令用于向已存在的 key 的 value 后面追加数据。 |
存储命令 | prepend | 向已存在 key 的value 的千面追加数据。 |
存储命令 | cas | 比较和替换,比对后,没有被其他客户端修改的情况下才能写入。 |
检索命令 | get | 获取存储在 key 中的 value,不存在,则返回空。 |
检索命令 | gets | 获取带有 CAS 令牌存的 value,若 key 不存在,则返回为空。 |
删除 | delete | 删除已存在的 key。 |
计算 | incr/decr | 对已存在的 key 的数字值进行自增或自减操作。 |
清除 | flush_all | 清除所有内容。 |
监控命令
命令 | 描述 |
---|---|
stats | 返回 memcached 的统计信息 |
stats settings | 正在运行的 memcached 的设置 |
stats items | 每个 slab class 的存储信息 |
stats sizes | 存储在缓存中的所有 item 的常规大小和计数 |
stats sizes_enable | 启动直方图的形式展示 sizes 信息 |
stats sizes_disable | 禁用直方图 |
stats slabs | 已激活的 slab 的信息 |
stats conns | 连接信息 |
stats reset | 清空统计数据 |
- 命令地址:https://github.com/memcached/memcached/blob/master/doc/protocol.txt
5. 客户端使用
6. Java 使用 xmemcached 具体例子
1. 添加依赖
代码语言:javascript复制<dependency>
<groupId>com.googlecode.xmemcached</groupId>
<artifactId>xmemcached</artifactId>
<version>xxx</version>
</dependency>
2. 配置类 AppConfig
代码语言:javascript复制@Configuration
@Profile("single")
public class AppConfig {
@Bean
public MemcachedClient memcachedClient() throws IOException {
return new XMemcachedClient("127.0.0.1", 11211);
}
}
3. 业务模拟 UserService
代码语言:javascript复制@Service
@Profile("single")
public class UserService {
@Resource
private MemcachedClient memcachedClient;
public User findUser(String userId) throws Exception {
User user;
// 1. 判断缓存中是否存在
user = memcachedClient.get(userId);
if (user != null) {
System.out.println("从缓存中读取到值:" user);
return user;
}
// TODO 2. 不存在则读取数据库或者其他地方的值
user = new User(userId, "张三");
System.out.println("从数据库中读取到值:" user);
// 3. 同步存储 value 到 memcached,缓存超时为 1 小时,3600 秒
memcachedClient.set(userId, 3600, user);
return user;
}
}
4. 测试类
代码语言:javascript复制@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
@ActiveProfiles("single")
public class UserServiceTests {
@Resource
private UserService userService;
@Test
public void setTest() throws Exception {
User user = userService.findUser("zp");
System.out.println(user);
}
}
5. 结果
- 第一次运行,可以看到第一次因缓存中没有,从数据库读取。
- 第二次运行,可以看到从缓存中读取。
7. 服务端配置
- 命令行参数
- 查看
memcached -h
或man memcached
获取最新文档。
- 查看
- init 脚本
- 如果通过 yum 应用商店安装,可以使用
/etc/sysconfig/memcached
文件进行参数配置。
- 如果通过 yum 应用商店安装,可以使用
- 检查运行配置
stats settings
查看运行中的 memcached 的配置(可以用 telnet 连接 memcached 进行测试)。
8. Memcached 性能
- Memcached 性能的关键是硬件,内部实现是 hash 表,读写操作都是 O(1)。硬件好,几百万的 QPS 都是没问题的。
- 最大连接数限制:内部基于事件机制(类似于 JAVA NIO)所以这个限制和 nio 类似,只要内存、操作系统参数进行调整,轻松几十万。
- 集群节点数量限制:理论是没限制的,但是节点越多,客户端需要建立的连接就会越多。如果要存储的数据很多,优先考虑可以增加内存,成本太高的情况下,再增加节点。
- memcached 服务端没有分布式的功能,所以不论是集群还是主从备份,都需要第三方产品支持。
9. 服务器硬件需要
- CPU 要求
- CPU 占用率低,默认为 4 个工作线程。
- 内存要求
- memcached 内容存在内存里面,所以内存使用率高。
- 建议 memcached 实例独占服务器,而不是混用。
- 建议每个 memcached 实例内存大小都是一致的,如果不一致则需要进行权重调整。
- 网络要求
- 根据用户传输的内容来定,网络越大越好,虽然通常 10M 就够用了。
- 建议:项目往 memcached 传输的内容保持尽可能的小。
这些应该在前期规划的时候尽量考虑进去。
10. Memcached 应用场景
- 数据查询缓存:将数据库中的数据加载到 memcached,提供程序的访问速度。
- 计数器的场景:通过
incr
/decr
命令实现评论数量、点击数统计、操作次数等等场景。 - 乐观锁实现:例如计划任务多实例部署的场景下,通过 CAS 实现不重复执行。
- 防止重复处理:CAS 命令。