spring Boot 整合 Memcached (含 windows 安装)

 

概述 : 

Memcached是一个自由开源的,高性能,分布式内存对象缓存系统。Memcached基于内存的key-value存储,

用来存储小块的任意数据,这些数据可以是数据库调用、API调用或者是页面渲染的结果。

通过Memcached缓存数据库查询结果,可以有效地减少数据库访问次数,进而提高动态Web应用的速度。

虽然Memcached的守护进程是用C写的,但是客户端可以用任何语言来编写,并通过Memcached协议与守护进程进行通信。

因为Spring Boot暂时还没有提供 Memcached相关的支持包,因此需要我们通过集成第三方提供的Memcached客户端来实现。

Spymemcached是官方推出的一个Memcached Java客户端,使用NIO实现,异步、单线程,在性能上表现出色,

广泛应用于Java + Memcached项目中。

下载安装地址 :

https://www.runoob.com/memcached/window-install-memcached.html


本次下载:

64位系统 1.4.5版本:http://static.runoob.com/download/memcached-1.4.5-amd64.zip


安装:

1、解压下载的安装包到指定目录。

2、在 memcached1.4.5 版本之后,memcached 不能作为服务来运行,需要使用任务计划中来开启一个普通的进程,

在 window 启动时设置 memcached自动执行。

我们使用管理员身份执行以下命令将 memcached 添加来任务计划表中:

  schtasks /create /sc onstart /tn memcached /tr "'D:JAVAMemcachedmemcached-amd64memcached.exe' -m 512"

  D:JAVAMemcachedmemcached-amd64memcached.exe 是我的解压缩地址

注意:-m 512 意思是设置 memcached 最大的缓存配置为512M。

注意:我们可以通过使用 "D:JAVAMemcachedmemcached-amd64memcached.exe -h" 命令查看更多的参数配置。

3、如果需要删除 memcached 的任务计划可以执行以下命令:

  schtasks /delete /tn memcached


4、启动和关闭 memcached 服务:
  D:JAVAMemcachedmemcached-amd64memcached.exe -d start (执行后没有成功和错误信息,表示成功)
  D:JAVAMemcachedmemcached-amd64memcached.exe -d stop (执行后没有成功和错误信息,表示成功)
命令参考:https://www.cnblogs.com/gyfluck/p/9239370.html

启动以后之后

可以 本地 Telnet 127.0.0.1 11211  看是否能访问

整合环境 :

jdk:1.8
版本: memcached-1.4.5-amd64

创建一个springboot项目

依赖的jar:

       <dependency>
            <groupId>net.spy</groupId>
            <artifactId>spymemcached</artifactId>
            <version>2.12.3</version>
        </dependency>

< 完整pom在最后 >

application.properties:

memcache.ip=127.0.0.1
memcache.port=11211

先来个main方法 测试一下:

package com.infinitepossibilities.Test;

import net.spy.memcached.MemcachedClient;
import java.net.InetSocketAddress;
import java.util.concurrent.Future;

public class Demo {

    public static void main(String[] args) throws Exception {
        test();
    }

    public static void test() throws Exception {

        MemcachedClient memcachedClient = new MemcachedClient(new InetSocketAddress("127.0.0.1", 11211));

        //设置缓存   过期时间单位为秒, 0表示永远不过期
        Future future = memcachedClient.set("yiwang", 5, "tongban");

        Object data;

        System.out.println("************* :  "+future.get());//返回状态 true or false
        data= memcachedClient.get("yiwang");
        System.out.println("第一次取出数据:"+data);

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        data = memcachedClient.get("yiwang");
        System.out.println("第二次取出数据:"+data);

        memcachedClient.shutdown();
    }
}

MemcacheConfig:

package com.infinitepossibilities.config;

import net.spy.memcached.MemcachedClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.IOException;
import java.net.InetSocketAddress;

@Configuration
public class MemcacheConfig {

    @Value("${memcache.ip}")
    private String ip;

    @Value("${memcache.port}")
    private int port;

    @Bean
    public MemcachedClient getMemcachedClient(){

        MemcachedClient memcachedClient = null;

        try {
            memcachedClient = new MemcachedClient(new InetSocketAddress(ip,port));
        } catch (IOException e) {
            e.printStackTrace();
        }

        return memcachedClient;
    }
}

MemcacheController:

