Memcached
==================================================================================
http://blog.sina.com.cn/s/blog_493a845501013ei0.html 分布式缓存
1.简介
****************************************************
缓存是一种常驻于内存的内存数据库,内存的读取速度远远快于程序在磁盘读取数据的速度。
将经常访问的数据放到内存上面这样可以提高访问数据的速度,同时可以降低磁盘或数据库的压力。
Memcache优势:
1.实现分布式缓存(支持热部署),通过hashcode根据缓存服务器ip智能分配将数据缓存到服务器上。
2.实现最近最少访问的数据优先被移除缓存。
3.快速找到适配的存储空间,避免内存的浪费。
4.使用键值对存储数据,方便读取、修改等缓存的管理。
5.socket通信,缓存服务器和应用服务器分离。等等
参数说明
------------------------------------------------------------------------------------------------------
memcached -d -m 10 -u root -l 192.168.5.80 -p 11222 -c 256 -P /tmp/memcached.pid
参数说明:
-d选项是启动一个守护进程
-m是分配给Memcache使用的内存数量,单位是MB,我这里是10MB
-u是运行Memcache的用户,我这里是root
-l是监听的服务器IP地址
-p是设置Memcache监听的端口,最好是1024以上的端口
-c选项是最大运行的并发连接数,默认是1024,按照你服务器的负载量来设定
-P是设置保存Memcache的pid文件
2.失效策略
****************************************************
memcached的缓存失效策略是LRU(最近最少使用)加上到期失效策略。
当向memcached存储数据时,你可能会设置一个过期时间,可以是永久也可以是一段时间,
但是如果一旦给memcached分配的内存使用完毕,则首先会替换掉已失效的数据,其次是最近最少使用的数据。
*memcached的过期时间并不能随便设置,有一个最大时限就是30天,若超过30天后,存储时返回true,但是在取数据的时候取不到。(在取数据的时候才去做验证,看看数据是否失效)
*通常session的失效算法是“当前时间>=session最后访问时间+失效时间”
*只有在cache值update的时候(set/add/replace)才会更新,仅仅get操作是不会更新这个时间的! 对于失效的cache,严格来说,只有在get操作的时候,才真正回收(可供新的cache使用)
过期时间有两种格式:
1. 相对时间:多长时间,给出过期的时间长度
2. 绝对时间:到期时间,给出过期的最后期限
服务端的处理
时间处理源代码【memcached.c】如下:
#define REALTIME_MAXDELTA 60*60*24*30 // 定义30天的秒数
static rel_time_t realtime(const time_t exptime) {
if (exptime == 0) return 0; //设置为0,永久有效{逃不出LRU}
if (exptime > REALTIME_MAXDELTA) { // 超过30天,是绝对时间
if (exptime <= process_started) // 小于进程启动日期
return (rel_time_t)1; //
return (rel_time_t)(exptime - process_started); // 返回进程启动之后的时间差
} else { // 不超过30天,是相对时间
return (rel_time_t)(exptime + current_time); // exptime + (tvsec - process_started)
}
}
相对时间时,返回的值是:服务器当前时间之后的exptime - process_started秒
绝对时间时,返回的值是:服务器当前时间之后的(exptime -服务器当前时间) - process_started秒
可以看到,如果Client和Server时间不一致,使用绝对时间很容易导致缓存过期。
所以使用相对时间是比较安全的做法。
memcache设置的缓存时间如果超过30天,需要使用 time()+时间;设置为0,永久有效,但是如果内存不够用就LRU了
3.内存管理
****************************************************
Slab Allocatoion分配机制:
Slab Allocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块,已完全解决内存碎片问题。Slab Allocation的原理相当简单。将分配的内存分割成各种尺寸的块(chucnk),并把尺寸相同的块分成组(chucnk的集合)如图:
Slab Allocation 的主要术语
Page :分配给Slab 的内存空间,默认是1MB。分配给Slab 之后根据slab 的大小切分成chunk.
Chunk : 用于缓存记录的内存空间。
Slab Class:特定大小的chunk 的组。
在启动时指定“-f”参数,能在某种程度上控制内存组之间的大小差异。默认大小为1.25。
4.分布式
****************************************************
Memcached不互通信的分布式:memcached尽管是“分布式”缓存服务器,但服务器端并没有分布式功能。各个memcached不会互相通信以共享信息。他的分布式主要是通过客户端实现的。
http://blog.youkuaiyun.com/u010558660/article/details/52767218 一致性hash算法与Java实现
==================================================================================
Java MemcachedClient
出处: http://hitery.iteye.com/blog/734639
2,incr,decr,counter方法没有过期时间参数
这使得用memcached无法保持那种需要具有实效的计数器。
某些场合,譬如记录用户的错误登录次数,我需要隔断时间就清零,danga限制我这么干。
当然,我们可以用set先存储一个Long值来绕过这个限制,但这会同时带来另一个问题:默认的MemcachedClient在序列化基本数据类型时用了特殊的格式
(NativeHandler,带来的问题就是存储的数据只能由java client来解析),因此数字在memcached服务器中无法使用incr,decr命令。
看了源码,我发现memcachedclient有个属性primitiveAsString可以控制这个序列化选择。万幸,把它设为true,我绕过去了。
官方网站推荐用spymemcached作为客户端。
-------------------------------------------------------------------------------------------------------------------
问题
MemcachedClient--Builderbuilder=new XMemcachedClientBuilder(AddrUtil.getAddresses("ip:11211"));
builder.setConnectionPoolSize(5);
MemcachedClient mClient = builder.build();
mClient.setPrimitiveAsString(true);
mClient.set("key", 5, 6); //参数:key,expDate,value
mClient.incr("key", 2); //参数:key,增值
//如果不设置mClient.setPrimitiveAsString(true);会报异常
//Exception: cannot increment or decrement non-numeric value