1. Memcached 简介


  • 是一个免费开源的、高性能的、具有分布式内存对象的缓存系统,它通过减轻数据库负载加速动态 Web 应用。
  • 本质上就是一个内存 key-value 缓存。
  • 协议简单,使用的是基于文本行的协议。
  • 不支持数据的持久化,服务器关闭之后数据全部丢失。
  • Memcached 简洁而强大,便于快速开发,上手较为容易。
  • 没有安全机制。

    2. Memcached 设计理念


  • 简单的键/值存储。
    • 服务器不关心您的数据是什么样的,只管数据存储。
  • 服务端功能简单,很多逻辑依赖客户端实现。
    • 客户端专注如何选择读取或写入的服务器,以及无法联系服务器时要执行的操作。
    • 服务端专注如何存储和管理合适清除或重用内存。
  • Memcached 实例之间没有通信机制。
  • 每个命令的复杂度为 O(1)。
    • 慢速机器上的查询应该在 1ms 一下运行。高端服务器的吞吐量可以达到每秒数百万。
  • 缓存自动清除机制。
  • 缓存失效机制。

    3. 安装和测试


  1. yum install libevent-devel
  2. wget https://memcached.org/latest
  3. mv latest memcached-1.6.6.tar.gz
  4. tar -zxf memcached-1.6.6.tar.gz
  5. cd memcached-1.6.6
  6. ./configure --prefix=/usr/local/memcached
  7. make && sudo make install
  8. # 启动并使用 memcached
  9. cd /usr/local/memcached
  10. ./bin/memcached -m 64 -p 11211 -u root -vvv
  11. # 使用 memcached
  12. # telnet memcached_server_ip port
  13. telnet localhost 11211

常用启动参数

参数 说明
-p 监听的 TCP 端口(默认:11211)
-U 监听的 UDP 端口(默认:11211,0 表示不监听)
-l 监听的 IP 地址(默认:INADDR_ANY,所有地址)
-d 作为守护进程来运行
-u 设定进程所属用户(仅 root 用户可以使用)
-m 所有 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 清空统计数据

  • Java 客户端(xmemcached)示例: ```java MemcachedClient client = new XMemcachedClient(“host”, 11211);

// 同步存储 value 到 memcached,缓存超时为 1 小时,3600 秒。 client.set(“key”, 3600, someObject); // 从 memcached 获取 key 对应的 value。 Object someObject = client.get(“key”);

// 从 memcached 获取 key 对应的 value,操作超时 2 秒。 someObject = client.get(“key”, 2000); // 更新缓存的超时时间为 10 秒。 boolean success = client.touch(“key”, 10);

// 删除 value client.delete(“key”);


- 客户端支持的特性:集群下多服务器选择、节点权重配置、失败/故障转移、数据压缩、连接管理。
<a name="6e1a66a1"></a>
### 6. Java 使用 xmemcached 具体例子

---

<a name="c164f378"></a>
#### 1. 添加依赖
```xml
<dependency>
    <groupId>com.googlecode.xmemcached</groupId>
    <artifactId>xmemcached</artifactId>
    <version>xxx</version>
</dependency>

2. 配置类 AppConfig

@Configuration
@Profile("single")
public class AppConfig {

    @Bean
    public MemcachedClient memcachedClient() throws IOException {
        return new XMemcachedClient("127.0.0.1", 11211);
    }

}

3. 业务模拟 UserService

@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. 测试类

@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 -hman memcached 获取最新文档。
  • init 脚本
    • 如果通过 yum 应用商店安装,可以使用 /etc/sysconfig/memcached 文件进行参数配置。
  • 检查运行配置
    • 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 命令。