SpringBoot 精通系列-SpringBoot如何操作Memcache

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/nihui123/article/details/101101222

导语
  随着公司的业务速度的提高,数据持久化的问题就凸显出来,很多的场景下使用的是缓存技术来解决请求数据库的压力,这种也是缓存技术使用最多的场景之一,当然在高并发、分布式Session场景下,也会使用缓存技术来提高系统的可用性。在工作中比较常用的是Redis,当然在有些场景下使用的是Memcache。这里首先来介绍一下关于Memcache 的使用

Memcache介绍

  首先来说Memcache是一个开源高性能的分布式内存对象key-value缓存系统,用于加速动态的Web应用,从而减轻数据库的负载能力,在工作场景中很多人把它当做一个内存式的数据库在使用。那么内存式到底是什么呢?我们都知道,在计算机主要靠CPU来进行计算,内存用来存储CPU操作的数据。在计算机硬件中还有一个叫做硬盘的东西。那么这三者之间是怎么交互的。首先要知道计算机内存式有限的,这个是不可否认的,其次CPU的计算速度与内存以及外部存储之间是存在一定的差距的,所以就使用了一种高速缓存Cache的技术。来匹配内存与CPU之间的速度不匹配的问题。也就是说在计算机中能跟内存挂钩的都是速度比较搞的。Memcache被称为是内存式的缓存,那么它的效率一定是毋庸置疑。

  它可以应对任意多个连接,使用非阻塞的网络IO,由于它的工作机制就是跟上面说的一样是直接操作内存,在内存中开辟的空间,然后建立Hash表,并且有Memcache自己来管理这些Hash表,这样的方式来进行缓存操作,再加上非阻塞的IO。执行的效率上要比一般的缓冲设计结构更高效。

Memcache 特点

协议简单

  Memcache在服务端和客户端之间的通信中采用的是最为简单的文本协议,可以通过Telnet就可以在Memcache上存取数据。

基于Libevent的事件处理机制

  Libevent是一套跨平台的事件处理接口的封装。首先要知道在不同操作系统中对于事件的操作是不一样的,例如在不同的Linux版本中操作IO事件有poll、epoll。在Windows中的select。当然在低版本的Linux中也有使用select的。那么这些在不同平台上的IO事件处理,在Memcache中都得到了解决,使用Libevent进行网络并发连接的处理,能够保证在高并发的情况下,任然可以保持快速响应的能力。

内置的内存存储方式

  之前提到的Memcache中保存的数据都存储在Memcache内置的内存空间中,由于数据存储在内存中,所以当出现宕机或者是出现重启的时候就会导致内存中的数据丢失,都知道内存中的数据并不是持久化存储的。Memcache LRU(Least Recently Used)算法自动删除不使用的缓存,不过这个功能是可以进行配置的,Memcache通过启动“-M”参数可以禁止LRU,当是为了高效实用建议不要禁用。

不适用场景列举

  • 缓存对象不能大于1MB,毕竟操作的是内存太大的话会导致内存消耗加速
  • key 的长度大于250字符,还是上面的原因
  • Memcache 未提供任何的安全策略,也就是说有些数据可以这里获取
  • 不支持持久化,因为操作的是内存。

Memcache 安装

这里介绍的是在Ubuntu下的安装。

安装Memcache服务端

sudo apt-get install memcached

root@nihui-PC:~# apt-get install memcached
正在读取软件包列表... 完成
正在分析软件包的依赖关系树
正在读取状态信息... 完成
建议安装:
  libcache-memcached-perl libmemcached libanyevent-perl libyaml-perl libterm-readkey-perl
下列【新】软件包将被安装:
  memcached
升级了 0 个软件包,新安装了 1 个软件包,要卸载 0 个软件包,有 184 个软件包未被升级。
需要下载 122 kB 的归档。
解压缩后会消耗 295 kB 的额外空间。
获取:1 http://packages.deepin.com/deepin panda/main amd64 memcached amd64 1.5.6-1 [122 kB]
已下载 122 kB,耗时 0秒 (277 kB/s)
正在选中未选择的软件包 memcached。
(正在读取数据库 ... 系统当前共安装有 192272 个文件和目录。)
正准备解包 .../memcached_1.5.6-1_amd64.deb  ...
正在解包 memcached (1.5.6-1) ...
正在设置 memcached (1.5.6-1) ...
Created symlink /etc/systemd/system/multi-user.target.wants/memcached.service → /lib/systemd/system/memcached.service.
正在处理用于 systemd (238-5) 的触发器 ...
正在处理用于 man-db (2.8.3-2) 的触发器 ...

安装完Memcache服务端以后,我们需要启动该服务:

memcached -d -m 128 -p 11111 -u root

这里需要说明一下memcached服务的启动参数:

-p 监听的端口
-l 连接的IP地址, 默认是本机
-d start 启动memcached服务
-d restart 重起memcached服务
-d stop|shutdown 关闭正在运行的memcached服务
-d install 安装memcached服务
-d uninstall 卸载memcached服务
-u 以的身份运行 (仅在以root运行的时候有效)
-m 最大内存使用,单位MB。默认64MB
-M 内存耗尽时返回错误,而不是删除项
-c 最大同时连接数,默认是1024
-f 块大小增长因子,默认是1.25-n 最小分配空间,key+value+flags默认是48
-h 显示帮助

