Memcache

Memcache的概述

memcache就是一个数据库、但是数据存在内存中。常用来做缓存服务器、将从数据库查询的数据缓存起来,减少数据库查询、加快查询速度。

使用场景:缓存服务器
适合存储的数据:
① 访问比较频繁的数据,安全性差的数据,丢失无所谓的数据。
② 数据更新,比较频繁的数据,比如用户的在线状态。
③ 数据的单个键值不能太大,不要超过1Mb数据。

为什么会有Memcache和memcached两种名称?

Memcache是这个项目的名称,而memcached是它服务端的主程序文件名。

MemCache的工作流程

先检查客户端的请求数据是否在memcached中,如有,直接把请求数据返回,不再对数据库进行任何操作;如果请求的数据不在memcached中,就去查数据库,把从数据库中获取的数据返回给客户端,同时把数据缓存一份到memcached中(memcached客户端不负责,需要程序明确实现);每次更新数据库的同时更新memcached中的数据,保证一致性;当分配给memcached内存空间用完之后,会使用LRU(Least Recently Used,最近最少使用)策略加上到期失效策略,失效数据首先被替换,然后再替换掉最近未使用的数据

Memcache的分布式缓存

特别澄清一个问题,MemCache虽然被称为"分布式缓存",但是MemCache本身完全不具备分布式的功能,MemCache集群之间不会相互通信(与之形成对比的,比如JBoss Cache,某台服务器有缓存数据更新时,会通知集群中其他机器更新缓存或清除缓存数据),所谓的”分布式”,完全依赖于客户端程序的实现。

MemCache一次写缓存的流程:

1、应用程序输入需要写缓存的数据

2、API将Key输入路由算法模块,路由算法根据Key和MemCache集群服务器列表得到一台服务器编号

3、由服务器编号得到MemCache及其的ip地址和端口号

4、API调用通信模块和指定编号的服务器通信,将数据写入该服务器,完成一次分布式缓存的写操作

读缓存和写缓存一样,只要使用相同的路由算法和服务器列表,只要应用程序查询的是相同的Key,MemCache客户端总是访问相同的客户端去读取数据,只要服务器中还缓存着该数据,就能保证缓存命中。

这种MemCache集群的方式也是从分区容错性的方面考虑的,假如Node2宕机了,那么Node2上面存储的数据都不可用了,此时由于集群中Node0和Node1还存在,下一次请求Node2中存储的Key值的时候,肯定是没有命中的,这时先从数据库中拿到要缓存的数据,然后路由算法模块根据Key值在Node0和Node1中选取一个节点,把对应的数据放进去,这样下一次就又可以走缓存了,这种集群的做法很好,但是缺点是成本比较大。

一致性哈希(hash)的原理

首先求出memcached服务器(节点)的哈希值, 并将其配置到0~2^32的圆(continuum)上。 然后用同样的方法求出存储数据的键的哈希值,并映射到圆上。然后从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个服务器上。 如果超过2^32仍然找不到服务器,就会保存到第一台memcached服务器上。

Java支持的Memcached客户端有三种

1.官方提供的基于传统阻塞io由Greg Whalin维护的客户端:memcached client for java

2.Dustin Salling实现的基于java nio的Spymemcached

3.XMemcached

三种API比较

1.memcached client for java

较早推出的memcached Java客户端的API,应用广泛,运行比较稳定,其官网地址为:GitHub - gwhalin/Memcached-Java-Client: Information about this project lives on the wiki

2.spymemcached

支持异步,单线程的memcached客户端,用到了java1.5版本的concurrent和nio,存取速度会高于前者,但是稳定性不好,测试中常报timeOut等相关异常,其官网地址为:http://code.google.com/p/spymemcached/

3.xmemcached

Memcached同样是基于java nio的客户端,java nio相比于传统阻塞io模型来说,有效率高(特别在高并发下)和资源耗费相对较少的优点。传统阻塞IO为了提高效率,需要创建一定数量的连接形成连接池,而nio仅需要一个连接即可(当然,nio也是可以做池化处理),相对来说减少了线程创建和切换的开销,这一点在高并发下特别明显。因此XMemcached与Spymemcached在性能都非常优秀,在某些方面(存储的数据比较小的情况下)Xmemcached比Spymemcached的表现更为优秀,具体可以看这个Java Memcached Clients Benchmark。Xmemcached的官网地址为:http://code.google.com/p/xmemcached/

示例代码如下:

示例程序

memcached client for java

