springBoot 集成 memcached

一、 memcached 介绍

1.1 简介

       Memcached 是一个高性能的分布式内存对象缓存系统 ,用于动态 Web 应用以减轻数据库负载。它通过内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。

       Memcached 基于一个存储键/值对的 HashMap,在内存中对任意的数据(比如字符串、对象等)使用 key-value 存储,数据可以来自数据库调用、API 调用,或者页面渲染的结果。其守护进程(daemon )是用 C 写的,但是客户端可以用任何语言来编写,并通过 Memcached 协议与守护进程通信。

1.2 特性

        1、本质上就是一个内存 key-value 缓存

        2、协议简单,使用的是基于文本行的协议

        3、不支持数据的持久化,服务器关闭之后数据全部丢失

        4、Memcached 简洁而强大,便于快速开发,上手较为容易

        5、互不通信的 Memcached 之间具有分布特征 ,没有安全机制

1.3 优点

        Memcached 可以利用多核优势,单实例吞吐量极高,可以达到几十万 QPS(取决于 key/value 的字节大小以及服务器硬件性能,日常环境中 QPS 高峰大约在 4-6w 左右)。适用于最大程度扛量。

       支持直接配置为 session handle

1.4 缺点

        1、只支持简单的 key-value 数据结构,不像 Redis 可以支持丰富的数据类型

        2、无法进行持久化,数据不能备份,只能用于缓存使用,且重启后数据全部丢失

        3、无法进行数据同步,不能将 Memcached 中的数据迁移到其他 Memcached 实例中

        4、Memcached 内存分配采用 Slab Allocation 机制管理内存,value 大小分布差异较大时会造成内存利用率降低,并引发低利用率时依然出现踢出等问题。需要用户注重 value 设计。

1.5 实现原理

       Memcached 处理的原理是每一个 key/valuekey 会通过一个 hash 表转换成 hash key,便于查找对比以及尽可能的做到散列。同时 Memcached 用的是一个二级散列,通过一个 hash 表来维护。

       Memcached 有两个核心组件:服务端(server)和客户端(client)。

       在一个 Memcached 组件查询中,client 先通过 key hash 值来确定 key server 端的位置,当 server 端确定后,客户端就会发送一个查询请求给对应的 server 端。让它来查找出确切数据,因为这之间没有交互以及多播协议,因此 Memcached 带给网络的影响最小。

1.6 适用场景

        1、利用 Memcached 可以缓存 session 数据 、临时数据以减少对他们的数据库写操作

        2、缓存一些很小但是被频繁访问的文件

        3、经常被读取并且实时性要求不强可以等到自动过期的数据。

        4、变化频繁,查询频繁,但是不需要入库的场景读多写少的场景中用于页面缓存

1.7 不适用场景

        1、缓存的数据需要持久化

        2、key 的长度大于 250 字符

        3、变化频繁且需要入库

        4、过大的数据不适宜放在 Memcached

