Memcached集成配置Springboot以及xmemcached常规操作

目录

(一) 集成前配置

引入依赖

配置application.yml

自定义properties类

自定义Memcached连接配置类

MemcachedClien

tBuilder 相关属性含义

(二) MemcachedClient相关操作

插入Set

获取Get

touch更新数据超时时间

CAS原子操作

综合性操作例子

迭代所有key(不建议)

Incr/Decr原子递增/原子递减

查看统计信息

保存数据体量较大时压缩

(三) 监视服务器运行状况stats命令详解


(一) 集成前配置

引入依赖

         
        
        
            com.googlecode.xmemcached
            xmemcached
            2.4.5
        

配置application.yml

spring:
  memcache:
    # 服务地址
    servers: 127.0.0.1:11211
    # 连接数量
    poolSize: 10
    # 操作超时时长
    opTimeout: 5000
    sanitizeKeys: false    # 是否启用url encode机制

自定义properties类

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * XMemcached
 * 为了缩短篇幅 , 笔者删减了getter 和 setter 
 * @author HUANG
 */
@Component
// 用于读取配置文件
@ConfigurationProperties(prefix = "spring.memcache")
public class IMemcachedProperties {

    /**
     * memcached服务地址
     */
    private String servers;

    /**
     * nio连接池的数量
     */
    private Integer poolSize;

    /**
     * 设置默认操作超时
     */
    private Long opTimeout;

    /**
     * 是否启用url encode机制
     */
    private Boolean sanitizeKeys;
 
}

自定义Memcached连接配置类

import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.MemcachedClientBuilder;
import net.rubyeye.xmemcached.XMemcachedClientBuilder;
import net.rubyeye.xmemcached.command.BinaryCommandFactory;
import net.rubyeye.xmemcached.impl.KetamaMemcachedSessionLocator;
import net.rubyeye.xmemcached.utils.AddrUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;

/**
 * Memcached 配置
 */
@Configuration
public class IMemcachedConfig {

    /**
     * 日志
     */
    private static Logger logger = LoggerFactory.getLogger(IMemcachedConfig.class);

    @Autowired
    private IMemcachedProperties iMemcachedProperties;

    @Bean
    public MemcachedClient getMemcachedClinet() {
        MemcachedClient memcachedClient = null;
        try {
            // 获取连接
            MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses(iMemcachedProperties.getServers()));
            // 从1.3版本开始,xmemcached支持failure模式。所谓failure模式是指,当一个memcached节点down掉的时候,发往这个节点的请求将直接失败,而不是发送给下一个有效的memcached节点 , 默认不启用failure模式
            builder.setFailureMode(false);
            builder.setSanitizeKeys(iMemcachedProperties.getSanitizeKeys());
            // 启用连接池 , 设置nio连接池连接数量, Xmemcached是基于java nio的client实现,默认对一个memcached节点只有一个连接,这在通常情况下已经有非常优异的表现。但是在典型的高并发环境下,nio的单连接也会遇到性能瓶颈。因此XMemcached支持设置nio的连接池,允许建立多个连接到同一个memcached节点,但是请注意,这些连接之间是不同步的,因此你的应用需要自己保证数据更新的同步,
            builder.setConnectionPoolSize(iMemcachedProperties.getPoolSize());
            // 设置操作超时时长
            builder.setOpTimeout(iMemcachedProperties.getOpTimeout());
            // 设置连接时长
            builder.setConnectTimeout(3000);
            // 设置数据一致性hash算法
            builder.setSessionLocator(new KetamaMemcachedSessionLocator());
            // 启用二进制协议 Memcached 1.4开始正式启用二进制协议,xmemcached 1.2开始支持二进制协议
            builder.setCommandFactory(new BinaryCommandFactory());
            memcachedClient = builder.build();
        } catch (IOException e) {
            logger.error("init MemcachedClient fail:", e);
        }
        return memcachedClient;
    }

}

MemcachedClientBuilder 相关属性含义