<!-- https://mvnrepository.com/artifact/com.whalin/Memcached-Java-Client -->
<dependency>
    <groupId>com.whalin</groupId>
    <artifactId>Memcached-Java-Client</artifactId>
    <version>3.0.2</version>
</dependency>
import com.whalin.MemCached.MemCachedClient;
import com.whalin.MemCached.SockIOPool;

public class CacheTest {

    public static void main(String[] args) {
        /**
         * 初始化SockIOPool,管理memcached的连接池
         */
        String[] servers={"192.168.1.105:10000"};
        SockIOPool pool=SockIOPool.getInstance();
        pool.setServers(servers);
        pool.setFailover(true);
        pool.setInitConn(10);
        pool.setMinConn(5);
        pool.setMaxConn(250);
        pool.setMaintSleep(30);
        pool.setNagle(false);
        pool.setSocketTO(3000);
        pool.setAliveCheck(true);
        pool.initialize();

        /**
         * 建立MemcachedClient实例
         */
        MemCachedClient memCachedClient=new MemCachedClient();
        for(int i=0;i<1000;i++){
            /**
             * 将对象加入到memcached缓存
             */
            boolean success=memCachedClient.set(""+i,"Hello!");
            /**
             * 从memcached缓存中按key值取对象
             */
            String result=(String)memCachedClient.get(""+i);
            System.out.println(String.format("set( %d ): %s", i, success));
            System.out.println(String.format("get( %d ): %s", i, result));
        }
    }
}

Spymemcached

<!--Spymemcached依赖-->
<!-- https://mvnrepository.com/artifact/com.google.code.simple-spring-memcached/spymemcached -->
<dependency>
    <groupId>com.google.code.simple-spring-memcached</groupId>
    <artifactId>spymemcached</artifactId>
    <version>2.8.4</version>
</dependency>
import net.spy.memcached.MemcachedClient;
import java.net.InetSocketAddress;
import java.util.concurrent.Future;

public class TestSpyMemcache {

    public static void main(String[] args){
        //保存对象
        try{
            /*建立MemcachedClient实例,并指定memcached服务的IP地址和端口号*/
            MemcachedClient mc = new MemcachedClient(new InetSocketAddress("10.11.15.222", 10000));
            Future<Boolean> b = null;
            /* 将key值,过期时间(秒)和要缓存的对象set到memcached中 */
            b = mc.set("neea:testDaF:ksIdno", 900, "someObject");
            if (b.get().booleanValue() == true) {
                mc.shutdown();
            }
        }catch (Exception e){
            e.printStackTrace();
        }

        // 取得对象
        try {
            //建立MemcachedClient 实例,并指定memcached服务的IP地址和端口号
            MemcachedClient mc = new MemcachedClient(new InetSocketAddress("192.168.1.105", 10000));
            //按照key值从memcached中查找缓存,不存在则返回null
            Object b = mc.get("neea:testDaF:ksIdno");
            System.out.println(b.toString());
            mc.shutdown();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Xmemcached

<!--xmemcached依赖-->
<!-- https://mvnrepository.com/artifact/com.googlecode.xmemcached/xmemcached -->
<dependency>
    <groupId>com.googlecode.xmemcached</groupId>
    <artifactId>xmemcached</artifactId>
    <version>2.4.6</version>
</dependency>
import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.MemcachedClientBuilder;
import net.rubyeye.xmemcached.XMemcachedClientBuilder;
import net.rubyeye.xmemcached.utils.AddrUtil;

public class TestXMemcache {

    public static void main(String[] args) {
        MemcachedClientBuilder builder = new XMemcachedClientBuilder(
                AddrUtil.getAddresses("192.168.1.105:10000"));
        MemcachedClient memcachedClient;
        try {
            memcachedClient = builder.build();
            memcachedClient.set("hello", 0, "Hello,xmemcached");
            String value = memcachedClient.get("hello");
            System.out.println("hello=" + value);
            memcachedClient.delete("hello");
            value = memcachedClient.get("hello");
            System.out.println("hello=" + value);

            //关闭memcached客户端
            memcachedClient.shutdown();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Memcache安装与基本操作:Linux Memcached 安装 | 菜鸟教程

Memcache与Redis的区别和联系:十分钟学会memcache,比你想象的要简单_给我一杯拿铁的博客-CSDN博客_memcache

Java代码支持:MemCache超详细解读 - 五维思考 - 博客园

集群:JAVA MemCache 史无前例的详细讲解!看完包精通MEMCACHE! - 王大王 - 博客园

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值