• 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

  • 相关阅读:
    6.Ray-消息订阅器编写
    附录:2-Event Sourcing pattern (事件溯源设计模式)
    附录:1-Grain生命周期-译注
    4.Ray-Handler之CoreHandler编写
    Q&A-20180128
    TODO
    3.Ray-Event编写
    缓存技术内部交流_01_Ehcache3简介
    Spring AMQP 源码分析 04
    Spring AMQP 源码分析 03
  • 原文地址:https://www.cnblogs.com/lifan12589/p/14832333.html
Copyright © 2020-2023  润新知