大型网站架构设计-memcache AP丨与分布式

2014-11-21 13:23:14     33 人阅读    

    memcache客户端与服务端通过构建在TCP协议之上的memcache协议4来进行通信,协议 支持两种数据的传递,这两种数据分别为文本行和非结构化数据。文本行主要用来承载客户端的命令及服务端的响应,而非结构化数据则主要用于客户端和服务端数据的传递。由于非结构 化数据采用字节流的形式在客户端和服务端之间进行传输和存储,因此使用方式非常灵活,缓存数据存储几乎没有任何限制,并且服务端也不需要关心存储的具体内容及字节序。

memcache协议支持通过如下几种方式来读取/写入/失效数据:
•           set将数据保存到缓存服务器,如果缓存服务器存在同样的key,则替换之;
•           add将数据新增到缓存服务器,如果缓存服务器存在同样的key,则新增失败;
•           replace将数据替换缓存服务器中相同的key,如果缓存服务器不存在同样的key,则替 换失败;
•           append将数据追加到已经存在的数据后面;
•           prepend将数据追加到已经存在的数据前面;
•           cas提供对变量的cas操作,它将保证在进行数据更新之前,数据没有被其他人更改;
•           get从缓存服务器获取数据;
•           incr对计数器进行增量操作;
•           decr对计数器进行减量操作;
•           delete将缓存服务器上的数据删除。

memcache官方提供的Memcached-Java-Client5工具包含了对memcache协议的Java封装,

使用它可以比较方便地与缓存服务端进行通信,它的初始化方式如下:

public static void init(){

String[] servers = {

"192.168.136.135:11211"

};

SockIOPool pool = SockIOPool.getlcstacce();

pool. setServers (servers);//设置月服务器

pool. setFailover (true);//容错

pool. setlnitConn (10) ; //设置初始连接数

pool. setMinConn (5 ) ; //设置最小连接数

pool. setMaxConn (25) ; //设置最大连接数

pool. setMaintSleep (30) ; / /设置连接池维护线程的睡眠时间

pool. setNagle (false);//设置是否使用 Nagle 算法

pool. setSocketTO (3000);//设置socket的读取等待超时时间

pool. setAliveCheck (true);//设置连接心跳监测开关

pool. setHashingAlg( SockIOPool.      丑);//设置 Hash 算法

pool.initialize ();

}

通过SockIOPool可以设置与后端缓存服务器的一系列参数,如服务器地址、是否采用容


 

错、初始连接数、最大连接数、最小连接数、线程睡眠时间、是否使用Nagle算法、socket的 读取等待超时时间、是否心跳检测、Hash算法,等等。

使用Memcached-Java-ClientAPI设置缓存的值:

MemCachedClient memCachedClient = new MemCachedClient(); memCachedClient.add(nkeyn, 1); memCachedClient.set("key", 2); memCachedClient.replace("key", 3);

通过add()方法新增缓存,如果缓存服务器存在同样的key则返回false;而通过set()方法 将数据保存到缓存服务器,缓存服务器如果存在同样的key则将其替换。replace()方法可以用 来替换服务器中相同的key的值,如果缓存服务器不存在这样的key则返回false

使用Memcached-Java-ClientAPI获取缓存的值:

Object value = memCachedClient.get("key");

String[] keys = {Mkey1",Mkey2M};

Map<String, Objectvalues = memCachedClient.getMulti(keys);

通过get()方法,可以从服务器获取该key对应的数据;而使用getMulti()方法,则可以一次

性从缓存服务器获取一组数据。

对缓存的值进行appendprepend操作:

memCachedClient.set("key-name", "chenkangxian"); memCachedClient.prepend("key-name", "hello"); memCachedClient.append("key-name", "!");

通过prepend()方法,可以在对应key的值前面增加前缀;而通过append()方法,则可以在

对应的key的值后面追加后缀。

对缓存的数据进行cas6操作:

MemcachedItem item = memCachedClient.gets("key"); memCachedClient.cas("key", (Integer)item.getValue() + 1,

item.getCasUnique());

通过gets()方法获得key对应的值和值的版本号,它们包含在MemcachedItem对象中;然 后使用cas()方法对该值进行修改,当key对应的版本号与通过gets取到的版本号(即 item.getCasUnique())相同时,则将key对应的值修改为item.getValue() + 1,这样可以防止并发

修改所带来的问题。 6 memcacheCAS有点类似JavaCAS (compare and set)操作,关于JavaCAS操作,第4章会有详细介绍。

对缓存的数据进行增量与减量操作

memCachedClient.incr(nkeyn,1);

memCachedClient.decr(nkeyn,1);

使用incr()方法可以对key对应的值进行增量操作,而使用decr()方法则可以对key对应的 值进行减量操作。

memcache本身并不是一种分布式的缓存系统,它的分布式是由访问它的客户端来实现的。 一种比较简单的实现方式是根据缓存的key来进行Hash当后端有#台缓存服务器时,访问的 服务器为hash(key)%N这样可以将前端的请求均衡地映射到后端的缓存服务器,如图2-1所示。 但这样也会导致一个问题,一旦后端某台缓存服务器宕机,或者是由于集群压力过大,需要新增缓存服务器时,大部分的key将会重新分布。对于高并发系统来说,这可能会演变成一场灾 难,所有的请求将如洪水般疯狂地涌向后端的数据库服务器,而数据库服务器的不可用,将会导致整个应用的不可用,形成所谓的雪崩效应”。

 

使用consistent Hash算法能够在一定程度上改善上述问题。该算法早在1997年就在论文

Consistent hashing and random trees7中被提出,它能够在移除/添加一台缓存服务器时,尽可能小地改变已存在的key映射关系,避免大量key的重新映射。

consistent Hash的原理是这样的,它将Hash函数的值域空间组织成一个圆环,假设Hash 函数的值域空间为0232-1 (Hash值是一个32位的无符号整型),整个空间按照顺时针方向 进行组织,然后对相应的服务器节点进行Hash,将它们映射到Hash环上,假设有4台服务器, 分别为node1node2node3node4,它们在环上的位置如图2-2所示。

 

接下来使用相同的Hash函数,计算出对应的keyHash值在环上对应的位置。根据 consistentHash算法,按照顺时针方向,分布在node1node2之间的key它们的访问请求会 被定位到node2node2node4之间的key访问请求会被定为到node4以此类推。

假设有新节点node5增加进来时,假设它被Hashnode2node4之间,如图2-3所示。 那么受影响的只有node2node5之间的key它们将被重新映射到node5而其他key的映射

关系将不会发生改变,这样便避免了大量key的重新映射。

当然,上面描绘的只是一种理想的情况,各个节点在环上分布得十分均匀。正常情况下,当节点数量较少时,节点的分布可能十分不均匀,从而导致数据访问的倾斜,大量的key被映 射到同一台服务器上。为了避免这种情况的出现,可以引入虚拟节点机制,对每一个服务器节点都计算多个Hash值,每一个Hash值都对应环上一个节点的位置,该节点称为虚拟节点,而 key的映射方式不变,只是多了一步从虚拟节点再映射到真实节点的过程。这样,如果虚拟节 [1]

点的数量足够多,即使只有很少的实际节点,也能够使key分布得相对均衡。


 


原文地址:http://www.itmmd.com/201411/202.html
该文章由 萌萌的IT人 整理发布,转载须标明出处。

大型网站架构设计-memcached分布式 session 管理   上一篇
下一篇  大型网站架构设计-分布式缓存memcache简介及安装

精彩回复
发表评论
姓名:       

《程序员app》专门为程序员量身定做!