发表于: 2019-11-24 23:35:08

1 1014


今天完成的事:
1、学习Memcached缓存。
首先就是理解Memcached、memcache、memcached三者的区别。
Memcached:指的是Memcached服务器,就是独立运行Memcached的后台服务器,用于缓存数据的容器。
且Memcached是一个高性能分布式的内存对象缓存系统,通过缓存数据库查询结果,减少访问数据库次数,减少负载压力,提高动态web应用的性能。
memcache、memcached:是Memcached的客户端,通过两者可以访问Memcached服务器,两者只有微小差异。memcached要多些守护进程的操作方法,性能更好些。
Memcached适合存储的数据:
(1)访问较为频繁的数据,安全性差的数据,丢失无所谓的数据。
(2)数据更新,比较繁琐的数据,比如用户的在线状态。

(3)数据的单个键值对不能太大,不要超过1MB的数据。


2、java连接Memcached服务。
首先下载memcached客户端,下载地址: http://static.runoob.com/download/memcached-win64-1.4.4-14.zip
因为1.4.5版本之前memcached可以作为一个服务器安装,安装方便,所以这里下载64位系统1.4.4版本。
只需要将下载的压缩包解压,而后cd到文件夹下“memcached.exe -d install”直接安装即可。
使用“memcached.exe -h”可以查看相关参数,因为默认IP范围太大,尝试进行修改。

修改配置需如下所示,

打开注册表,找到对对应的注册表,修改ImagePath参数,这里改为本机 127.0.0.1:11314 端口,内存128MB。

使用start、stop命令进行memcached服务的启闭。

可以在任务管理器中查看memcached服务的运行。

如果需要卸载的话,按如下即可。


java连接Memcached服务,有三种方式,这里选用SpyMemcached方式。


首先添加spymemcached的jar包,查看的都是说下载jar包导入,搜了好久发现有个说是可以使用谷歌的一个依赖,于是maven中心库中搜索,分别尝试了两种jar包,
两个jar包都可以单独使用。但是测试类中导入的类是一样的。

本来以为两个jar包会有冲突,结果并没有,在依赖树里,两个jar包并列。这里使用的net.spy的jar包。
 
上面说了修改了IP以及端口,正确才能正常存储,使用其他的都会报错异常。也算是验证了修改有效。 


3、memcached命令。
set、add、replace三个命令返回值为boolean,set是设置数据,相当于add加replace,add是添加数据,key不能相同,replace是修改数据,key必须是存在的,修改其value。
append、prepend命令都是给存在的key追加value数据,只是位置不同,一前一后。

其中set命令,相关参数如下,主要是key、exptime、value。


命令中主要是CAS命令需要重点说下,CAS主要是为了分布式环境下更新的一致性问题,每次更新都需要指定更新的key的cas_token,可以使用gets命令得到,注意是命令后有“s”。CAS仅在当前客户端最后一次取值后,该key对应的值没有被其他客户端修改的情况下,才能将值写入,检查则是通过cas_token参数进行,这个参数是memcached指定给已存在的元素的一个唯一的64位值。
cas_token也就是key的版本标识,每当value被修改时,其key的cas_token就会被更新,加一,保证当前只有一个客户端对memcached进行操作,没有操作成功,就说明有其他客户端在操作,需要利用gets命令获得当前的cas_token,然后继续操作。
相应命令代码如下:
import net.spy.memcached.CASResponse;
import net.spy.memcached.CASValue;
import net.spy.memcached.MemcachedClient;
import org.apache.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
public class MemcacheTest {
    private static Logger logger = Logger.getLogger(MemcacheTest.class);
    MemcachedClient mcc;
    @Before
    public void before(){
        try {
            // 本地连接 Memcached 服务
            mcc = new MemcachedClient(new InetSocketAddress("127.0.0.1", 11314));
            System.out.println("本地连接 Memcached 服务:成功!");
        } catch (IOException e) {
            // 不要使用捕捉自带的打印信息,容易锁死空间
//            e.printStackTrace();
            // 使用logger打印日志
            logger.error("连接失败!出现异常:" + e);
            // 或者直接 e.getMessage() 输出,但是e.getMessage()信息可能不全
            System.out.println("连接失败!出现异常:" + e.getMessage());
        }
    }