配置选项参数表:

属性名
servers memcached节点列表,形如“主节点1:port,备份节点1:port 主节点2:port,备份节点2:port“的字符串,可以不设置备份节点,主备节点逗号隔开,不同分组空格隔开。
weights 与servers对应的节点的权重
authInfoMap 授权验证信息,仅在xmemcached 1.2.5及以上版本有效
connectionPoolSize nio连接池大小,默认为1
commandFactory 协议工厂,net.rubyeye.xmemcached.command.BinaryCommandFactory,TextCommandFactory(默认),KestrelCommandFactory
sessionLocator 分布策略,一致性哈希net.rubyeye.xmemcached.impl.KetamaMemcachedSessionLocator或者ArraySessionLocator(默认)
transcoder 序列化转换器,默认使用net.rubyeye.xmemcached.transcoders.SerializingTranscoder,更多选项参见javadoc
bufferAllocator IoBuffer分配器,默认为net.rubyeye.xmemcached.buffer.SimpleBufferAllocator,可选CachedBufferAllocator(不推荐)
failureMode 是否启用failure模式,true为启用,默认不启用

(二) MemcachedClient相关操作

插入Set

客户不能存储所有类型的复杂结构。对象通常是不可序列化的,例如从mysql查询返回的行对象。必须先将数据转换为纯数组或哈希/表类型结构,然后才能存储或检索它。key最长250 , 存储体量单个最大1M(因为这是典型slab 的最大值)

// 使用到的引入类
import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.exception.MemcachedException;

    // 注入客户端实例  
    @Autowired
    private MemcachedClient memcachedClient;

    @PostMapping("/testMem001")
    public void testMem001(String key, String value){
        try {
            memcachedClient.set(key, 0, value,  5000);
            Object o = memcachedClient.get(key);
            System.out.println("查询出来的数据是" + o);
        } catch (TimeoutException e) {
            // 此处若是set进去的数据已经超时失效 get方法就会出现TimeOutException
            logger.error("数据失效,查询失败,key:[{}]" , key);
            e.printStackTrace();
        } catch (InterruptedException | MemcachedException e) {
            e.printStackTrace();
        }
    } 

获取Get

  • 存储数据是通过set方法,它有三个参数,第一个是存储的key名称,第二个是expire时间(单位秒),超过这个时间,memcached将这个数据替换出去,0表示永久存储(默认是一个月),第三个参数就是实际存储的数据,可以是任意的java可序列化类型。
  • 获取存储的数据是通过get方法,传入key名称即可。如果要删除存储的数据,这是通过delete方法,它也是接受key名称作为参数。
  • XMemcached由于是基于nio,因此通讯过程本身是异步的,client发送一个请求给memcached,你是无法确定memcached什么时候返回这个应答,客户端此时只有等待,因此还有个等待超时的概念在这里。客户端在发送请求后,开始等待应答,如果超过一定时间就认为操作失败,这个等待时间默认是5秒(1.3.8开始改为5秒,之前是1秒),上面例子展现的方法调用的都是默认的超时时间,get方法同样有允许传入超时时间的重载方法,例如
   value=client.get(“hello”,3000);

就是等待3秒超时,如果3秒超时就跑出TimeoutException,用户需要自己处理这个异常。因为等待是通过调用CountDownLatch.await(timeout)方法,因此用户还需要处理中断异常InterruptException。最后的MemcachedException表示Xmemcached内部发生的异常,如解码编码错误、网络断开等等异常情况。

touch更新数据超时时间

client.touch(key,new-expire-time);
  • 获取缓存数据并更新超时时间
client.getAndTouch(key,new-expire-time);

CAS原子操作

