zoukankan      html  css  js  c++  java
  • 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/
    任何傻瓜都能写出计算机可以理解的代码。好的程序员能写出人能读懂的代码。

     
  • 相关阅读:
    SQL练习题
    数据库基础
    Java-反射与注解
    Linux基础
    pipeline的使用示例
    vagrant与vrtualbox的使用
    12.04公有,私有属性,析构函数,成员属性
    12.1面向对象编程的介绍(oop):封装,继承,多态,访问私有属性
    mysql操作之二:fetchone与获取lastrowid
    10.02经典类的bug
  • 原文地址:https://www.cnblogs.com/leigq/p/13406521.html
Copyright © 2011-2022 走看看