root@nihui-PC:~# memcached -d -m 128 -p 11111 -u root
root@nihui-PC:~#
root@nihui-PC:~# ps -ef|grep memcache
memcache  5395     1  0 12:07 ?        00:00:00 /usr/bin/memcached -m 64 -p 11211 -u memcache -l 127.0.0.1 -P /var/run/memcached/memcached.pid
root      6272     1  0 12:09 ?        00:00:00 memcached -d -m 128 -p 11111 -u root
root      6621  3648  0 12:11 pts/1    00:00:00 grep memcache
root@nihui-PC:~#

会发现其中启动了两个 Memcache实例,其中一个是使用上面的命令启动的,一个是默认启动的。

Memcache客户端
Memcache Clinet 目前支持3种。

  • Memcached Client for Java停止更新
  • SpyMemcached 停止更新
  • 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是怎么集成Memcache。

1. 增加依赖管理

  添加关于memcache的依赖

 <!-- https://mvnrepository.com/artifact/com.googlecode.xmemcached/xmemcached -->
 <dependency>
     <groupId>com.googlecode.xmemcached</groupId>
     <artifactId>xmemcached</artifactId>
     <version>2.4.5</version>
 </dependency>

详细配置如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.nh.memcache</groupId>
    <artifactId>memcache</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>memcache</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.googlecode.xmemcached/xmemcached -->
        <dependency>
            <groupId>com.googlecode.xmemcached</groupId>
            <artifactId>xmemcached</artifactId>
            <version>2.4.5</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2.添加配置文件

  当然在添加配置文件的时候,SpringBoot默认没有支持自动配置所以需要使用SpringBoot提供的配置文件机制来编写自己的配置文件。
首先编写一个配置文件的Properties对象用来与配置文件进行映射

/**
 * @Classname XMemcachedProperties
 * @Description TODO
 * @Date 2019/9/21 12:41 PM
 * @Created by nihui
 */
@Component
@ConfigurationProperties(prefix = "memcached")
public class XMemcachedProperties {
    private String servers;
    private int poolSize;
    private long opTimeout;

    public String getServers() {
        return servers;
    }

    public void setServers(String servers) {
        this.servers = servers;
    }

    public int getPoolSize() {
        return poolSize;
    }

    public void setPoolSize(int poolSize) {
        this.poolSize = poolSize;
    }

    public long getOpTimeout() {
        return opTimeout;
    }

    public void setOpTimeout(long opTimeout) {
        this.opTimeout = opTimeout;
    }
}

编写Memcache的配置类使用@Configration注解进行标注表明这个是一个配置类

/**
 * @Classname MemcachedBuilder
 * @Description TODO
 * @Date 2019/9/21 12:44 PM
 * @Created by nihui
 */
@Configuration
public class MemcachedBuilder {
    protected static Logger logger = LoggerFactory.getLogger(MemcachedBuilder.class);

    @Resource
    private XMemcachedProperties xMemcachedProperties;

    @Bean
    public MemcachedClient getMemcachedClinet(){
        MemcachedClient memcachedClient = null;
        try {
            MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses(xMemcachedProperties.getServers()));
            builder.setConnectionPoolSize(xMemcachedProperties.getPoolSize());
            builder.setOpTimeout(xMemcachedProperties.getOpTimeout());
            memcachedClient = builder.build();
        }catch (IOException e){
            logger.error("init MemcachedClient failed"+e);
        }
        return memcachedClient;
    }
}

3.注入组件

  如上代码在配置类中注入一个MemcacheClient的Bean对象,并且设置了一些基本的参数,而这些参数都是由配置文件来提供

  @Bean
    public MemcachedClient getMemcachedClinet(){
        MemcachedClient memcachedClient = null;
        try {
            MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses(xMemcachedProperties.getServers()));
            builder.setConnectionPoolSize(xMemcachedProperties.getPoolSize());
            builder.setOpTimeout(xMemcachedProperties.getOpTimeout());
            memcachedClient = builder.build();
        }catch (IOException e){
            logger.error("init MemcachedClient failed"+e);
        }
        return memcachedClient;
    }

4.编写配置文件

  根据上面配置类的内容,可以知道需要配置如下的三个参数,服务地址、线程池大小、超时时间,当然为了高可用的话还可以将服务地址设置成一个数组。这里是测试就先不用高可用。

memcached.servers=10.2.116.178:11111
memcached.poolSize=10
memcached.opTimeout=6000

5.编写测试类

  这里使用默认的SpringBoot自带的测试类进行测试。测试缓存的get和set方法。

@RunWith(SpringRunner.class)
@SpringBootTest
public class MemcacheApplicationTests {

    @Autowired
    private MemcachedClient memcachedClient;
    @Test
    public void contextLoads() throws Exception {
        memcachedClient.set("hello",0,"Hello,xmemcached");
        String value = memcachedClient.get("hello");
        System.out.println("hello = "+ value);
        memcachedClient.delete("hello");
    }

}

  可以看到存储数据是通过set方法还有设置了其三个参数,第一个参数表示key,第一个参数表示expire时间单位是秒,超过这个时间memcached将这个数据替换出去,0表示永久存储,默认是一个月,第三个参数就是实际存储的数据,可以是任意的Java可序列化类型,当然也可以继承序列化接口Serializable,或者是可以序列化为指定类型,当然这里要满足Value的大小设定,超过大小将不会被缓存。

总结

  上面简单的介绍了关于Memcache以及如何使用SpringBoot来整合Memcache,当然上面只是举例了一个简单的小例子。后面的博客中还会有更多的关于memcache 的使用在等着大家,希望大家可以多多支持。

猜你喜欢

转载自blog.csdn.net/nihui123/article/details/101101222