Memcached是通过cas协议实现原子更新,所谓原子更新就是compare and set,原理类似乐观锁,每次请求存储某个数据同时要附带一个cas值,memcached比对这个cas值与当前存储数据的cas值是否相等,如果相等就让新的数据覆盖老的数据,如果不相等就认为更新失败,这在并发环境下特别有用。XMemcached提供了对CAS协议的支持(无论是文本协议还是二进制协议),XMemcached提供了一个*CASOperation*接口包装了这部分操作,允许你尝试N次去原子更新某个key存储的数据,无需显式地调用gets获取cas值

CASOpertion接口只有两个方法,一个是设置最大尝试次数的getMaxTries方法,这里是尝试一次,如果尝试超过这个次数没有更新成功将抛出一个TimeoutException,如果你想无限尝试(理论上),可以将返回值设定为Integer.MAX_VALUE;另一个方法是根据当前获得的GetsResponse来决定更新数据的getNewValue方法,如果更新成功,这个方法返回的值将存储成功,这个方法的两个参数是最新一次gets返回的GetsResponse结果。

//cas 操作 CASOperation String 就是你将要修改后的值类型 也是getNewValue的return值
boolean huang = this.memcachedClient.cas("hxk3", new CASOperation() {
         @Override
         public int getMaxTries() {
                return 0;
         }
         @Override
         public String getNewValue(long currentCAS, String currentValue) {
                return "这是新的CAS值";
         }
});

综合性操作例子

  
  // 首先存储 hello 对应的world字符串
  if (!client.set("hello", 0, "world")) {
		System.err.println("set error");
  }

  //  然后调用add添加,因为数据已经存在,因此add会失败
  if (client.add("hello", 0, "dennis")) {
		System.err.println("Add error,key is existed");
  }

  //  然后调用replace替换 , replace在数据存在的情况才会成功,也就是将hello对应的数据更新为dennis
  if (!client.replace("hello", 0, "dennis")) {
		System.err.println("replace error");
  }
    
  // 然后通过prepend方法在dennis前加上了字符串hello 
  client.append("hello", " good");

  // 然后通过append方法在dennis后加上了字符串good
  client.prepend("hello", "hello ");

  // 获取
  String name = client.get("hello", new StringTranscoder());
  // 结果 hello dennis good。
  System.out.println(name);
  // 而删除数据则是通过deleteWithNoReply方法,这个方法删除数据并且告诉memcached不用返回应答,因此这个方法不会等待应答直接返回,特别适合于批量处理;同样地,set、add、replace等方法也有相应的withNoReply重载版本
  client.deleteWithNoReply(“hello”);

迭代所有key(不建议)

迭代器是memcached所有key的快照,它不是实时的。“ stats cachedump”具有长度限制,因此如果有很多密钥,迭代器将无法访问所有密钥. 应用程序不应依赖于此功能。

不推荐使用  memcached 1.6.x将删除cachedump stats命令,因此以后将删除此方法
 

Memcached本身并没有提供迭代所有key的方法,但是通过"stats items"和"stats cachedump"统计协议可以做到迭代所有的key,这个迭代过程是低效,因此如无必要,并不推荐使用此方法。XMemcached仅提供了文本协议的迭代支持,其他协议暂未支持。

想迭代所有的key,你只需要获取一个KeyIterator即可:


KeyIterator it=client.getKeyIterator(AddrUtil.getOneAddress("localhost:11211"));
while(it.hasNext())
{
   String key=it.next();
}

Incr/Decr原子递增/原子递减

incr/decr 两个操作都类似Java中的原子类如AtomicIntger,用于原子递增或者递减变量数值:

this.memcachedClient.incr("a", 5, 1) == 1;
this.memcachedClient.incr("a", 5) == 6;
this.memcachedClient.incr("a", 4) == 10;
this.memcachedClient.decr("a", 1) == 9;
this.memcachedClient.decr("a", 2) == 7;

incr和decr都有三个参数的方法,第一个参数指定递增的key名称,第二个参数指定递增的幅度大小,第三个参数指定当key不存在的情况下的初始值。两个参数的重载方法省略了第三个参数,默认指定为0。

