SpringBoot整合Memcached

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);
	}

}

执行结果如下:

20191014213932.png

其它

  • 参考: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


作者:不敲代码的攻城狮
出处:https://www.cnblogs.com/leigq/
任何傻瓜都能写出计算机可以理解的代码。好的程序员能写出人能读懂的代码。

 
原文地址:https://www.cnblogs.com/leigq/p/13406521.html