目录
上一篇提到,Memcached将数据全部保存在内存中,并且服务端节点间互相分离,这就带来了一定的性能问题:
首先,由于数据完全存储于内存中,一方面其性能上限比较低,很容易产生单点问题,另一方面,一旦服务器实例重启,原本的数据将全部丢失,因此,服务宕机的代价非常高;
其次,由于服务器很容易出现单点问题,宕机概率很高,从而导致访问穿透缓存层打向数据库,造成雪崩,如果应用到分布式系统架构中,会带来很大的潜在风险;
此外,由于Memcached无法像其他分布式组件那样具有自动发现的能力,因此无法扩展。
它主要依赖客户端提供分布式特性,官方对此的描述是:“Logic Half in Client, Half in Server”。
Memcached的常用客户端有xmemcached、spymemcached等。这里以xmemcached为例,官方介绍的特性如下:
- 完全支持Memcached的 text/bianry 协议
- 异步API
- 多线程/线程安全
- 支持通过哈希或一致性哈希管理多个服务器节点
- 使用JMX管理服务器节点
- 支持为节点设置权重
- 支持动态伸缩集群规模、设置节点权重
- 支持客户端统计数据
- 自动重连和心跳机制
- 支持与Spring集成
- NIO连接池
- 支持failure模式(快速失败)和standby模式(请求转发到后备节点)
- 可以自动发现AWS ElasticCache节点
- 支持kestrel(推特的一个分布式消息队列,不过已经不再维护了)
1 基本使用
首先需要引入依赖包:
<dependency>
<groupId>com.googlecode.xmemcached</groupId>
<artifactId>xmemcached</artifactId>
<version>2.4.6</version>
</dependency>
xmemcached的关键类是XMemcachedClient,它可以由XMemcachedClientBuilder来创建,或者直接new一个,下面是一个创建客户端,并添加和获取一条数据的例子:
public static void main(String[] args) throws Exception {
MemcachedClient client= new XMemcachedClient(HOST,11211);
client.add("helloworld",0,"this is a test example");
System.out.println(client.get("helloworld", new StringTranscoder()));
client.shutdown();
}
其他的Memcached命令,如cas、append、set、gets、stats等,xmemcached也提供了实现。 此外还提供了一些很有用的操作,例如touch。touch的作用是更新缓存的存活时间,不使用touch的话就要先get再set一次,开销很大,一个类似操作是getAndTouch,它可以获取缓存值并更新
2 高级特性
2.1 为节点设置权重
XMemcachedClient的构造方法,支持传入InetSocketAddress列表,来连接多个服务器,我们在服务器上再开一个实例,端口设定为11212,并添加到客户端的连接列表中,然后在一个10次的循环中进行写入操作:
ArrayList<InetSocketAddress> serverList=new ArrayList<>();
serverList.add(server1);
serverList.add(server2);
MemcachedClient client= new XMemcachedClient(serverList);
for(int i=0;i<10;i++){
client.add("helloworld-"+i,0,"this is a test example");
}
client.shutdown();
使用telnet分别连接到两个服务端,使用stats item命令,可以看到两边都是5个