package com.infinitepossibilities.controller;
import net.spy.memcached.CASResponse;
import net.spy.memcached.CASValue;
import net.spy.memcached.MemcachedClient;
import net.spy.memcached.internal.OperationFuture;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MemcacheController {

    @Autowired
    private MemcachedClient memcachedClient;


    @RequestMapping("/getAndset")
    public void getAndset() {

        //设置缓存   过期时间单位为秒, 0表示永远不过期
        OperationFuture<Boolean> flag = memcachedClient.set("zhongguo", 5, "shanghai");

        Object data;
        data= memcachedClient.get("zhongguo");
        System.out.println("第一次取出数据:"+data);  //shanghai

        try {
            //让  key  过期
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        data = memcachedClient.get("zhongguo");
        System.out.println("第二次取出数据:"+data); //null

    }

    /**
     * Memcached add 命令用于将 value(数据值) 存储在指定的 key(键) 中。
     *
     * 如果 add 的 key 已经存在,则不会更新数据(过期的 key 会更新),之前的值将仍然保持相同,并且您将获得响应 NOT_STORED。
     */
    @RequestMapping("/add")
    public void add() {

        //设置缓存   过期时间单位为秒, 0表示永远不过期
        OperationFuture<Boolean> flag = memcachedClient.set("zhongguo", 5, "shanghai");

        System.out.println(flag);

        Object data;
        data= memcachedClient.get("zhongguo");
        System.out.println("第一次取出数据:"+data);

        memcachedClient.add("zhongguo",5, "2"); // 进行 Add操作

        data = memcachedClient.get("zhongguo");
        System.out.println("第二次取出数据:"+data);// 之前的值未过期,新值不生效

        try {
            //让  key  过期
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        memcachedClient.add("zhongguo",5, "2"); // 再进行 Add操作

        System.out.println("第三次取出数据:"+memcachedClient.get("zhongguo"));  //取出值为2

    }

    /**
     * replace 命令用于替换已存在的 key(键) 的 value(数据值)。
     *
     * 如果 key 不存在,则替换失败,并且您将获得响应 NOT_STORED。
     */
    @RequestMapping("/replace")
    public void replace() {

        //设置缓存   过期时间单位为秒, 0表示永远不过期
        OperationFuture<Boolean> flag = memcachedClient.set("zhongguo", 5, "shanghai");

        System.out.println(flag);

        Object data;
        data= memcachedClient.get("zhongguo");
        System.out.println("第一次取出数据:"+data);

        memcachedClient.replace("zhongguo",5, "2"); // 进行 replace 操作

        data = memcachedClient.get("zhongguo");
        System.out.println("第二次取出数据:"+data);// 值更新为 2

        try {
            //让  key  过期
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        memcachedClient.replace("zhongguo",5, "shanghai"); // 再进行 replace 操作

        System.out.println("第三次取出数据:"+memcachedClient.get("zhongguo"));  //key 为空, 取出结果为 null

    }

    /**
     * append 命令用于向已存在 key(键) 的 value(数据值) 后面追加数据
     */
    @RequestMapping("/append")
    public void append() {

        //设置缓存   过期时间单位为秒, 0表示永远不过期
        OperationFuture<Boolean> flag = memcachedClient.set("zhongguo", 5, "shanghai");

        System.out.println(flag);

        Object data;
        data= memcachedClient.get("zhongguo");
        System.out.println("第一次取出数据:"+data);

        memcachedClient.append("zhongguo","2"); // 进行 append 操作

        data = memcachedClient.get("zhongguo");
        System.out.println("第二次取出数据:"+data);// 值更新为 shanghai2

        try {
            //让  key  过期
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        memcachedClient.append("zhongguo","shanghai"); // 再进行 append 操作

        System.out.println("第三次取出数据:"+memcachedClient.get("zhongguo"));  //key 为空, 取出结果为 null

    }


    /**
     * prepend  命令用于向已存在 key(键) 的 value(数据值) 后面追加数据
     */
    @RequestMapping("/prepend")
    public void prepend() {

        //设置缓存   过期时间单位为秒, 0表示永远不过期
        OperationFuture<Boolean> flag = memcachedClient.set("zhongguo", 5, "shanghai");

        System.out.println(flag);

        Object data;
        data= memcachedClient.get("zhongguo");
        System.out.println("第一次取出数据:"+data);

        memcachedClient.prepend("zhongguo","2"); // 进行 prepend 操作

        data = memcachedClient.get("zhongguo");
        System.out.println("第二次取出数据:"+data);// 值更新为 2shanghai

        try {
            //让  key  过期
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        memcachedClient.prepend("zhongguo","shanghai"); // 再进行 prepend 操作

        System.out.println("第三次取出数据:"+memcachedClient.get("zhongguo"));  //key 为空, 取出结果为 null

    }


    /**
     * CAS(Check-And-Set 或 Compare-And-Swap) 命令用于执行一个"检查并设置"的操作
     *
     * 它仅在当前客户端最后一次取值后,该key 对应的值没有被其他客户端修改的情况下, 才能够将值写入。
     *
     * 检查是通过cas_token参数进行的, 这个参数是Memcach指定给已经存在的元素的一个唯一的64位值。
     */
    @RequestMapping("/cas")
    public void cas() {

        //设置缓存   过期时间单位为秒, 0表示永远不过期
        OperationFuture<Boolean> flag = memcachedClient.set("zhongguo", 5, "shanghai");

        System.out.println(flag);

        Object data;
        data= memcachedClient.get("zhongguo");
        System.out.println("第一次取出数据:"+data);

        //通过 gets 获取 CAS token (令牌)
        CASValue casValue = memcachedClient.gets("zhongguo");

        System.out.println("CAS token --  : " + casValue);  //{CasValue 20/shanghai}

        //使用cas方法来更新数据
        CASResponse casResponse = memcachedClient.cas("zhongguo",casValue.getCas(),5,"2");

        System.out.println("CAS 响应信息 :"+casResponse);// OK


        data = memcachedClient.get("zhongguo");
        System.out.println("第二次取出数据:"+data);  // 2


        try {
            //让  key  过期
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //通过 gets 获取 CAS token (令牌)
        CASValue casValue2 = memcachedClient.gets("zhongguo");

        System.out.println("CAS token --  : " + casValue2);  //null

        //使用cas方法来更新数据
        CASResponse casResponse2 = memcachedClient.cas("zhongguo",casValue.getCas(),5,"2");

        System.out.println("CAS 响应信息 :"+casResponse2);// NOT_FOUND

        data = memcachedClient.get("zhongguo");
        System.out.println("第三次取出数据:"+data);  // null

    }

    /**
     * delete 命令用于删除已存在的 key(键)。
     */
    @RequestMapping("/delete")
    public void delete() {

        //设置缓存   过期时间单位为秒, 0表示永远不过期
        OperationFuture<Boolean> flag = memcachedClient.set("zhongguo", 5, "shanghai");

        System.out.println(flag);

        Object data;
        data = memcachedClient.get("zhongguo");
        System.out.println("第一次取出数据:" + data); //shanghai

        OperationFuture<Boolean> zhongguo = memcachedClient.delete("zhongguo");

        System.out.println(zhongguo.getStatus()); //{OperationStatus success=true:  DELETED}

        data = memcachedClient.get("zhongguo");
        System.out.println("第二次取出数据:" + data); //null

        //没有 key 的情况下
        OperationFuture<Boolean> zhongguo2 = memcachedClient.delete("zhongguo");

        System.out.println(zhongguo2.getStatus()); //{OperationStatus success=false:  NOT_FOUND}

    }

    /**
     * Memcached incr 与 decr 命令用于对已存在的 key(键) 的数字值进行自增或自减操作。
     *
     * incr 与 decr 命令操作的数据必须是十进制的32位无符号整数。
     *
     * 如果 key 不存在返回 NOT_FOUND,如果键的值不为数字,则返回 CLIENT_ERROR,其他错误返回 ERROR。
     */
    @RequestMapping("/incrOrDecr")
    public void incrOrDecr() {

        //设置缓存   过期时间单位为秒, 0表示永远不过期
        OperationFuture<Boolean> flag = memcachedClient.set("zhongguo", 5, "1000");

        System.out.println(flag);

        Object data;
        data = memcachedClient.get("zhongguo");
        System.out.println("第一次取出数据:" + data); // 1000

        long incr = memcachedClient.incr("zhongguo", 100);

        System.out.println("取出 incr 之后的数据:" + memcachedClient.get("zhongguo")); // 1100

        long decr = memcachedClient.decr("zhongguo", 100);

        System.out.println("取出 decr 之后的数据:" + memcachedClient.get("zhongguo")); // 1000


        memcachedClient.append("zhongguo","shanghai");

        System.out.println("取出 append 之后的数据:" + memcachedClient.get("zhongguo")); //  1000shanghai


        //ERROR net.spy.memcached.protocol.ascii.MutatorOperationImpl:  Error:  CLIENT_ERROR cannot increment or decrement non-numeric value
        long incr2 = memcachedClient.incr("zhongguo", 100);
        System.out.println("取出 incr 之后的数据:" + memcachedClient.get("zhongguo")); //  1000shanghai


        //ERROR net.spy.memcached.protocol.ascii.MutatorOperationImpl:  Error:  CLIENT_ERROR cannot increment or decrement non-numeric value
        long decr2 = memcachedClient.decr("zhongguo", 100);
        System.out.println("取出 decr 之后的数据:" + memcachedClient.get("zhongguo"));//  1000shanghai


        try {
            //让  key  过期
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //key 过期后 未报错  但返回 的都是 -1

        long incr3 = memcachedClient.incr("zhongguo", 100);

        System.out.println(incr3); //  -1
        System.out.println("取出 incr 之后的数据:" + memcachedClient.get("zhongguo")); //  null


        long decr3 = memcachedClient.decr("zhongguo", 100);

        System.out.println(decr3); //  -1
        System.out.println("取出 decr 之后的数据:" + memcachedClient.get("zhongguo"));//  null

    }

}

pom:

<?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.5.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.infinitePossibilities</groupId>
    <artifactId>memcached</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>memcached</name>
    <description>memcached</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>net.spy</groupId>
            <artifactId>spymemcached</artifactId>
            <version>2.12.3</version>
        </dependency>
    </dependencies>

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

</project>

Githup: https://github.com/lifan12589/infinite-possibilities/tree/master/ac-memcached

原文地址:https://www.cnblogs.com/lifan12589/p/14832333.html