Xmemcached还提供了一个称为计数器的封装,它封装了incr/decr方法,使用它就可以类似AtomicLong那样去操作计数:

Counter counter=memcachedClient.getCounter("counter",0);
counter.incrementAndGet();
counter.decrementAndGet();
counter.addAndGet(-10);

其中getCounter的第二个参数是计数器的初始值。

查看统计信息

Memcached提供了统计协议用于查看统计信息:

  Map> result=client.getStats();

getStats方法返回一个map,其中存储了所有已经连接并且有效的memcached节点返回的统计信息,你也可以统计具体的项目,如统计items项目:

   Map> result=client.getStatsByItem("items");

只要向getStatsByItem传入需要统计的项目名称即可。

返回出局格式如下

Memcached集成配置Springboot以及xmemcached常规操作_第1张图片

保存数据体量较大时压缩

数据压缩

memcached存储大数据的效率是比较低的,当数据比较大的时候xmemcached会帮你压缩在存储,取出来的时候自动解压并反序列化,这个大小阀值默认是16K,可以通过Transcoder接口的setCompressionThreshold(1.2.1引入)方法修改阀值,

压缩时Memcached会设置一个特殊的标志位。然后压缩数据并存储。由于使用了特殊标志,客户端将自动知道是否在返回时解压缩该值。

比如设置为1K:

builder.getTranscoder()).setCompressionThreshold(1024);

sanitizeKeys

在官方客户端有提供一个sanitizeKeys选项,当选择用URL当key的时候,MemcachedClient会自动将URL encode再存储。默认是关闭的,想启用可以通过:

 builder.setSanitizeKeys(true);

(三) 监视服务器运行状况stats命令详解

  • pid: memcache服务器进程ID
  • uptime:服务器已运行秒数
  • time:服务器当前Unix时间戳
  • version:memcache版本
  • pointer_size:操作系统指针大小
  • rusage_user:进程累计用户时间
  • rusage_system:进程累计系统时间
  • curr_connections:当前连接数量
  • total_connections:Memcached运行以来连接总数
  • connection_structures:Memcached分配的连接结构数量
  • cmd_get:get命令请求次数 get_hits的数量通常高于cmd_set
  • cmd_set:set命令请求次数
  • cmd_flush:flush命令请求次数 , 每次有人发出flush_all命令时,缓存中的所有项目都会失效,并且此计数器会增加。
  • get_hits:get命令命中次数 get_hits的数量通常高于cmd_set
  • get_misses:get命令未命中次数
  • delete_misses:delete命令未命中次数
  • delete_hits:delete命令命中次数
  • incr_misses:incr命令未命中次数
  • incr_hits:incr命令命中次数
  • decr_misses:decr命令未命中次数
  • decr_hits:decr命令命中次数
  • cas_misses:cas命令未命中次数
  • cas_hits:cas命令命中次数
  • cas_badval:使用擦拭次数
  • auth_cmds:认证命令处理的次数
  • auth_errors:认证失败数目
  • bytes_read:读取总字节数
  • bytes_written:发送总字节数
  • limit_maxbytes:分配的内存总大小(字节)
  • accepting_conns:服务器是否达到过最大连接(0/1),与下面的listen_disabled_num相关,如果已经连接到memcached,则可以通过检查此值是1还是0来查看其是否达到最大连接数
  • listen_disabled_num:失效的监听数 , 计算memcached达到其连接限制的次数 , 当memcached达到最大连接数设置时,它将禁用其侦听器,并且新连接将在队列中等待,当有人断开连接时,memcached唤醒侦听器并再次开始接受,保持在零或接近零。
  • threads:当前线程数
  • conn_yields:连接操作主动放弃数目
  • bytes:当前存储占用的字节数
  • curr_items:当前存储的数据总数
  • total_items:启动以来存储的数据总数
  • evictions:LRU释放的对象数目
  • reclaimed:已过期的数据条目来存储新数据的数目

 

 

 

你可能感兴趣的:(memcached,memcached,java)