1.8 与 Redis 比较相同点

        1、都是基于内存的数据库系统,最大存储量是根据机器内存大小而定

        2、都有不同的过期策略,分布式数据的备份可以设置一主多从,也可以一主一从(Master-Slave

        3、都支持 key-value 数据缓存

1.9 与 Redis 比较不同点

        1、数据持久化支持:Redis 虽然是基于内存的存储系统,但是它本身是支持内存数据的持久化的,而且提供两种主要的持久化策略:RDB 快照和 AOF 日志。而 Memcached 是不支持数据持久化操作的。

        2、灾难恢复:Memcached 挂掉后,数据不可恢复。 Redis 数据丢失后可以通过 AOF 恢复

        3、IO 方面:Redis 使用的单线程 IO 复用网络模型,  而 Memcached 多线程非阻塞 IO 复用模型

        4、数据支持类型:Redis 支持 key-value 数据类型,还有 listsetzsethash 等数据结构,而 Memcached 只支持 key-value 数据

        5、Value 值大小不同:Redis 最大可以达到 512mbMemcached 只有 1mb

        6、数据一致性:Memcached 提供了 CAS 命令,可以保证多个并发访问操作同一份数据的一致性问题。Redis 没有提供 CAS 命令,并不能保证这点,不过 Redis 提供了事务的功能,可以保证一串命令的原子性,中间不会被任何操作打断。

二、对 java 的支持

        可以使用三种不同的 Java 客户端来支持 Memcached, 分别为 Memcached-java-client、Spymemcached 和 XMemcached。我们分别介绍下这三种客户端。

2.1 Memcached-java-client 客户端

        Memcached-java-client 客户端推出较早,应用最广泛,阻塞式 IO,稳定性高,高并发下性能低。较早推出的 Memcached JAVA 客户端 API,应用广泛,运行比较稳定,使用阻塞 IO,不支持 CAS 操作,已停止更新。

2.2 Spymemcached 客户端

        Spymemcached 客户端时基于 JDK Concurrent NIO,存取速度高,并发性能高,支持 CAS 操作,已停止更新。

2.3 XMemcached 客户端

        XMemcached 客户端同样基于 NIO 实现,减少了线程创建和切换的开销,这一点在高并发下特别明显,一直更新。推荐使用。

三、下载安装

        在菜鸟教程里面下载相应的版本,我安装的是 1.4.4 版本,具体如何安装以及修改参数都在上面的网页教程里面有相应的记录。

        这里我需要说明的是:当执行

 c:\memcached\memcached.exe -d start 

        之后,这个 memcached 进程就会启动,关机重启电脑也会自动启动这个进程。不用再刻意的去配置开机启动。

四、使用 Memcached-java-client

4.1 添加 maven 依赖

   <dependency>
       <groupId>commons-pool</groupId>
       <artifactId>commons-pool</artifactId>
    </dependency>
    <dependency>
       <groupId>com.whalin</groupId>
       <artifactId>Memcached-Java-Client</artifactId>
       <version>3.0.2</version>
    </dependency>

4.2 修改 application.properties 配置信息

# memcached config
memcache.servers=127.0.0.1:11211
memcache.failover=true
memcache.initConn=100
memcache.minConn=20
memcache.maxConn=1000
memcache.maintSleep=50
memcache.nagel=false
memcache.socketTO=3000
memcache.aliveCheck=true

4.3 编写 memcache 配置类

@Configuration
public class MemcacheConfig {

    @Value("${memcache.servers}")
    private String[] servers;
    @Value("${memcache.failover}")
    private boolean failover;
    @Value("${memcache.initConn}")
    private int initConn;
    @Value("${memcache.minConn}")
    private int minConn;
    @Value("${memcache.maxConn}")
    private int maxConn;
    @Value("${memcache.maintSleep}")
    private int maintSleep;
    @Value("${memcache.nagel}")
    private boolean nagel;
    @Value("${memcache.socketTO}")
    private int socketTO;
    @Value("${memcache.aliveCheck}")
    private boolean aliveCheck;
    
    @Bean
    public SockIOPool sockIOPool () {
        SockIOPool pool = SockIOPool.getInstance();
        pool.setServers(servers);
        pool.setFailover(failover);
        pool.setInitConn(initConn);
        pool.setMinConn(minConn);
        pool.setMaxConn(maxConn);
        pool.setMaintSleep(maintSleep);
        pool.setNagle(nagel);
        pool.setSocketTO(socketTO);
        pool.setAliveCheck(aliveCheck);
        pool.initialize();
        return pool;
    }
 
    @Bean
    @ConditionalOnBean(SockIOPool.class)
    public MemCachedClient memCachedClient(){
        return new MemCachedClient();
    }
	
}

4.4 编写测试类

@RestController
public class MemcacheController {

	@Autowired
	private MemCachedClient memCachedClient;
		
	@RequestMapping("/memcacheIndex")
	public String memcacheIndex() throws InterruptedException {
		// 放入缓存
		boolean flag = memCachedClient.set("a", 1);
		System.out.println(flag);
		// 取出缓存
		Object a = memCachedClient.get("a");
		System.out.println(a);
		// 3s后过期
		memCachedClient.set("b", "2", new Date(3000));
		Object b = memCachedClient.get("b");
		System.out.println(b);
 
		Thread.sleep(3000);
		b = memCachedClient.get("b");
                System.out.println(a);
		System.out.println(b);
		return "aaaa";
	}
}

4.5 测试

        启动程序,输入 http://localhost:8080/memcacheIndex,输出结果如图所示:

五、使用 SpyMemcached 方式

5.1 添加 maven 依赖

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

5.2 修改 application.properties 配置信息

memcache.ip=127.0.0.1
memcache.port=11211

5.3 编写 SpyMemcacheConfig 配置类

@Configuration
public class SpyMemcacheConfig implements CommandLineRunner{

        @Value("${memcache.ip}")
        private String ip;
        @Value("${memcache.port}")
        private int port;
    
        private MemcachedClient client = null;
    
	@Override
	public void run(String... args) throws Exception {
		try {
			client = new MemcachedClient(new InetSocketAddress(ip,port));
		} catch (IOException e) {
		}
	}
	
	public MemcachedClient getClient() {
        return client;
    }
}

5.4 编写测试类

@RestController
public class SpyMemcacheController {
	
	@Autowired
	private SpyMemcacheConfig spyMemcacheConfig;
	
	@RequestMapping("/spyMemcacheIndex")
	public String spyMemcacheIndex() throws InterruptedException {
		/*这个过期时间单位是秒,最大值是60*60*24*30*/
		spyMemcacheConfig.getClient().set("spyMemcachedKey",1,"张三");
		System.out.println("基于spyMemcached实现,现在的值为 "+spyMemcacheConfig.getClient().get("spyMemcachedKey"));
		Thread.sleep(2000);
		System.out.println("1秒后缓存内容清除,现在的值为: "+spyMemcacheConfig.getClient().get("spyMemcachedKey"));
		return "aaaaa";
	}
}

5.5 测试

       启动程序,输入 http://localhost:8080/spyMemcacheIndex,输出结果如图所示:

六、使用 XMemcached 方式

6.1 添加 maven 依赖

<dependency>
	<groupId>com.googlecode.xmemcached</groupId>
	<artifactId>xmemcached</artifactId>
	<version>2.4.5</version>
</dependency>

6.2 修改 application.properties 配置信息

# memcached服务器集群(格式为host:port,多个服务器之间用空格隔开)
memcached.server=127.0.0.1:11211 10.86.54122:11211 

# 接口操作的默认超时时间,可以被接口覆盖
memcached.opTimeout=3000 

# 池子大小
memcached.poolSize=10 

# 是否开启失败模式,默认为false
memcached.failureMode=false  

# 是否使用memcached缓存
memcached.enabled=true 

6.3 编写 XMemcacheConfig 配置类

@Configuration
public class XMemcacheConfig {
	
	@Value("${memcached.server}")
	private String server;
	
	@Value("${memcached.opTimeout}")
	private Integer opTimeout;
	
	@Value("${memcached.poolSize}")
	private Integer poolSize;
	
	@Value("${memcached.failureMode}")
	private boolean failureMode;
	
	@Value("${memcached.enabled}")
	private boolean enabled;
	
	@Bean(name = "memcachedClientBuilder")
	public MemcachedClientBuilder getBuilder() {
		MemcachedClientBuilder memcachedClientBuilder = new XMemcachedClientBuilder(server);
		// 内部采用一致性哈希算法
		memcachedClientBuilder.setSessionLocator(new KetamaMemcachedSessionLocator());
		// 操作的超时时间
		memcachedClientBuilder.setOpTimeout(opTimeout);
		// 采用二进制传输协议(默认为文本协议)
		memcachedClientBuilder.setCommandFactory(new BinaryCommandFactory());
		// 设置连接池的大小
		memcachedClientBuilder.setConnectionPoolSize(poolSize);
		// 是否开起失败模式
		memcachedClientBuilder.setFailureMode(failureMode);
		return memcachedClientBuilder;
	}
	/**
	 * 由Builder创建memcachedClient对象,并注入spring容器中
	 * @param memcachedClientBuilder
	 * @return
	 */
	@Bean(name = "memcachedClient")
	public MemcachedClient getClient(@Qualifier("memcachedClientBuilder") MemcachedClientBuilder memcachedClientBuilder) {
		MemcachedClient client = null;
		try {
			client =  memcachedClientBuilder.build();
		} catch(Exception e) {
			e.printStackTrace();
		}
		return client;
	}
}

6.4 编写测试类

@RestController
public class XMemcacheController {

	@Autowired
	private MemcachedClient memcachedClient;
	
	@RequestMapping("/XMemcacheIndex")
	public String XMemcacheIndex() throws InterruptedException {
		try {
			//新增操作
			memcachedClient.set("XMemcacheKeyOne",0,"张三");
			System.out.println((String)memcachedClient.get("XMemcacheKeyOne"));
			
			//删除操作
			memcachedClient.delete("XMemcacheKeyOne");
			System.out.println((String)memcachedClient.get("XMemcacheKeyOne"));
			
			//设置存活时间
			memcachedClient.set("XMemcacheKeyTwo",1,"李四");
			Thread.sleep(2000);
			System.out.println((String)memcachedClient.get("XMemcacheKeyTwo"));
			
			//更新操作
			memcachedClient.set("XMemcacheKeyThree",0,"王五");
			System.out.println((String)memcachedClient.get("XMemcacheKeyThree"));
			memcachedClient.set("XMemcacheKeyThree",0,"王五他儿子");
			System.out.println((String)memcachedClient.get("XMemcacheKeyThree"));		
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "xMemcacheIndex";
	}
}

6.5 测试

        启动程序,输入 http://localhost:8080/XMemcacheIndex,输出结果如下所示:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

快乐的小三菊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值