    @After
    public void after(){
        // 关闭连接
        mcc.shutdown();
        System.out.println("关闭连接");
    }
    // 设置数据
    @Test
    public void set(){
        try {
            // 存储数据
            Future fo = mcc.set("aaa", 900, "bbb");
            // 查看存储状态
            System.out.println("存储状态:" + fo.get());
            // 输出值
            System.out.println("输出值 - " + mcc.get("aaa"));
        } catch (InterruptedException e) {
            logger.error("出现异常:" + e);
            System.out.println("出现异常:" + e.getMessage());
        } catch (ExecutionException e) {
            logger.error("出现异常:" + e);
            System.out.println("出现异常:" + e.getMessage());
        }
    }
    // 添加数据,key不能相同
    @Test
    public void add(){
        try {
            // 存储数据
            Future fo = mcc.set("aaa", 900, "bbb");
            // 查看存储状态
            System.out.println("存储状态:" + fo.get());
            // 输出值
            System.out.println("输出值 - " + mcc.get("aaa"));
            // 添加原有key
            fo = mcc.add("aaa", 900, "memcached");
            // 打印状态,false
            System.out.println("添加原有key,存储状态:" + fo.get());
            // 添加新key
            fo = mcc.add("111", 900, "222");
            // 打印状态,true
            System.out.println("添加新key,存储状态:" + fo.get());
            // 输出
            System.out.println("新key输出值 - " + mcc.get("111"));
        } catch (InterruptedException e) {
            logger.error("出现异常:" + e);
            System.out.println("出现异常:" + e.getMessage());
        } catch (ExecutionException e) {
            logger.error("出现异常:" + e);
            System.out.println("出现异常:" + e.getMessage());
        }
    }
    // 修改数据,key需存在相同key名称
    @Test
    public void replace(){
        try {
            // 存储数据
            Future fo = mcc.set("aaa", 900, "bbb");
            // 查看存储状态
            System.out.println("存储状态:" + fo.get());
            // 输出值
            System.out.println("输出值 - " + mcc.get("aaa"));
            // 原有key修改值
            fo = mcc.replace("aaa", 900, "666");
            // 输出 原有key修改值 方法后的状态,true
            System.out.println("添加原有key,存储状态:" + fo.get());
            // 获取键对应的值
            System.out.println("原有key输出值 - " + mcc.get("aaa"));
        } catch (InterruptedException e) {
            logger.error("出现异常:" + e);
            System.out.println("出现异常:" + e.getMessage());
        } catch (ExecutionException e) {
            logger.error("出现异常:" + e);
            System.out.println("出现异常:" + e.getMessage());
        }
    }
    // 对存在的key进行 后部 的数据添加操作
    @Test
    public void append(){
        try {
            // 存储数据
            Future fo = mcc.set("aaa", 900, "bbb");
            // 查看存储状态
            System.out.println("存储状态:" + fo.get());
            // 输出值
            System.out.println("输出值 - " + mcc.get("aaa"));
            // 对存在的key进行数据添加操作
            fo = mcc.append("aaa", " 222");
            // 输出状态
            System.out.println("存储状态:" + fo.get());
            // 获取键对应的值
            System.out.println("输出值 - " + mcc.get("aaa"));
        } catch (InterruptedException e) {
            logger.error("出现异常:" + e);
            System.out.println("出现异常:" + e.getMessage());
        } catch (ExecutionException e) {
            logger.error("出现异常:" + e);
            System.out.println("出现异常:" + e.getMessage());
        }
    }
    // 对存在的key进行 前部 的数据添加操作
    @Test
    public void prepend(){
        try {
            // 存储数据
            Future fo = mcc.set("aaa", 900, "bbb");
            // 查看存储状态
            System.out.println("存储状态:" + fo.get());
            // 输出值
            System.out.println("输出值 - " + mcc.get("aaa"));
            // 对存在的key进行数据添加操作
            fo = mcc.prepend("aaa", "222 ");
            // 输出执行 set 方法后的状态
            System.out.println("存储状态:" + fo.get());
            // 获取键对应的值
            System.out.println("输出值 - " + mcc.get("aaa"));
        } catch (InterruptedException e) {
            logger.error("出现异常:" + e);
            System.out.println("出现异常:" + e.getMessage());
        } catch (ExecutionException e) {
            logger.error("出现异常:" + e);
            System.out.println("出现异常:" + e.getMessage());
        }
    }
    // 对存在的key使用 cas方法 来更新数据
    @Test
    public void CAS(){
        try {
            // 存储数据
            Future fo = mcc.set("rrr", 900, "ccc");
            // 查看存储状态
            System.out.println("存储状态:" + fo.get());
            // 输出值
            System.out.println("输出值 - " + mcc.get("rrr"));
            // 通过 gets 方法获取 CAS token(令牌)
            CASValue casValue = mcc.gets("rrr");
            // 输出 CAS token(令牌) 值
            System.out.println("CAS token - " + casValue);
            // 输出 CAS token(令牌) 对应的 数字值
            System.out.println("CAS token 数字 - " + casValue.getCas());
            // 尝试使用cas方法来更新数据
            CASResponse casresp = mcc.cas("rrr", casValue.getCas(), 900, "333");
            // 输出 CAS 响应信息
            System.out.println("CAS响应信息 - " + casresp);
            // 输出值
            System.out.println("cas更新,输出值 - " + mcc.get("rrr"));
        } catch (InterruptedException e) {
            logger.error("出现异常:" + e);
            System.out.println("出现异常:" + e.getMessage());
        } catch (ExecutionException e) {
            logger.error("出现异常:" + e);
            System.out.println("出现异常:" + e.getMessage());
        }
    }
    // 对存在的key进行数据 删除 操作
    @Test
    public void delete(){
        try {
            // 存储数据
            Future fo = mcc.set("aaa", 900, "bbb");
            // 查看存储状态
            System.out.println("存储状态:" + fo.get());
            // 输出值
            System.out.println("输出值 - " + mcc.get("aaa"));
            // 对存在的key进行数据删除操作
            fo = mcc.delete("aaa");
            // 输出执行 delete 方法后的状态
            System.out.println("存储状态:" + fo.get());
            // 输出值
            System.out.println("输出值 - " + mcc.get("aaa"));
        } catch (InterruptedException e) {
            logger.error("出现异常:" + e);
            System.out.println("出现异常:" + e.getMessage());
        } catch (ExecutionException e) {
            logger.error("出现异常:" + e);
            System.out.println("出现异常:" + e.getMessage());
        }
    }
    // 对存储的数据,十进制的32位无符号整数,进行 自增、自减 操作
    @Test
    public void IncrDecr(){
        try {
            // 存储数据
            Future fo = mcc.set("number", 900, "11111");
            // 查看存储状态
            System.out.println("存储状态:" + fo.get());
            // 输出值
            System.out.println("输出值 - " + mcc.get("aaa"));
            // 自增并输出
            System.out.println("自增并输出 - " + mcc.incr("number", 111));
            // 自减并输出
            System.out.println("自减并输出 - " + mcc.decr("number", 112));
        } catch (InterruptedException e) {
            logger.error("出现异常:" + e);
            System.out.println("出现异常:" + e.getMessage());
        } catch (ExecutionException e) {
            logger.error("出现异常:" + e);
            System.out.println("出现异常:" + e.getMessage());
        }
    }
}
明天计划的事:
1、学习Redis缓存。
2、进行压测对比。
遇到的问题:
收获:
1、学习Memcached缓存。
首先就是理解Memcached、memcache、memcached三者的区别。
2、java连接Memcached服务,选用SpyMemcached方式。
下载memcached客户端,下载地址: http://static.runoob.com/download/memcached-win64-1.4.4-14.zip
3、学习了memcached命令。

返回列表 返回列表
评论

    分享到