Memcached使用点滴
使用Memcached进行对象缓存和内存优化
使用Memcached进行对象缓存和内存优化随着互联网的迅猛发展,数据量快速增长,对于网站的访问速度和稳定性提出了更高的要求。
而在这个背景下,Memcached作为一款轻量级的缓存系统,得到了越来越多的应用。
一、什么是MemcachedMemcached是一款高性能的分布式内存缓存系统,主要用于减轻数据库负载压力,提高网站访问速度和稳定性。
它采用了键值对的存储方式,在内存中对数据进行存储和访问。
这样可以有效地降低数据库的访问频率,提高网站的响应速度。
Memcached最初由Brad Fitzpatrick开发,是一个开源项目。
它运行在一个分布式的环境中,客户端通过TCP/IP协议连接到Memcached服务器,将数据存储在内存中,可以快速地读取数据。
二、为什么要使用Memcached在一个传统的web应用中,当一个用户请求一个页面时,通常需要连接到数据库中查询数据,然后渲染网页。
但是随着访问量的增加,数据库会遇到性能瓶颈,导致访问速度变慢。
而Memcached作为一个分布式缓存系统,可以有效地解决数据库访问频率过高的问题,减轻数据库的负担。
同时,由于Memcached是一款基于内存的缓存系统,访问速度非常快,能够提供快速的读取服务。
因此,在高并发的情况下,使用Memcached可以提高网站的响应速度,提供更好的用户体验。
三、如何使用Memcached使用Memcached非常简单,只需要在代码中添加一些缓存相关的代码即可。
下面以PHP为例,介绍如何在代码中使用Memcached。
1. 安装和启动Memcached首先需要安装Memcached,并启动Memcached服务。
sudo apt-get install memcached2. 使用PHP扩展在PHP代码中,可以使用PHP扩展来连接到Memcached服务器并进行相关的操作。
我们可以使用Memcached类来进行操作,示例如下:<?php// 创建一个Memcached对象$mem = new Memcached();// 添加Memcached服务器$mem->addServer("localhost", 11211);// 存储数据$mem->set("key", "value", 3600);// 获取数据$val = $mem->get("key");// 输出数据echo $val;>3. 使用缓存进行性能优化在实际使用中,需要根据具体的应用场景来选择合适的缓存策略。
Memcached安装使用
Memcached安装使用1.Memcached安装下载地址:/p/memcached/downloads/list1.1. 安装libevent# tar zxvf libevent-2.0.19-stable.tar.gz# cd libevent-2.0.19-stable# ./configure --prefix=/usr/local/libevent# make# make install1.2. 安装memcached# tar zxvf memcached-1.4.13.tar.gz# cd memcached-1.4.13# ./configure --with-libevent=/usr/local/libevent –-enable-threads --prefix=/usr/local/memcached# make# make install2.Memcached 运行2.1. 运行memcached# ./memcached -d -u root -m 1024 -P /opt/memcached/pid/memcached11211.pid –C -v2.2. 启动参数说明•启动方式:•-d 以守护程序(daemon)方式运行•-u root 指定用户,如果当前为root ,需要使用此参数指定用户•-P /tmp/a.pid 保存PID到指定文件•内存设置:•-m 1024 数据内存数量,不包含memcached本身占用,单位为MB •-M 内存不够时禁止LRU,报错•-n 48 初始chunk=key+suffix+value+32结构体,默认48字节•-f 1.25 增长因子,默认1.25•-L 启用大内存页,可以降低内存浪费,改进性能•连接设置:•-l 127.0.0.1 监听的IP地址,本机可以不设置此参数•-p 11211 TCP端口,默认为11211,可以不设置•-U 11211 UDP端口,默认为11211,0为关闭•并发设置:•-c 1024 最大并发连接数,默认1024,最好是200•-t 4 线程数,默认4。
Memcached 基本语法 记录
Memcached 基本语法 记录
set 指令:指令将value数值存储在指定的key中;
set key flags exptime bytes [noreply]
value
key:键值 key-value 结构中的 key,用于查找缓存值。
flags:可以包括键值对的整型参数,客户机用法它存储关于键值对的额外信息 。
bytes:在缓存中存储的字节数
noreply(可选): 该参数告诉服务器不需要返回数据
value:存储的值(始终位于其次行)(可挺直理解为key-value结构中的value)
STORED:保存胜利ቤተ መጻሕፍቲ ባይዱ输出。
NOT_STORED :在保存失败后输出。
get yx
STORED:保存胜利后输出。
ERROR:在保存失败后输出。
add 指令:
Memcached add 指令用于将 value(数据值) 存储在指定的 key(键) 中。假如 add 的 key 已经存在,则不会更新数据(过期的key 会更新),之前的值将仍然保持相同,并且您将获得响应 NOT_STORED。
add key flags exptime bytes [noreply]
value
key:键值 key-value 结构中的 key,用于查找缓存值。
flags:可以包括键值对的整型参数,客户机用法它存储关于键值对的额外信息 。
exptime:在缓存中保存键值对的时光长度(以秒为单位,0 表示永久)
exptime:在缓存中保存键值对的时光长度(以秒为单位,0 表示永久)
bytes:在缓存中存储的字节数
noreply(可选): 该参数告诉服务器不需要返回数据
网站大访问量缓存技术之memcache的安装和使用
网站大访问量缓存技术之memcache的安装和使用知识点:一、memcachemem 内存cache 缓存网页的静态化--》文件缓存。
memcache 内存来作为缓存。
管理内存中的数据。
大中型项目。
1。
作用:用来缓存数据。
数据库临时存储数据的地方,刷新或重启(关机)。
数据就没有了2 优势:数据写入内存,访问速度将加快。
3 memcache 的安装和配置。
memcached.exe 执行可以安装memcache.php_memcache.dll php的扩展库文件。
---》php5.n版本5.2+安装:1 检查以前是否装过memcache控制面板--》管理工具---》服务--》memcache选项。
(没有,没装过);2 安装:memcached.exe -d install3 启动:memcached.exe -d start注意:memcache 内存管理,在杀毒软件下,最好把保护功能暂时先停掉。
4 卸载:需要进服务当中先把mamcache停止掉。
memcached.exe -d unistall5 应用:mysql 3306默认。
memcache 11211 默认。
memcached.exe -d 【参数】installstartuninstallrestart 重启stop 停止memcache服务。
php---》memcache 配置1》php_memcache.dll 文件拷贝php/ext/php_memcache.dll2》php.ini文件:在extension 列表最后一行添加以下代码。
extension=php_memcache.dll --》启动memcache 扩展库。
需要重启apache.6 php使用memcache1>$mem = new Memcache; //实例化内存管理对象memcache的对象。
2>php连接memcache;$mem->connect("主机名称",端口号); 成功返回true 失败false3>memcache add("变量名称","值");$mem->add();4>从内存中取出数据:$mem->get(变量名称);mem 存储数据和数组没有问题。
memcache使用文档
Memcache使用指南一线天色天宇星辰概述Memcache 服务为您的应用程序提供了高性能的内存键值缓存,您可通过应用程序的多个实例访问该缓存。
Memcache 对于那些不需要数据库的永久性功能和事务功能的数据很有用,例如临时数据或从数据库复制到缓存以进行高速访问的数据。
Memcache API 与 Danga Interactive 开发的Memcached有类似的功能并兼容。
Memcache API 可通过以下方式让您提高应用程序的性能并减少数据库的负载:∙显著地减少数据库查询的次数。
∙减少使用率非常高的页面的数据库配额的使用。
∙缓存操作量巨大的查询和操作的结果。
∙让使用临时计数器成为可能。
通过使用 Memcache API,您可以为应用程序中的数据创建一致的缓存。
缓存可用于应用程序中的所有实例,而且数据只有通过内存压力(例如缓存中的数据过多)或开发人员设置的缓存政策才能清除。
可以在存储在缓存中的每个键-值对上设置缓存政策。
您可以清除所有缓存或针对每份数据设置缓存过期时间。
Client 类Memcache API 提供一个基于类的接口,以便与其他 Memcache API 兼容。
另请参阅提供相同功能的函数接口。
∙Client()∙实例方法:o set()o set_multi()o get()o get_multi()o delete()o delete_multi()o add()o add_multi()o replace()o replace_multi()o incr()o decr()o flush_all()o get_stats()∙class Client()∙与 Memcache 服务通信的客户端。
∙Client 实例有以下方法:∙set(key, value, time=0, min_compress_len=0)∙设置键的值,与先前缓存中的内容无关。
∙参数:∙key∙要设置的键。
MemcachedClient使用说明
MemcachedClient使⽤说明上⼀篇介绍了Memcached基本使⽤⽅法《》,下⾯介绍java如何操作memcached。
使⽤的是java_memcached-release_2.6.6。
⼀、使⽤⽅法新建项⽬,添加相关jar包:直接上代码了,注释写的很详细,不⽤多说了啊。
package ;import com.danga.MemCached.MemCachedClient;import com.danga.MemCached.SockIOPool;public class MemcachedDemo {public static void main(String[] args) {//memcached服务器String[] servers = {"127.0.0.1:11211","192.168.1.3:11211"};/*** 设置连接池可⽤cache服务器的权重,和server数组的位置⼀⼀对应*/Integer[] weights = {1,2};/*** 这个类⽤来创建管理客户端和服务器通讯连接池,客户端主要的⼯作包括数据通讯、服务器定位、hash码⽣成等都是由这个类完成的。
* 获得连接池的单态⽅法。
这个⽅法有⼀个重载⽅法getInstance( String poolName ),每个poolName只构造⼀个SockIOPool实例。
* 缺省构造的poolName是default。
*/SockIOPool pool = SockIOPool.getInstance();//设置memcached服务器pool.setServers(servers);//设置memcached服务器权重pool.setWeights(weights);//设置容错开关设置为TRUE,当当前socket不可⽤时,程序会⾃动查找可⽤连接并返回,否则返回NULL,默认状态是true,建议保持默认pool.setFailover( true );//设置开始时每个cache服务器的可⽤连接数pool.setInitConn( 10 );//设置每个服务器最少可⽤连接数pool.setMinConn( 5 );//设置每个服务器最⼤可⽤连接数pool.setMaxConn( 250 );/*** 设置连接池维护线程的睡眠时间* 设置为0,维护线程不启动* 维护线程主要通过log输出socket的运⾏状况,监测连接数⽬及空闲等待时间等参数以控制连接创建和关闭。
memcached 手册
memcached 手册Memcached是一个高性能的开源内存对象缓存系统,被广泛地应用于提升网站和应用程序性能。
该手册将介绍Memcached的基本概念、安装配置、常用命令以及最佳实践等关键内容,旨在帮助读者快速了解和使用Memcached。
一、Memcached概述Memcached可以看作是一个分布式的缓存系统,它将数据缓存在内存中,并提供了简单的键值对存取接口。
相比于传统的关系型数据库,Memcached具有更快的读写速度和更高的并发能力,因为它直接操作内存而避免了磁盘I/O。
此外,Memcached采用了多台服务器的分布式架构,能够提供横向扩展的能力。
二、安装与配置1.下载和安装:Memcached可以从官方网站或其他镜像站点下载安装包,并根据相应平台的指引进行安装。
安装完成后,可以通过运行"memcached"命令来启动Memcached服务。
2.配置文件:Memcached的默认配置文件是"memcached.conf",可以通过修改该文件中的参数来调整Memcached的行为。
主要的配置项包括监听端口、最大连接数、内存容量等。
三、常用命令1.存储数据:用"set"命令可以将键值对存入Memcached中,例如:"set key 0 3600 5"表示存储一个key为"key",值为"0",并设置过期时间为3600秒。
如果要存储的值超出了内存容量限制,旧的数据将会被替换。
2.获取数据:用"get"命令可以从Memcached中获取指定键对应的值,例如:"get key"可以获取到之前存储的值。
如果该键不存在,返回结果将是"END"。
3.删除数据:用"delete"命令可以从Memcached中删除指定键对应的值,例如:"delete key"可以删除之前存储的值。
memcache安装和使用
Memcache 的安装和使用安装:下载安装包:memcached-1.4.8.tar.gz(最新)libevent-1.4.9-stable.tar.gz(socket通信程序,它是memcached 所依赖的异步事件通知库) 上述包都是用c写的。
故在linux环境下安装,linux必须有c编译环境,目前都用gcc(最好系统自带,否则自己安装非常麻烦,特别耗时间)命令tar –xzf libevent-1.4.9-stable.tar.gzcd libevent-1.4.9-stable.tar.gz./configure –prefix=/usrmakemake install=============libevent 安装完毕====================tar –xzf memcached-1.4.8.tar.gzcd memcached-1.4.8.tar.gz./configure –prefix=/usrmakemake install=============memcache安装完毕==================Memcache 已经安装到usr/bin目录下启动/usr/bin memcached –d –m 128 –l 10.10.31.79 –p 11211 -u root-d 以守护(daemon)程序方式运行memcached-l 设置监听的ip地址,如果是本机,通常不设置-p 设置监听端口,默认为11211 通常不设置-m 设置内存大小单位M-u 指定用户。
当前用户为root时,可以指定用户。
(不能以root用户权限启动)-vv 用very vrebose模式启动,调试信息和错误输出到控制台还有很多命令可以用memcached –h 来查看测试telnet server port这里,我用的SecureCRT ,当然还有很多客户端工具,如PuTTy;Window 自带的cmd中的telnet 也可以,但是容易出现乱码问题,得设置编码格式。
simple-spring-memcached统一缓存的使用实例
simple-spring-memcached统一缓存的使用实例如何在一个中型的Java应用中使用Memcached缓存数据不是个简单的问题。
当某个缓存数据需要在多个系统间共享和失效时,必须要有统一的规划才能保证不出错。
经过各种实践,目前系统在使用Memcached缓存数据全部采用Simple-Spring-Memcached框架来完成,并统一规划各系统Spring和Cache key的配置。
下面对在使用过程中需要注意的点做一个详细说明:Cache整体规划目前我们系统中有两个不同的Memcached服务器:1session memcached服务器:主要存储用户的session2app memcached服务器: 主要用于缓存应用数据由于应用所有的缓存数据都放在app缓存上,为避免各应用的缓存数据出现冲突,必须规划好它们的命名空间。
所幸Simple-Spring-Memcached支持namespace的概念,因此对各应用的namespace前缀规定如下:应用namespace前缀goodscenter goodscentertrade tradeuic uic这个namespace在生成key时,将放在最前面,稍后会有例子详述。
同一个应用中存在许多需要缓存的对象,因此约定namespace前缀之后再加上缓存对象的类名。
例子如下:应用缓存对象完整的namespace 最终生成的keytrade TcRate (id为42) trade:TcRate trade:TcRate:12goodscenter GoodsDo(id为42) goodscenter:GoodsDo goodscenter:GoodsDo:12key的生成规则Simple-Spring-Memcached提供的针对单个对象的注解接口提供了两种key生成方式,详情见此文3AssignCache类注解通过assignKey指定cache的key4SingleCache类注解通过ParameterValueKeyProvider注解指定生成key的方法对于第一种只要求必须保证key不与其它的冲突,且namesapce符合规则。
memcached的使用
memcached的使⽤ 1. 下载memcached客户端⽂件把下载⽂件放在⽂件⽬录下2. 安装 memcached命令: c:/memcached/memcached.exe -d install3. 启动 memcachedc:/memcached/memcached.exe -d start4. 连接到 memcachedtelnet localhost 112115:客户端使⽤的基本命令启动/结束memcached -d -m 10 -u root -l 127.0.0.1 -p 11200 -c 256 -P /tmp/memcached.pid-d 选项是启动⼀个守护进程-m 是分配给Memcache使⽤的内存数量,单位是MB,这⾥是10MB-u 是运⾏Memcache的⽤户,这⾥是root-l 是监听的服务器IP地址,如果有多个地址的话,这⾥指定了服务器的IP地址127.0.0.1-p 是设置Memcache监听的端⼝,这⾥设置了12000,最好是1024以上的端⼝-c 选项是最⼤运⾏的并发连接数,默认是1024,这⾥设置了256,按照你服务器的负载量来设定-P 是设置保存Memcache的pid⽂件kill `cat /tmp/memcached.pid` 关闭memcached6:在项⽬中使⽤(与Spring集成)获取Memcached API 地址:创建接⼝MemcachedClient1import java.util.Collection;2import java.util.Map;3import java.util.concurrent.TimeoutException;45/**6 * 提供通⽤的memcached访问接⼝7*/8public interface MemcachedClient {9/**10 * 不管数据存在不存在都会将⽬前设置的数据存储的memcached11 *12 * @param key13 * 不要超过250字节14 * @param exp15 * 以秒为单位,如果超过30天的值,将会⽤unix timestamp来制定截⽌有效时间16 * @param value17 * @return18 * @throws TimeoutException19 * @throws InterruptedException20 * @throws MemcachedClientException21*/22boolean set(String key, int exp, Object value) throws TimeoutException,23 InterruptedException, MemcachedClientException;2425/**26 * 不管数据存在不存在都会将⽬前设置的数据存储的memcached,⾃⾏制定超时时间27 *28 * @see #set(String, int, Object)29 * @param key30 * @param exp31 * @param value32 * @param timeout33 * @return34 * @throws TimeoutException35 * @throws InterruptedException36 * @throws MemcachedClientException37*/38boolean set(String key, int exp, Object value, long timeout)39throws TimeoutException, InterruptedException,4142/**43 * 不管数据存在不存在都会将⽬前设置的数据存储的memcached,但不等待返回确认44 *45 * @see #set(String, int, Object)46 * @param key47 * @param exp48 * @param value49 * @throws InterruptedException50 * @throws MemcachedClientException51*/52void setWithNoReply(String key, int exp, Object value)53throws InterruptedException, MemcachedClientException;5455/**56 * 只有数据不存在时进⾏添加57 *58 * @param key59 * 不要超过250字节60 * @param exp61 * 以秒为单位,如果超过30天的值,将会⽤unix timestamp来制定截⽌有效时间62 * @param value63 * @return64 * @throws TimeoutException65 * @throws InterruptedException66 * @throws MemcachedClientException67*/68boolean add(String key, int exp, Object value) throws TimeoutException,69 InterruptedException, MemcachedClientException;7071/**72 * 只有数据不存在时进⾏添加73 *74 * @param key75 * @param exp76 * 以秒为单位,如果超过30天的值,将会⽤unix timestamp来制定截⽌有效时间77 * @param value78 * @param timeout79 * 1/1000秒为单位,在制定的时间段内没有响应就抛出TimeoutException80 * @return81 * @throws TimeoutException82 * @throws InterruptedException83 * @throws MemcachedClientException84*/85boolean add(String key, int exp, Object value, long timeout)86throws TimeoutException, InterruptedException,87 MemcachedClientException;8889/**90 * 只有数据不存在时进⾏添加,不需要返回具体的确认信息,⼤多数情况下可以⽤此⽅法来提升效率,毕竟我们对Memcached的理解是假设数据不是持久的91 *92 * @param key93 * @param exp94 * @param value95 * @throws InterruptedException96 * @throws MemcachedClientException97*/98void addWithNoReply(String key, int exp, Object value)99throws InterruptedException, MemcachedClientException;100101/**102 * 只有数据存在才进⾏覆盖103 *104 * @param key105 * @param exp106 * @param value107 * @return108 * @throws TimeoutException109 * @throws InterruptedException110 * @throws MemcachedClientException111*/112boolean replace(String key, int exp, Object value) throws TimeoutException,113 InterruptedException, MemcachedClientException;114115/**116 * 只有数据存在才进⾏覆盖117 *118 * @param key119 * @param exp120 * @param value121 * @param timeout122 * @return125 * @throws MemcachedClientException126*/127boolean replace(String key, int exp, Object value, long timeout)128throws TimeoutException, InterruptedException,129 MemcachedClientException;130131/**132 * 只有数据存在才进⾏覆盖,不等返回确认133 *134 * @param key135 * @param exp136 * @param value137 * @throws InterruptedException138 * @throws MemcachedClientException139*/140void replaceWithNoReply(String key, int exp, Object value)141throws InterruptedException, MemcachedClientException; 142143/**144 * 追加到当前数据的后⾯145 *146 * @param key147 * @param value148 * @return149 * @throws TimeoutException150 * @throws InterruptedException151 * @throws MemcachedClientException152*/153boolean append(String key, Object value) throws TimeoutException, 154 InterruptedException, MemcachedClientException;155156/**157 * 追加到当前数据的后⾯158 *159 * @param key160 * @param value161 * @param timeout162 * @return163 * @throws TimeoutException164 * @throws InterruptedException165 * @throws MemcachedClientException166*/167boolean append(String key, Object value, long timeout)168throws TimeoutException, InterruptedException,169 MemcachedClientException;170171/**172 * 追加到当前数据的后⾯,不等待响应173 *174 * @param key175 * @param value176 * @throws InterruptedException177 * @throws MemcachedClientException178*/179void appendWithNoReply(String key, Object value)180throws InterruptedException, MemcachedClientException; 181182/**183 * 追加到当前数据的前⾯184 *185 * @param key186 * @param value187 * @return188 * @throws TimeoutException189 * @throws InterruptedException190 * @throws MemcachedClientException191*/192boolean prepend(String key, Object value) throws TimeoutException, 193 InterruptedException, MemcachedClientException;194195/**196 * 追加到当前数据的前⾯197 *198 * @param key199 * @param value200 * @param timeout201 * @return202 * @throws TimeoutException203 * @throws InterruptedException204 * @throws MemcachedClientException205*/206boolean prepend(String key, Object value, long timeout)209210/**211 * 追加到当前数据的前⾯,不等待返回212 *213 * @param key214 * @param value215 * @throws InterruptedException216 * @throws MemcachedClientException217*/218void prependWithNoReply(String key, Object value)219throws InterruptedException, MemcachedClientException;220221long incr(String key, long delta, long initValue) throws TimeoutException,222 InterruptedException, MemcachedClientException;223224long incr(String key, long delta, long initValue, long timeout)225throws TimeoutException, InterruptedException,226 MemcachedClientException;227228void incrWithNoReply(String key, long delta) throws InterruptedException,229 MemcachedClientException;230231long decr(String key, long delta, long initValue) throws TimeoutException,232 InterruptedException, MemcachedClientException;233234long decr(String key, long delta, long initValue, long timeout)235throws TimeoutException, InterruptedException,236 MemcachedClientException;237238void decrWithNoReply(String key, long delta) throws InterruptedException,239 MemcachedClientException;240241boolean delete(String key) throws TimeoutException, InterruptedException,242 MemcachedClientException;243244boolean delete(String key, long opTimeout) throws TimeoutException,245 InterruptedException, MemcachedClientException;246247boolean delete(String key, long cas, long opTimeout)248throws TimeoutException, InterruptedException,249 MemcachedClientException;250251void deleteWithNoReply(String key) throws InterruptedException,252 MemcachedClientException;253254 <T> T get(String key) throws TimeoutException, InterruptedException,255 MemcachedClientException;256257 <T> T get(String key, long timeout) throws TimeoutException,258 InterruptedException, MemcachedClientException;259260 <T> Map<String, T> get(Collection<String> keyCollections)261throws TimeoutException, InterruptedException,262 MemcachedClientException;263264 <T> Map<String, T> get(Collection<String> keyCollections, long timeout)265throws TimeoutException, InterruptedException,266 MemcachedClientException;267268 <T> GetsResponse<T> gets(String key) throws TimeoutException,269 InterruptedException, MemcachedClientException;270271 <T> GetsResponse<T> gets(String key, long timeout) throws TimeoutException, 272 InterruptedException, MemcachedClientException;273274 <T> Map<String, GetsResponse<T>> gets(Collection<String> keyCollections) 275throws TimeoutException, InterruptedException,276 MemcachedClientException;277278 <T> Map<String, GetsResponse<T>> gets(Collection<String> keyCollections, 279long timeout) throws TimeoutException, InterruptedException,280 MemcachedClientException;281282283284boolean isEnabled();285 }创建接⼝实现类MemcachedClientWrapper1package .jszg.cache;3import java.util.Collection;4import java.util.HashMap;5import java.util.Map;6import java.util.Set;7import java.util.concurrent.TimeoutException;89import net.rubyeye.xmemcached.exception.MemcachedException;1011public class MemcachedClientWrapper implements MemcachedClient {12private net.rubyeye.xmemcached.MemcachedClient client;13private boolean enabled = false;1415public MemcachedClientWrapper() {16super();17 }1819public void setMemcachedClient(net.rubyeye.xmemcached.MemcachedClient client) {20this.client = client;21 }2223public net.rubyeye.xmemcached.MemcachedClient getXMemcachedClient() {24return client;25 }2627 @Override28public boolean set(String key, int exp, Object value) throws TimeoutException, InterruptedException, 29 MemcachedClientException {30try {31return client.set(key, exp, value);32 } catch (MemcachedException e) {33throw new MemcachedClientException(e);34 }35 }3637 @Override38public boolean set(String key, int exp, Object value, long timeout) throws TimeoutException,39 InterruptedException, MemcachedClientException {40try {41return client.set(key, exp, value, timeout);42 } catch (MemcachedException e) {43throw new MemcachedClientException(e);44 }45 }4647 @Override48public void setWithNoReply(String key, int exp, Object value) throws InterruptedException,49 MemcachedClientException {50try {51 client.setWithNoReply(key, exp, value);52 } catch (MemcachedException e) {53throw new MemcachedClientException(e);54 }55 }5657 @Override58public boolean add(String key, int exp, Object value) throws TimeoutException, InterruptedException, 59 MemcachedClientException {60try {61return client.add(key, exp, value);62 } catch (MemcachedException e) {63throw new MemcachedClientException(e);64 }65 }6667 @Override68public boolean add(String key, int exp, Object value, long timeout) throws TimeoutException,69 InterruptedException, MemcachedClientException {70try {71return client.add(key, exp, value, timeout);72 } catch (MemcachedException e) {73throw new MemcachedClientException(e);74 }75 }7677 @Override78public void addWithNoReply(String key, int exp, Object value) throws InterruptedException,79 MemcachedClientException {80try {81 client.addWithNoReply(key, exp, value);82 } catch (MemcachedException e) {83throw new MemcachedClientException(e);84 }85 }87 @Override88public boolean replace(String key, int exp, Object value) throws TimeoutException, InterruptedException,89 MemcachedClientException {90try {91return client.replace(key, exp, value);92 } catch (MemcachedException e) {93throw new MemcachedClientException(e);94 }95 }9697 @Override98public boolean replace(String key, int exp, Object value, long timeout) throws TimeoutException,99 InterruptedException, MemcachedClientException {100try {101return client.replace(key, exp, value, timeout);102 } catch (MemcachedException e) {103throw new MemcachedClientException(e);104 }105 }106107 @Override108public void replaceWithNoReply(String key, int exp, Object value) throws InterruptedException,109 MemcachedClientException {110try {111 client.replaceWithNoReply(key, exp, value);112 } catch (MemcachedException e) {113throw new MemcachedClientException(e);114 }115 }116117 @Override118public boolean append(String key, Object value) throws TimeoutException, InterruptedException,119 MemcachedClientException {120try {121return client.append(key, value);122 } catch (MemcachedException e) {123throw new MemcachedClientException(e);124 }125 }126127 @Override128public boolean append(String key, Object value, long timeout) throws TimeoutException, InterruptedException,129 MemcachedClientException {130try {131return client.append(key, value, timeout);132 } catch (MemcachedException e) {133throw new MemcachedClientException(e);134 }135 }136137 @Override138public void appendWithNoReply(String key, Object value) throws InterruptedException, MemcachedClientException { 139try {140 client.appendWithNoReply(key, value);141 } catch (MemcachedException e) {142throw new MemcachedClientException(e);143 }144 }145146 @Override147public boolean prepend(String key, Object value) throws TimeoutException, InterruptedException,148 MemcachedClientException {149try {150return client.prepend(key, value);151 } catch (MemcachedException e) {152throw new MemcachedClientException(e);153 }154 }155156 @Override157public boolean prepend(String key, Object value, long timeout) throws TimeoutException, InterruptedException,158 MemcachedClientException {159try {160return client.prepend(key, value, timeout);161 } catch (MemcachedException e) {162throw new MemcachedClientException(e);163 }164 }165166 @Override167public void prependWithNoReply(String key, Object value) throws InterruptedException, MemcachedClientException { 168try {169 client.prependWithNoReply(key, value);171throw new MemcachedClientException(e);172 }173 }174175 @Override176public long incr(String key, long delta, long initValue) throws TimeoutException, InterruptedException,177 MemcachedClientException {178try {179return client.incr(key, delta, initValue);180 } catch (MemcachedException e) {181throw new MemcachedClientException(e);182 }183 }184185 @Override186public long incr(String key, long delta, long initValue, long timeout) throws TimeoutException,187 InterruptedException, MemcachedClientException {188try {189return client.incr(key, delta, initValue, timeout);190 } catch (MemcachedException e) {191throw new MemcachedClientException(e);192 }193 }194195 @Override196public void incrWithNoReply(String key, long delta) throws InterruptedException, MemcachedClientException { 197try {198 client.incrWithNoReply(key, delta);199 } catch (MemcachedException e) {200throw new MemcachedClientException(e);201 }202 }203204 @Override205public long decr(String key, long delta, long initValue) throws TimeoutException, InterruptedException,206 MemcachedClientException {207try {208return client.decr(key, delta, initValue);209 } catch (MemcachedException e) {210throw new MemcachedClientException(e);211 }212 }213214 @Override215public long decr(String key, long delta, long initValue, long timeout) throws TimeoutException,216 InterruptedException, MemcachedClientException {217try {218return client.decr(key, delta, initValue, timeout);219 } catch (MemcachedException e) {220throw new MemcachedClientException(e);221 }222 }223224 @Override225public void decrWithNoReply(String key, long delta) throws InterruptedException, MemcachedClientException { 226try {227 client.decrWithNoReply(key, delta);228 } catch (MemcachedException e) {229throw new MemcachedClientException(e);230 }231 }232233 @Override234public boolean delete(String key) throws TimeoutException, InterruptedException, MemcachedClientException { 235try {236return client.delete(key);237 } catch (MemcachedException e) {238throw new MemcachedClientException(e);239 }240 }241242 @Override243public boolean delete(String key, long opTimeout) throws TimeoutException, InterruptedException,244 MemcachedClientException {245try {246return client.delete(key, opTimeout);247 } catch (MemcachedException e) {248throw new MemcachedClientException(e);249 }250 }251252 @Override253public boolean delete(String key, long cas, long opTimeout) throws TimeoutException, InterruptedException,255try {256return client.delete(key, cas, opTimeout);257 } catch (MemcachedException e) {258throw new MemcachedClientException(e);259 }260 }261262 @Override263public void deleteWithNoReply(String key) throws InterruptedException, MemcachedClientException {264try {265 client.deleteWithNoReply(key);266 } catch (MemcachedException e) {267throw new MemcachedClientException(e);268 }269 }270271 @SuppressWarnings("unchecked")272 @Override273public <T> T get(String key) throws TimeoutException, InterruptedException, MemcachedClientException { 274try {275return (T)client.get(key);276 } catch (MemcachedException e) {277throw new MemcachedClientException(e);278 }279 }280281 @SuppressWarnings("unchecked")282 @Override283public <T> T get(String key, long timeout) throws TimeoutException, InterruptedException,284 MemcachedClientException {285try {286return (T)client.get(key, timeout);287 } catch (MemcachedException e) {288throw new MemcachedClientException(e);289 }290 }291292 @Override293public <T> Map<String, T> get(Collection<String> keyCollections) throws TimeoutException,294 InterruptedException, MemcachedClientException {295try {296return client.get(keyCollections);297 } catch (MemcachedException e) {298throw new MemcachedClientException(e);299 }300 }301302 @Override303public <T> Map<String, T> get(Collection<String> keyCollections, long timeout) throws TimeoutException, 304 InterruptedException, MemcachedClientException {305try {306return client.get(keyCollections, timeout);307 } catch (MemcachedException e) {308throw new MemcachedClientException(e);309 }310 }311312 @SuppressWarnings("unchecked")313 @Override314public <T> GetsResponse<T> gets(String key) throws TimeoutException, InterruptedException,315 MemcachedClientException {316try {317return new GetsResponse<T>((net.rubyeye.xmemcached.GetsResponse<T>) client.gets(key));318 } catch (MemcachedException e) {319throw new MemcachedClientException(e);320 }321 }322323 @SuppressWarnings("unchecked")324 @Override325public <T> GetsResponse<T> gets(String key, long timeout) throws TimeoutException, InterruptedException, 326 MemcachedClientException {327try {328return new GetsResponse<T>((net.rubyeye.xmemcached.GetsResponse<T>) client.gets(key, timeout)); 329 } catch (MemcachedException e) {330throw new MemcachedClientException(e);331 }332 }333334 @Override335public <T> Map<String, GetsResponse<T>> gets(Collection<String> keyCollections) throws TimeoutException, 336 InterruptedException, MemcachedClientException {339 Map<String, net.rubyeye.xmemcached.GetsResponse<T>> tmps = client.gets(keyCollections);340if (tmps != null) {341 Set<String> keys = tmps.keySet();342for (String key : keys) {343 results.put(key, new GetsResponse<T>((net.rubyeye.xmemcached.GetsResponse<T>) tmps.get(key)));344 }345 }346return results;347 } catch (MemcachedException e) {348throw new MemcachedClientException(e);349 }350 }351352 @Override353public <T> Map<String, GetsResponse<T>> gets(Collection<String> keyCollections, long timeout)354throws TimeoutException, InterruptedException, MemcachedClientException {355try {356 Map<String, GetsResponse<T>> results = new HashMap<String, GetsResponse<T>>();357 Map<String, net.rubyeye.xmemcached.GetsResponse<T>> tmps = client.gets(keyCollections, timeout);358if (tmps != null) {359 Set<String> keys = tmps.keySet();360for (String key : keys) {361 results.put(key, new GetsResponse<T>((net.rubyeye.xmemcached.GetsResponse<T>) tmps.get(key)));362 }363 }364return results;365 } catch (MemcachedException e) {366throw new MemcachedClientException(e);367 }368 }369370 @Override371public boolean isEnabled() {372return enabled;373 }374375public void setEnabled(boolean enabled) {376this.enabled = enabled;377 }378379 }经验总结:缓存数据的⼀致性问题缓存数据尽量只读,因此缓存本⾝是不适合⼤量写和更新操作的数据场景的。
PHP内存缓存memcached安装与用法(经典)
PHP内存缓存加速功能memcached安装与用法Memcached是高性能的,分布式的内存对象缓存系统,用于在动态应用中减少数据库负载,提升访问速度。
Memcached 由Danga Interactive开发,用于提升访问速度的。
LJ每秒动态页面访问量几千次,用户700万。
Memcached将数据库负载大幅度降低,更好的分配资源,更快速访问。
=================================================一、memcached 简介在很多场合,我们都会听到memcached 这个名字,可能并没有用过或实际了解过,只知道它是一个很不错的东东。
这里简单介绍一下,memcached 是高效、快速的分布式内存对象缓存系统,主要用于加速WEB 动态应用程序。
二、memcached 安装windows下载:/memcached-win32/首先到下载memcached的windows版本和java客户端jar包,目前最新版本是memcached-1.2.1-win32.zip和java_memcached-release_1.6.zip,分别解压后即可!首先是安装运行memcached服务器,我们将memcached-1.2.1-win32.zip解压后,进入其目录,然后运行如下命令:1. c:>memcached.exe -d install2. c:>memcached.exe -l 127.0.0.1 -m 32 -d start第一行是安装memcached成为服务,这样才能正常运行,否则运行失败!第一行是启动memcached的,作为测试我们就简单的只分配32M内存了,然后监听本机端口和以守护进行运行。
执行完毕后,我们就可以在任务管理器中见到memcached.exe这个进程了。
3.下载php_memcache.dll,请自己查找对应的php版本的文件4. 在C:\winnt\php.ini 加入一行…extension=php_memcache.dll‟5.重新启动Apache,然后查看一下phpinfo,如果有memcache,那么就说明安装成功!memcached的基本设置:-p 监听的端口-l 连接的IP地址, 默认是本机-d start 启动memcached服务-d restart 重起memcached服务-d stop|shutdown 关闭正在运行的memcached服务-d install 安装memcached服务-d uninstall 卸载memcached服务-u 以的身份运行(仅在以root运行的时候有效)-m 最大内存使用,单位MB。
memcache 用法
memcache 用法
Memcache 是分布式缓存系统,主要服务于动态Web 应用,以减轻数据库负载。
其运作机理是基于存储键值对的数据结构(在内存中建立一个巨大的hash表,可以存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等)。
以下是Memcache的使用方法:1.添加一个键值对:使用 add 方法,例如:$mem->add('test','123',0,60);。
其中,'test' 是键,'123' 是值,0 是过期时间(单位:秒),60 是缓存时间(单位:秒)。
2.获取一个键的值:使用 get 方法,例如:$mem->get('test');。
这将返回键'test' 的值。
3.覆写已存在的键值对:使用 replace 方法,例如:$mem->replace('test','456',0,60);。
这将会替换键'test' 的值,新的值为'456'。
4.删除一个键值对:使用 delete 方法,例如:$mem->delete('test',60);。
这将删除键'test' 及其对应的值。
请注意,以上只是Memcache 的基础使用方式,实际应用中可能涉及更多复杂的操作和设置。
如果您需要更深入的了解或使用,建议查阅Memcache 的官方文档或相关教
程。
memcache 用法
memcache 用法摘要:1.简介2.Memcache的安装与配置3.Memcache的使用方法4.Memcache的数据类型5.Memcache的应用场景6.Memcache的优缺点7.总结正文:Memcache是一款高性能的分布式内存对象缓存系统,主要用于提高网站访问速度和减轻服务器负载。
它通过将热点数据存储在内存中,以减少对数据库的访问次数,从而提高网站性能。
1.简介Memcache是一个高性能的分布式内存对象缓存系统,主要用于提高网站访问速度和减轻服务器负载。
它通过将热点数据存储在内存中,以减少对数据库的访问次数,从而提高网站性能。
Memcache支持多种数据类型,包括字符串、整数、浮点数等。
2.Memcache的安装与配置要使用Memcache,首先需要在服务器上安装Memcache服务端。
安装完成后,需要对Memcache进行配置,包括设置内存大小、连接数等参数。
配置完成后,启动Memcache服务。
3.Memcache的使用方法Memcache的使用方法主要包括以下几个步骤:(1)连接Memcache服务器:使用PHP的Memcache扩展库,通过`memcache_connect()`函数连接到Memcache服务器。
(2)设置缓存数据:使用`memcache_set()`函数将数据存储到Memcache中。
(3)获取缓存数据:使用`memcache_get()`函数从Memcache中获取数据。
(4)删除缓存数据:使用`memcache_delete()`函数从Memcache中删除数据。
(5)清空缓存:使用`memcache_clear_cache()`函数清空Memcache 中的所有数据。
4.Memcache的数据类型Memcache支持多种数据类型,包括字符串、整数、浮点数等。
此外,Memcache还支持数据结构,如数组、链表等。
5.Memcache的应用场景Memcache主要应用于以下场景:(1)缓存数据库查询结果:将经常访问的数据从数据库中取出,存储到Memcache中,以减少对数据库的访问次数。
学习Memcached笔记
Memcached介绍什么是MemcachedMemcached是国外社区网站LiveJournal 的开发团队开发的高性能的分布式内存缓存服务器。
一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web 应用的速度、提高可扩展性。
官方网站:/memcached/Memcached运行图Memcached的主要特点基于C/S架构,协议简单基于libevent的事件处理libevent是一套跨平台的事件处理接口的封装,能够兼容包括这些操作系统:Windows/Linux/BSD/Solaris 等操作系统的的事件处理。
Memcached 使用libevent来进行网络并发连接的处理,能够保持在很大并发情况下,仍旧能够保持快速的响应能力。
libevent: /~provos/libevent/数据存储方式:Slab AllocationSlab Alloction 构造图Slab Allocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块,以完全解决内存碎片问题。
Slab Allocation的原理相当简单。
将分配的内存分割成各种尺寸的块(chunk),并把尺寸相同的块分成组(chunk的集合Page:分配给Slab的内存空间,默认是1MB。
分配给Slab之后根据slab的大小切分成chunk。
Chunk:用于缓存记录的内存空间。
Slab Class:特定大小的chunk的组。
memcached根据收到的数据的大小,选择最适合数据大小的slab。
memcached中保存着slab内空闲chunk的列表,根据该列表选择chunk,然后将数据缓存于其中。
Slab Alloction 缺点这个问题就是,由于分配的是特定长度的内存,因此无法有效利用分配的内存。
例如,将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了。
数据过期方式:Lazy Expiration + LRULazy Expirationmemcached内部不会监视记录是否过期,而是在get时查看记录的时间戳,检查记录是否过期。
Memcached命令行用法
Memcache 的命令行用法1、启动Memcache 常用参数memcached 1.4.3 -p <num> -U <num> 设置端口号(默认不设置为: 11211) UDP 监听端口(默认: 11211, 0 时关闭) -l <ip_addr> 绑定地址(默认:所有都允许,无论内外网或者本机更换IP,有安全隐患,若设置为127.0.0.1 就只能本机访问) -d 独立进程运行-u <username> 绑定使用指定用于运行进程<username> -m <num> -P <file> 如:在linux 下:./usr/local/bin/memcached -d -u jb-mc -l 192.168.1.197 -m 2048 -p 12121 在window 下:d:\App_Serv\memcached\memcached.exe -d RunService -l 127.0.0.1 -p 11211 -m 500 在windows 下注册为服务后运行:sc.exe create jb-Memcached binpath= “d:\App_Serv\memcached\memcached.exe -d RunService -p 11211 -m 500〃start= auto net start jb-Memcached 允许最大内存用量,单位M (默认: 64 MB) 将PID 写入文件<file>,这样可以使得后边进行快速进程终止, 需要与-d 一起使用2、连接:telnet 127.0.0.1 11211 不要说不会用这个?3、写入memcache <command name> <key> <flags> <exptime> <bytes>\r\n <data block>\r\n a) <command name> 可以是”set”, “add”, “replace”。
Memcached的使用
首先到/memcached/下载memcached的windows版本和java客户端jar包,目前最新版本是memcached-1.2.1-win32.zip和java_memcached-release_1.6.zip,分别解压后即可!首先是安装运行memcached服务器,我们将memcached-1.2.1-win32.zip解压后,进入其目录,然后运行如下命令:c:>memcached.exe -d installc:>memcached.exe -l 127.0.0.1 -m 32 -d start第一行是安装memcached成为服务,这样才能正常运行,否则运行失败!第一行是启动memcached的,作为测试我们就简单的只分配32M内存了,然后监听本机端口和以守护进行运行。
执行完毕后,我们就可以在任务管理器中见到memcached.exe这个进程了。
好了,我们的服务器已经正常运行了,下面我们就来写java的客户端连接程序。
我们将java_memcached-release_1.6.zip解压后的目录中的java_memcached-release_1.6.jar文件复制到java项目的lib 目录下,然后我们来编写代码,比如我提供的一个应用类如下:package utils.cache;import java.util.Date;import com.danga.MemCached.MemCachedClient;import com.danga.MemCached.SockIOPool;/*** 使用memcached的缓存实用类.** @author铁木箱子**/public class MemCached{// 创建全局的唯一实例protected static MemCachedClient mcc = new MemCachedClient(); protected static MemCached memCached = new MemCached();// 设置与缓存服务器的连接池static {// 服务器列表和其权重String[] servers = {"127.0.0.1:11211"};Integer[] weights = {3};// 获取socke连接池的实例对象SockIOPool pool = SockIOPool.getInstance();// 设置服务器信息pool.setServers( servers );pool.setWeights( weights );// 设置初始连接数、最小和最大连接数以及最大处理时间pool.setInitConn( 5 );pool.setMinConn( 5 );pool.setMaxConn( 250 );pool.setMaxIdle( 1000 * 60 * 60 * 6 );// 设置主线程的睡眠时间pool.setMaintSleep( 30 );// 设置TCP的参数,连接超时等pool.setNagle( false );pool.setSocketTO( 3000 );pool.setSocketConnectTO( 0 );// 初始化连接池pool.initialize();// 压缩设置,超过指定大小(单位为K)的数据都会被压缩mcc.setCompressEnable( true );mcc.setCompressThreshold( 64 * 1024 );}/*** 保护型构造方法,不允许实例化!**/protected MemCached(){}/*** 获取唯一实例.* @return*/public static MemCached getInstance(){return memCached;}/*** 添加一个指定的值到缓存中.* @param key* @param value* @return*/public boolean add(String key, Object value){return mcc.add(key, value);}public boolean add(String key, Object value, Date expiry) {return mcc.add(key, value, expiry);}public boolean replace(String key, Object value){return mcc.replace(key, value);}public boolean replace(String key, Object value, Date expiry) {return mcc.replace(key, value, expiry);}/*** 根据指定的关键字获取对象.* @param key* @return*/public Object get(String key){return mcc.get(key);}public static void main(String[] args){MemCached cache = MemCached.getInstance();cache.add("hello", 234);System.out.print("get value : " + cache.get("hello"));}}那么我们就可以通过简单的像main方法中操作的一样存入一个变量,然后再取出进行查看,我们可以看到先调用了add,然后再进行get,我们运行一次后,234这个值已经被我们存入了memcached的缓存中的了,我们将main方法中红色的那一行注释掉后,我们再运行还是可以看到get到的value也是234,即缓存中我们已经存在了数据了。
php memcached 用法
php memcached 用法“php memcached 用法”Memcached是一种高性能分布式内存对象缓存系统,常用于缓存常用数据,提高Web应用程序的性能。
在PHP中,Memcached可以通过扩展或使用Memcached类来实现。
本文将深入探讨Memcached的用法,包括安装、配置、连接、存储与获取数据、过期时间设置和常见问题解决等方面的内容。
第一步:安装和配置Memcached要使用PHP的Memcached扩展,首先需要在服务器上安装Memcached 软件包。
在Linux系统上,我们可以通过包管理器来安装。
例如,对于Ubuntu,可以使用以下命令安装:sudo apt-get install memcached安装好Memcached之后,我们需要编辑php.ini文件来启用Memcached扩展。
找到该文件(通常位于/etc/php/7.4/apache2/目录中)并打开它。
在文件中找到一个名为"extension"的行,然后在该行下面添加以下代码:extension=memcached.so保存并关闭php.ini文件。
重启Web服务器,使配置生效。
第二步:连接Memcached服务器在PHP中,我们可以通过两种方式连接到Memcached服务器:使用Memcached扩展或使用Memcached类。
以下是实现两种方法的示例代码:1. 使用Memcached扩展memcached = new Memcached();memcached->addServer('localhost', 11211);在这个例子中,我们创建了一个Memcached实例,并添加了一个服务器。
这里的localhost是Memcached服务器的主机名或IP地址,11211是Memcached服务器的默认端口号。
2. 使用Memcached类memcached = new Memcached();memcached->addServer('localhost', 11211);与使用Memcached扩展相比,使用Memcached类的代码几乎是一样的。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
我对于Memcached的接触,还是在去年看了CSDN的一系列国外大型网站架构设计而开始的。
最初的时候只是简单的封装了Memcached Java版的客户端,主要是对于配置的简化以及Memcached多点备份作了一些工作,然后就作为ASF的组件一部分提供给其他Team使用。
其实看过Memcached Java客户端代码的人就会了解其实客户端的事情很简单,就是要有一套高性能的Socket通信框架以及对Memcached的私有协议实现的接口,自己去做这些事情也是很简单的,不过既然有可以满足自己需求的开源部分,那么就去实现自己需要的但没有实现的。
这里我用的是Whalin的客户端版本,这里为什么还要提出来讲这个,后面会提到。
在对Java客户端作了简单封装和扩展以后,由于其他Team使用的没有什么特殊需求,也就没有再去做太多的修改,直到最近自己的服务集成平台需要做服务访问控制,才重新丰富了Cache组件,也就是这个过程中对于Memcached的一些特性和小的细节有了一些新的认识。
作为服务集成平台需要对服务有所监控,包括访问频率控制以及访问次数控制。
频率控制其实很类似于硬件方面的频率控制,例如硬件可以对IP的高频率访问视为攻击,列入黑名单。
而作为服务的访问,对于服务访问者的控制其实涉及到了业务参数,那么硬件就不是很适合去做这方面的控制,为此我也考虑了很久,最开始打算在Apache上做一个模块控制,但是最后觉得还是放在后面的业务框架上做这件事情。
当然后面我说说的方案可能并不好,但是也算是一种想法。
要把频繁的访问数据记录下来同时分析,那么数据库肯定是不行的,最简单的方式就是采用Cache,又因为是集群范围内的控制,那么集中式Cache就非Memcached莫数了(分布式的Cache传播本身损耗太大,集中式Cache本来的最大缺点就是单点,但作简单的备份操作就可以基本解决此类问题)。
作为解决这个问题的方法来说只需要实现两部分工作:访问计数器,定时任务。
定时任务在我做日志分析框架的时候都是采用了Jdk5的Concurrent包里面的ScheduledExecutorService,这个作简单的循环任务足够用了,同时也是有很好的多线程异步支持,复杂一点么用Quartz。
计数器就要靠Memcached来实现了,本来一般的Cache最大的问题就是高并发下的事务保证,如果采用Get+Set 来完成计数的话,那么高并发下计数器就会出现读写不一致性的问题,幸好Memcached提供了计数累加功能,让这种累加动作能够在服务端一次做好,服务端控制并发写入,保证数据的一致性。
下面就看看以下几个方法:boolean storeCounter(String key, long count):存储key的计数器,值为count。
long getCounter(String key):获取key的计数器,如果不存在返回-1。
long addOrDecr(String key, long decr):计数器值减去decr,如果计数器不存在,保存decr作为计数器值long addOrIncr(String key, long inc):计数器值增加inc,如果计数器不存在,保存inc作为计数器值long decr(String key, long decr):与addOrDecr不同的是在计数器不存在的时候不保存任何值,返回-1long incr(String key, long inc) :与addOrIncr不同的是在计数器不存在的时候不保存任何值,返回-1这里需要说明几点:storeCounter和普通的set方法不同,如果通过set方式置入key:value的话,getCounter等其他四个方法都认为技术器不存在。
所以Counter的存储方式是和普通内容存储不同的。
在不同的场景要慎用addOrXXXX和XXXX的方法,两者还是有比较大的区别的。
计数器没有提供移除特殊方法,使用delete方法可以移除计数器,但是频繁的delete和addOrXXXX有时候会出现一些奇怪的问题(例如同名的计数器就没有办法再次被创建,不过这个还需要进一步的去研究一下看看)。
一般情况下如果计数器的key不是很多,同时也会被复用,那么可以通过置为0或者减去已经分析过的数量来复位。
有上面的一套计数器机制就可以很方便的实现Memcached的计数功能,但是又一个问题出现了,如何让定时任务去遍历计数器,分析计数器是否到了阀值,触发创建黑名单记录的工作。
早先我同事希望我能够提供封装好的keySet接口,但是我自己觉得其实作为Cache来说简单就是最重要的,Cache不需要去遍历。
首先使用Cache的角色就应该知道Key,然后去Cache里面找,找不到就去后台例如DB里面去搜索,然后将搜索的结果在考虑更新到Cache里面,这样才是最高效并且最可靠的,Cache靠不住阿,随时都可能会丢失或者崩溃,因此作为类似于一级缓存或者这类数据完整性要求不高,性能要求很高的场景使用最合适。
当时就没有提供这样的接口,直到今天自己需要了,才考虑如何去做这件事情。
开始考虑是否能够将key都记录在另外的Cache中或者是Memcached中,首先在高并发下更新操作就是一大问题,再者Memcached的内存分配回收机制以及Value的大小限制都不能满足这样的需求,如果使用数据库,那么频繁更新操作势必不可行,采用异步缓存刷新又有一个时间间隔期,同时更新也不是很方便。
最后考虑如果能够让Memcached实现Keyset那么就是最好的解决方案,网上搜索了一下,找到一种策略,然后自己优化了一下,优化后的代码如下:@SuppressWarnings("unchecked")public Set keySet(int limit,boolean fast){Set<String> keys = new HashSet<String>();Map<String,Integer> dumps = new HashMap<String,Integer>();Map slabs = getCacheClient().statsItems();if (slabs != null && slabs.keySet() != null){Iterator itemsItr = slabs.keySet().iterator();while(itemsItr.hasNext()){String server = itemsItr.next().toString();Map itemNames = (Map) slabs.get(server);Iterator itemNameItr = itemNames.keySet().iterator();while(itemNameItr.hasNext()){String itemName = itemNameItr.next().toString();// itemAtt[0] = itemname// itemAtt[1] = number// itemAtt[2] = fieldString[] itemAtt = itemName.split(":");if (itemAtt[2].startsWith("number"))dumps.put(itemAtt[1],Integer.parseInt(itemAtt[1]));}}if (!dumps.values().isEmpty()){Iterator<Integer> dumpIter = dumps.values().iterator();while(dumpIter.hasNext()){int dump = dumpIter.next();Map cacheDump = statsCacheDump(dump,limit);Iterator entryIter = cacheDump.values().iterator();while (entryIter.hasNext()){Map items = (Map)entryIter.next();Iterator ks = items.keySet().iterator();while(ks.hasNext())String k = (String)ks.next();try{k = URLDecoder.decode(k,"UTF-8"); }catch(Exception ex){Logger.error(ex);}if (k != null && !k.trim().equals("")) {if (fast)keys.add(k);elseif (containsKey(k))keys.add(k);}}}}}return keys;}对于上面代码的了解需要从Memcached内存分配和回收机制开始,以前接触Memcached的时候只是了解,这部分代码写了以后就有些知道怎么回事了。
Memcached为了提高内存的分配和回收效率,采用了slab和dump分区的概念。
Memcached一大优势就是能够充分利用Memory资源,将同机器或者不同机器的Memcached服务端组合成为对客户端看似统一的存储空间,Memcached 可以在一台机器上开多个端口作为服务端多个实例,也可以在多台机器上开多个服务实例,而slab 就是Memcached的服务端。
下面是我封装后的Cache配置:<?xml version="1.0" encoding="UTF-8"?><memcached><client name="mclient0" compressEnable="true"defaultEncoding="UTF-8" socketpool="pool0"><!--errorHandler></errorHandler--></client><client name="mclient1" compressEnable="true"defaultEncoding="UTF-8" socketpool="pool1"><!--errorHandler></errorHandler--></client><client name="mclient11" compressEnable="true"defaultEncoding="UTF-8" socketpool="pool11"><!--errorHandler></errorHandler--></client><socketpool name="pool0" failover="true" initConn="10" minConn="5" maxConn="250" maintSleep="0"nagle="false" socketTO="3000" aliveCheck="true"><servers>10.2.225.210:13000,10.2.225.210:13001,10.2.225.210:1 3002</servers></socketpool><socketpool name="pool1" failover="true" initConn="10" minConn="5" maxConn="250" maintSleep="0"nagle="false" socketTO="3000" aliveCheck="true"><servers>10.2.225.210:13000</servers></socketpool><socketpool name="pool11"failover="true"initConn="10"minConn="5" maxConn="250" maintSleep="0"nagle="false" socketTO="3000" aliveCheck="true"><servers>10.2.225.210:13000</servers></socketpool><cluster name="cluster1"><memCachedClients>mclient1,mclient11</memCachedClients></cluster></memcached>可以看到其实pool才是最终连接服务端的配置,看看pool0,它会连接10.2.225.210:13000,10.2.225.210:13001,10.2.225.210:13002这些机器和他们的端口,但是对于使用pool0的mclient0来说它仅仅只是知道有一个叫做mclient0的cache可以保存数据。