package org.dayatang.cache.memcached;
import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;
import org.apache.commons.lang3.StringUtils;
import org.dayatang.cache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import java.util.Set;
/**
* 基于Memcached的缓存实现
*
* @author chencao
*
*/
public class MemcachedBasedCache implements Cache {
private static final Logger LOGGER = LoggerFactory
.getLogger(MemcachedBasedCache.class);
private MemCachedClient mcc;
private String[] servers;
private int initConn = 100;
private int minConn = 100;
private int maxConn = 250;
private int connectTimeout = 3000;
private String poolName;
private boolean initialized = false;
public Object get(String key) {
init();
Object obj = mcc.get(key);
debug("命中缓存:{},key:{}", new Object[] { (obj != null), key });
return obj;
}
@Override
public Map<String, Object> get(String... keys) {
init();
Map<String, Object> map = mcc.getMulti(keys);
return map;
}
public boolean containsKey(String key) {
init();
return mcc.keyExists(key);
}
public void put(String key, Object value) {
init();
mcc.set(key, value);
debug("缓存数据,key:{}", key);
}
public void put(String key, Object value, Date expiry) {
init();
mcc.set(key, value, expiry);
debug("缓存数据,key:{},过期日期:{}", key, expiry);
}
public void put(String key, Object value, long living) {
init();
Date now = new Date();
Date expiry = new Date(now.getTime() + living);
put(key, value, expiry);
}
public boolean remove(String key) {
init();
boolean result = mcc.delete(key);
debug("删除缓存,key:{}", key);
return result;
}
@SuppressWarnings("rawtypes")
protected void prepareClient() {
// grab an instance of our connection pool
SockIOPool pool = null;
if (StringUtils.isBlank(getPoolName())) {
pool = SockIOPool.getInstance();
mcc = new MemCachedClient();
} else {
pool = SockIOPool.getInstance(getPoolName());
mcc = new MemCachedClient(getPoolName());
}
// Integer[] weights = { 5, 1 };
// set the servers and the weights
pool.setServers(servers);
// pool.setWeights(weights);
// set some basic pool settings
// 5 initial, 5 min, and 250 max conns
// and set the max idle time for a conn
// to 6 hours
pool.setInitConn(getInitConn());
pool.setMinConn(getMinConn());
pool.setMaxConn(getMaxConn());
pool.setMaxIdle(1000 * 60 * 60 * 6);
// set the sleep for the maint thread
// it will wake up every x seconds and
// maintain the pool size
pool.setMaintSleep(30);
// pool.setBufferSize(1024);
// set some TCP settings
// disable nagle
// set the read timeout to 3 secs
// and don't set a connect timeout
pool.setNagle(false);
pool.setSocketTO(3000);
pool.setSocketConnectTO(getConnectTimeout());
// initialize the connection pool
pool.initialize();
// lets set some compression on for the client
// compress anything larger than 64k
// mcc.setCompressEnable(true);
// mcc.setCompressThreshold(64 * 1024);
Map map = mcc.stats(servers);
Set keys = map.keySet();
if (keys.size() == 0) {
error("客户端创建遇到错误,无法创建。");
}
for (Object key : keys) {
// logger.info("客户端创建完成。key = 【{}】, status = 【{}】", key, map
// .get(key));
info("客户端创建完成。key = 【{}】", key);
}
}
public String[] getServers() {
return servers;
}
public void setServers(String... servers) {
this.servers = Arrays.copyOf(servers, servers.length);
}
/**
* 获取初始化连接数
*
* @return 初始化连接数
*/
public int getInitConn() {
return initConn;
}
/**
* 设置初始化连接数
*
* @param initConn
* 初始化连接数
*/
public void setInitConn(int initConn) {
this.initConn = initConn;
}
/**
* 获取最小连接数
*
* @return 最小连接数
*/
public int getMinConn() {
return minConn;
}
/**
* 设置最小连接数
*
* @param minConn
* 最小连接数
*/
public void setMinConn(int minConn) {
this.minConn = minConn;
}
/**
* 获取最大连接数
*
* @return 最大连接数
*/
public int getMaxConn() {
return maxConn;
}
/**
* 设置最大连接数
*
* @param maxConn
* 最大连接数
*/
public void setMaxConn(int maxConn) {
this.maxConn = maxConn;
}
/**
* 获取连接超时时间(毫秒)
*
* @return 连接超时时间(毫秒)
*/
public int getConnectTimeout() {
return connectTimeout;
}
/**
* 设置连接超时时间(毫秒)
*
* @param connectTimeout
* 连接超时时间(毫秒)
*/
public void setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
}
/**
* 获取socket pool名称
*
* @return socket pool名称
*/
public String getPoolName() {
return poolName;
}
/**
* 设置socket pool名称
*
* @param poolName
* socket pool名称
*/
public void setPoolName(String poolName) {
this.poolName = poolName;
}
public void init() {
if (initialized) {
return;
}
if (servers == null || servers.length == 0) {
throw new IllegalStateException("Must assign memcached server address");
}
for (String server : servers) {
info("准备为Memcached服务器{}创建客户端...", server);
info("最小连接数为:{}", minConn);
info("最大接数为:{}", maxConn);
info("初始化连接数为:{}", initConn);
info("连接超时时间为:{}毫秒", connectTimeout);
}
prepareClient();
// if (logger.isDebugEnabled()) {
// logger.debug("客户端创建完成。...");
// }
initialized = true;
}
private void debug(String message, Object... params) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(message, params);
}
}
private void info(String message, Object... params) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info(message, params);
}
}
private void error(String message, Object... params) {
if (LOGGER.isErrorEnabled()) {
LOGGER.error(message, params);
}
}
}