Memcached简介
Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。
为了提高性能,memcached中保存的数据都存储在memcached内置的内存存储空间中。由于数据仅存在于内存中,因此重启memcached、重启操作系统会导致全部数据消失。另外,内容容量达到指定值之后,就基于LRU(Least Recently Used)算法自动删除不使用的缓存。memcached本身是为缓存而设计的服务器,因此并没有过多考虑数据的永久性问题。
Memcached安装
我是参考这个安装的:https://www.runoob.com/memcached/window-install-memcached.html
Java客户端选型
根据阅读这篇文章,最后选择使用XMemcached
,前两个都已经停止更新了。
XMemcached介绍
是使用最为广泛的Memcache Java客户端,是一个全新的 Java Memcache Client。Memcache 通过它自定义协议与客户端交互,而XMemcached就是它的Java客户端实现,相比较于其他客户端来说XMemcached 的优点如下
XMemcached主要特性
XMemcached 支持设置连接池、宕机报警、使用二进制文件、一致性Hash、进行数据压缩等操作,总结下来有以下一些点
- 性能优势,使用的NIO
- 协议支持广泛
- 支持客户端分布,提供了一致性Hash 实现
- 允许设置节点权重,XMemcached允许通过设置节点的权重来调节Memcached的负载,设置的权重越高,该Memcached节点存储的数据就越多,所要承受的负载越大
- 动态的增删节点,Memcached允许通过JMX或者代码编程来实现节点的动态的添加或者删除操作。方便扩展或者替换节点。
- XMemcached 通过 JMX 暴露的一些接口,支持Client本身的监控和调整,允许动态设置调优参数、查看统计数据、动态增删节点等;
- 支持链接池操作。
- 可扩展性强,XMemcached是基于Java NIO框架 Yanf4j 来实现的,所以在结构上相对清晰,分层明确。
整合SpringBoot
依赖
Maven依赖:
<!--memcache-->
<!-- https://mvnrepository.com/artifact/com.googlecode.xmemcached/xmemcached -->
<dependency>
<groupId>com.googlecode.xmemcached</groupId>
<artifactId>xmemcached</artifactId>
<version>2.4.5</version>
</dependency>
<!--使用注解处理器来生成自己的元数据:参考:https://www.jianshu.com/p/57fec884c017-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
配置
当然在添加配置文件的时候,SpringBoot默认没有支持自动配置所以需要使用SpringBoot提供的配置文件机制来编写自己的配置文件。
1、application.yml添加配置:
# ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ memcache 配置 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ #
spring:
memcache:
# memcached服务器节点
servers: 127.0.0.1:11211
# nio连接池的数量
poolSize: 10
# 设置默认操作超时
opTimeout: 3000
# 是否启用url encode机制
sanitizeKeys: false
2、新建 XMemcachedProperties 类,用于保存yml中的配置
package com.blog.www.config.memcache;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
* XMemcached 配置属性,读取的是 yml 文件中 spring.memcached 开头的属性
*/
@ConfigurationProperties(prefix = "spring.memcached")
@PropertySource("classpath:application.yml")
@Configuration
@Data
public class XMemcachedProperties {
/**
* memcached服务器节点
*/
private String servers;
/**
* nio连接池的数量
*/
private Integer poolSize;
/**
* 设置默认操作超时
*/
private Long opTimeout;
/**
* 是否启用url encode机制
*/
private Boolean sanitizeKeys;
}
3、新建 MemcachedConfig 初始化配置
package com.blog.www.config.memcache;
import lombok.extern.slf4j.Slf4j;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.IOException;
/**
* Memcached 配置
*/
@Configuration
@Slf4j
public class MemcachedConfig {
@Autowired
private XMemcachedProperties xMemcachedProperties;
@Bean
public MemcachedClient getMemcachedClinet(){
MemcachedClient memcachedClient = null;
try {
MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses(xMemcachedProperties.getServers()));
builder.setFailureMode(false);
builder.setSanitizeKeys(xMemcachedProperties.getSanitizeKeys());
builder.setConnectionPoolSize(xMemcachedProperties.getPoolSize());
builder.setOpTimeout(xMemcachedProperties.getOpTimeout());
builder.setSessionLocator(new KetamaMemcachedSessionLocator());
builder.setCommandFactory(new BinaryCommandFactory());
memcachedClient = builder.build();
}catch (IOException e){
log.error("init MemcachedClient failed:", e);
}
return memcachedClient;
}
}
使用
package com.blog.www.base;
import org.junit.After;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* 测试基类,其他类继承此类
* <br/>
* @author :leigq
* @date :2019/8/13 17:17
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public abstract class BaseApplicationTests {
protected Logger log = LoggerFactory.getLogger(this.getClass());
private Long time;
@Before
public void setUp() {
this.time = System.currentTimeMillis();
log.info("==> 测试开始执行 <==");
}
@After
public void tearDown() {
log.info("==> 测试执行完成,耗时:{} ms <==", System.currentTimeMillis() - this.time);
}
}
package com.blog.www;
import com.blog.www.base.BaseApplicationTests;
import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.exception.MemcachedException;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.concurrent.TimeoutException;
/**
* Memcached 测试
*/
public class MemcachedTest extends BaseApplicationTests {
@Autowired
private MemcachedClient memcachedClient;
@Test
public void test() throws InterruptedException, TimeoutException, MemcachedException {
// 放入缓存
boolean flag = memcachedClient.set("a", 0, 1);
// 取出缓存
Object a = memcachedClient.get("a");
log.warn("a is [{}]", a);
// 3s后过期
memcachedClient.set("b", 3, 2);
Object b = memcachedClient.get("b");
log.warn("b is [{}]", b);
Thread.sleep(3000);
b = memcachedClient.get("b");
log.warn("b is [{}]", b);
}
}
执行结果如下:
其它
- 参考:https://blog.csdn.net/nihui123/article/details/101101222
- xmemcached Github:https://github.com/killme2008/xmemcached
- 深入使用XMemcached:http://www.imooc.com/article/256593
- memcache及使用场景:https://blog.csdn.net/weixin_43101391/article/details/82937849