前段时间公司开发的网站越来越慢了,领导让我加缓存,当时对如何使用中间件缓存一无所知,但领导交待的任务,硬着头皮也得上了。memcached这一块我就不介绍了,网上很多的文章介绍。
最初是找了“memcached client for java”,找了网上的一些代码,直接放上去,感觉速度提升不少,心里高兴的很。马上进行压力测试,当并发300时,缓存就失效了,一直报异常(这个过了有段时间了,具体的异常我记不太清了),这样肯定不行,只能另找它路。找了几天,最后确定用xmemcached,后期的压力测试也很给力。在此做个笔录,也给还在找缓存资料的程序员们提供点微薄的资料。
一、centos上安装memcached(省略)
二、官网下载xmemcached.jar文件。
三、xmemcached初始化(这里直接上代码了)
public class MemCachedManager {
private static MemcachedClientBuilder builder = null;
private static MemcachedClient mcc = null;
private static List<InetSocketAddress> address=new ArrayList<InetSocketAddress>();
private static String memcachedListsServer="192.168.1.2:11211,192.168.1.2:11212,192.168.1.2:11213";//这里可以读取配置文件
private static int pool_size=5;//连接池,也可以从配置文件中读取
static{
if(memcachedListsServer!=null && ! memcachedListsServer.equals("")){
if(memcachedListsServer.indexOf(",")>-1){
String[] servers = memcachedListsServer.split(",");
for(int i=0;i<servers.length;i++){
serversList.add(servers[i]);
address.add(AddrUtil.getOneAddress(servers[i]));
}
}else{
serversList.add(memcachedListsServer);
address.add(AddrUtil.getOneAddress(memcachedListsServer));
}
builder = new XMemcachedClientBuilder(address);
//设置连接池大小
if(pool_size!=null && ! pool_size.equals("")){
int pool_size_int=Integer.valueOf(pool_size);
if(pool_size_int>0){
builder.setConnectionPoolSize(pool_size_int);
}
}
//启用二进制协议,但如果设置为二进制,则不能查找所有keys(特别注意)
//builder.setCommandFactory(new BinaryCommandFactory());
//设置分布策略,一致性哈希net.rubyeye.xmemcached.impl.KetamaMemcachedSessionLocator或者ArraySessionLocator(默认)
builder.setSessionLocator(new KetamaMemcachedSessionLocator(true));
try {
mcc = builder.build();
} catch (IOException e) {
e.printStackTrace();
}
}
//获取缓存
public static Object get(String keyName){
if(!isCachedExist()){
return null;
}
Object obj=null;
try {
obj = mcc.get(keyName);
return obj;
} catch (TimeoutException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (MemcachedException e) {
e.printStackTrace();
}
return obj;
}
//获取多个缓存数据
public static Map<String, Object> gets(List<String> keyNames){
if(!isCachedExist()){
return null;
}
Map<String, Object> map=null;
try {
map = mcc.get(keyNames);
return map;
} catch (TimeoutException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (MemcachedException e) {
e.printStackTrace();
}
return map;
}
//设置缓存数据(expire表示缓存失效的时间)
public static boolean set(String keyName, Object keyValue, int expire){
if(!isCachedExist()){
return false;
}
boolean isSuccess=false;
try {
isSuccess = mcc.set(keyName, expire, keyValue);
} catch (TimeoutException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (MemcachedException e) {
e.printStackTrace();
}
return isSuccess;
}
//获取所有服务器上所有的缓存数据
public static List<MemCached> getKeys() throws UnsupportedEncodingException{
if(!isCachedExist()){
return null;
}
List<MemCached> memcachedList=new ArrayList<MemCached>();
try {
for(String server : serversList){
KeyIterator it = mcc.getKeyIterator(AddrUtil.getOneAddress(server));
while(it.hasNext())
{
String key = it.next();
Object obj = get(key);
String key_value = getObjectType(obj);
MemCached mem = new MemCached();
mem.setKeyname(URLDecoder.decode(key, "UTF-8"));
mem.setValue(key_value);
mem.setServiceName(server);
memcachedList.add(mem);
}
}
});
} catch (MemcachedException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
return memcachedList;
}
//根据缓存数据判断数据类型
private static String getObjectType(Object obj){
String returnStr="Object";
if(obj!=null){
if(obj instanceof Integer || obj instanceof String || obj instanceof Double || obj instanceof Float
|| obj instanceof Long || obj instanceof Boolean || obj instanceof Date){
returnStr=obj.toString();
}
}else{
returnStr="Null";
}
return returnStr;
}
}
获取缓存服务器上所有的缓存数据今天就到这了,但这同样会有问题,现实开发中也不会去得到所有的缓存数据,因为系统很大做了集群之后,缓存服务器也会增多,同时去获取所有的缓存数据这是不可取的,一般真正的开发中也不去读取所有的缓存,那如何去更新缓存呢,我将在下一篇博客中写我们现在的解决方案,希望和大家一起讨论