package com.idoo.ott.core.cache;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeoutException;
import net.rubyeye.xmemcached.KeyIterator;
import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.XMemcachedClient;
import net.rubyeye.xmemcached.exception.MemcachedException;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SuppressWarnings("deprecation")
public class CacheHandlerImpl {
private Map<String, Object> cacheKeys;
private MemcachedClient memcachedClient;
private Logger logger = LoggerFactory.getLogger(getClass());
public void freshCache(JoinPoint jp) {
String serviceClsName = jp.getTarget().getClass().getSimpleName();
if (cacheKeys != null && cacheKeys.size() > 0
&& cacheKeys.containsKey(serviceClsName)) {
logger.info("refresh cache keys: " + cacheKeys.get(serviceClsName));
freshCacheByName(serviceClsName);
}
}
public void freshCacheByName(String cacheName) {
if (cacheKeys != null && cacheKeys.size() > 0
&& cacheKeys.containsKey(cacheName)) {
logger.info(cacheName + " refresh cache keys:"
+ cacheKeys.get(cacheName));
List<String> keys = getAllKeys();
cacheName = String.valueOf(cacheKeys.get(cacheName));
if ("#flushAll".equals(cacheName)) {
this.deleteCache(cacheName);
return;
}
// 逗号分开
if (StringUtils.isNotBlank(cacheName)) {
String caches[] = cacheName.split(",");
for (String key : caches) {
clearCache(key, keys);
}
}
}
}
private void clearCache(String cacheKey, List<String> cacheKeys) {
for (String key : cacheKeys) {
if (key.indexOf(cacheKey) > -1) {
this.deleteCache(key);
}
}
}
/**
* 二次缓存清理,避免脏数据产生
* @author 905706
* @param key
*/
private void deleteCache(final String key){
this.delete(key);
new Thread(){
public void run(){
try {
Thread.sleep(5000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
delete(key);
}
}.start();
}
public boolean delete(String key){
try {
if("#flushAll".equalsIgnoreCase(key)){
memcachedClient.flushAll();
}else{
memcachedClient.delete(key);
}
return true;
} catch (TimeoutException e) {
logger.error(key + ":fresh cache error", e);
return false;
} catch (InterruptedException e) {
logger.error(key + ":fresh cache error", e);
return false;
} catch (MemcachedException e) {
logger.error(key + ":fresh cache error", e);
return false;
}
}
public List<String> getAllKeys() {
List<String> list = new ArrayList<String>();
Map<InetSocketAddress, Map<String, String>> servers;
try {
servers = this.memcachedClient.getStats();
if (servers != null && servers.size() > 0) {
Iterator<InetSocketAddress> itserver = servers.keySet()
.iterator();
while (itserver.hasNext()) {
InetSocketAddress isa = itserver.next();
KeyIterator ki = this.memcachedClient.getKeyIterator(isa);
while (ki.hasNext()) {
list.add(ki.next());
}
}
}
} catch (MemcachedException e) {
logger.error("fresh cache error", e);
} catch (InterruptedException e) {
logger.error("fresh cache error", e);
} catch (TimeoutException e) {
logger.error("fresh cache error", e);
}
return list;
}
public static void main(String[] args) throws IOException,
TimeoutException, InterruptedException, MemcachedException {
CacheHandlerImpl handlerImpl = new CacheHandlerImpl();
List<InetSocketAddress> addressList = new ArrayList<InetSocketAddress>();
addressList.add(new InetSocketAddress("172.21.11.201", 12000));
addressList.add(new InetSocketAddress("172.21.11.202", 12000));
handlerImpl.memcachedClient = new XMemcachedClient(addressList);
List<String> list = handlerImpl.getAllKeys();
handlerImpl.memcachedClient.flushAll();
System.out.println("flush all");
}
public void setCacheKeys(Map<String, Object> cacheKeys) {
this.cacheKeys = cacheKeys;
}
public Map<String, Object> getCacheKeys() {
return cacheKeys;
}
public void setMemcachedClient(MemcachedClient memcachedClient) {
this.memcachedClient = memcachedClient;
}
public MemcachedClient getMemcachedClient() {
return memcachedClient;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
if (this.memcachedClient != null)
this.memcachedClient.shutdown();
this.memcachedClient = null;
}
}
applicationContext-aop.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<bean name="memcachedClient"
class="net.rubyeye.xmemcached.utils.XMemcachedClientFactoryBean"
destroy-method="shutdown">
<property name="servers">
<value>${memcached.server}</value>
</property>
<!-- server's weights -->
<property name="weights">
<list>
<value>1</value>
<value>1</value>
</list>
</property>
<!-- nio connection pool size -->
<property name="connectionPoolSize" value="1"></property>
<!-- Use binary protocol,default is TextCommandFactory -->
<property name="commandFactory">
<bean class="net.rubyeye.xmemcached.command.TextCommandFactory"></bean>
</property>
<!-- Distributed strategy -->
<property name="sessionLocator">
<bean class="net.rubyeye.xmemcached.impl.KetamaMemcachedSessionLocator"></bean>
</property>
<!-- Serializing transcoder -->
<property name="transcoder">
<bean class="net.rubyeye.xmemcached.transcoders.SerializingTranscoder" />
</property>
<!-- ByteBuffer allocator -->
<property name="bufferAllocator">
<bean class="net.rubyeye.xmemcached.buffer.SimpleBufferAllocator"></bean>
</property>
<!-- Failure mode -->
<property name="failureMode" value="false" />
</bean>
<bean id="cacheHandler" class="com.idoo.ott.core.cache.CacheHandlerImpl">
<property name="memcachedClient" ref="memcachedClient"></property>
<property name="cacheKeys">
<map>
<!-- key service类名 媒资同步接口 -->
<entry key="AssetAddService"
value="getAssetList,getAssetListByPackageCode,getAssetDetail,getRecommendResource,getRelateAsset,getAssetTrailer,searchByKeyWord" />
<!-- 栏目同步接口 -->
<entry key="ColumnDelService" value="getCatalog" />
<entry key="ColumnSynService" value="getCatalog" />
</map>
</property>
</bean>
<!-- <aop:aspectj-autoproxy /> -->
<aop:config>
<aop:aspect ref="cacheHandler">
<aop:pointcut id="pointcut"
expression="execution(* com.idoo.ott.iservice*..*.execute*(..))" /> <!-- 对所有的类以add开头的任何方法使用该方法。可以看spring参考手册 -->
<!-- method 指出before要调用的方法 -->
<aop:after-returning method="freshCache"
pointcut-ref="pointcut" />
</aop:aspect>
</aop:config>
</beans>
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeoutException;
import net.rubyeye.xmemcached.KeyIterator;
import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.XMemcachedClient;
import net.rubyeye.xmemcached.exception.MemcachedException;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SuppressWarnings("deprecation")
public class CacheHandlerImpl {
private Map<String, Object> cacheKeys;
private MemcachedClient memcachedClient;
private Logger logger = LoggerFactory.getLogger(getClass());
public void freshCache(JoinPoint jp) {
String serviceClsName = jp.getTarget().getClass().getSimpleName();
if (cacheKeys != null && cacheKeys.size() > 0
&& cacheKeys.containsKey(serviceClsName)) {
logger.info("refresh cache keys: " + cacheKeys.get(serviceClsName));
freshCacheByName(serviceClsName);
}
}
public void freshCacheByName(String cacheName) {
if (cacheKeys != null && cacheKeys.size() > 0
&& cacheKeys.containsKey(cacheName)) {
logger.info(cacheName + " refresh cache keys:"
+ cacheKeys.get(cacheName));
List<String> keys = getAllKeys();
cacheName = String.valueOf(cacheKeys.get(cacheName));
if ("#flushAll".equals(cacheName)) {
this.deleteCache(cacheName);
return;
}
// 逗号分开
if (StringUtils.isNotBlank(cacheName)) {
String caches[] = cacheName.split(",");
for (String key : caches) {
clearCache(key, keys);
}
}
}
}
private void clearCache(String cacheKey, List<String> cacheKeys) {
for (String key : cacheKeys) {
if (key.indexOf(cacheKey) > -1) {
this.deleteCache(key);
}
}
}
/**
* 二次缓存清理,避免脏数据产生
* @author 905706
* @param key
*/
private void deleteCache(final String key){
this.delete(key);
new Thread(){
public void run(){
try {
Thread.sleep(5000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
delete(key);
}
}.start();
}
public boolean delete(String key){
try {
if("#flushAll".equalsIgnoreCase(key)){
memcachedClient.flushAll();
}else{
memcachedClient.delete(key);
}
return true;
} catch (TimeoutException e) {
logger.error(key + ":fresh cache error", e);
return false;
} catch (InterruptedException e) {
logger.error(key + ":fresh cache error", e);
return false;
} catch (MemcachedException e) {
logger.error(key + ":fresh cache error", e);
return false;
}
}
public List<String> getAllKeys() {
List<String> list = new ArrayList<String>();
Map<InetSocketAddress, Map<String, String>> servers;
try {
servers = this.memcachedClient.getStats();
if (servers != null && servers.size() > 0) {
Iterator<InetSocketAddress> itserver = servers.keySet()
.iterator();
while (itserver.hasNext()) {
InetSocketAddress isa = itserver.next();
KeyIterator ki = this.memcachedClient.getKeyIterator(isa);
while (ki.hasNext()) {
list.add(ki.next());
}
}
}
} catch (MemcachedException e) {
logger.error("fresh cache error", e);
} catch (InterruptedException e) {
logger.error("fresh cache error", e);
} catch (TimeoutException e) {
logger.error("fresh cache error", e);
}
return list;
}
public static void main(String[] args) throws IOException,
TimeoutException, InterruptedException, MemcachedException {
CacheHandlerImpl handlerImpl = new CacheHandlerImpl();
List<InetSocketAddress> addressList = new ArrayList<InetSocketAddress>();
addressList.add(new InetSocketAddress("172.21.11.201", 12000));
addressList.add(new InetSocketAddress("172.21.11.202", 12000));
handlerImpl.memcachedClient = new XMemcachedClient(addressList);
List<String> list = handlerImpl.getAllKeys();
handlerImpl.memcachedClient.flushAll();
System.out.println("flush all");
}
public void setCacheKeys(Map<String, Object> cacheKeys) {
this.cacheKeys = cacheKeys;
}
public Map<String, Object> getCacheKeys() {
return cacheKeys;
}
public void setMemcachedClient(MemcachedClient memcachedClient) {
this.memcachedClient = memcachedClient;
}
public MemcachedClient getMemcachedClient() {
return memcachedClient;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
if (this.memcachedClient != null)
this.memcachedClient.shutdown();
this.memcachedClient = null;
}
}
applicationContext-aop.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<bean name="memcachedClient"
class="net.rubyeye.xmemcached.utils.XMemcachedClientFactoryBean"
destroy-method="shutdown">
<property name="servers">
<value>${memcached.server}</value>
</property>
<!-- server's weights -->
<property name="weights">
<list>
<value>1</value>
<value>1</value>
</list>
</property>
<!-- nio connection pool size -->
<property name="connectionPoolSize" value="1"></property>
<!-- Use binary protocol,default is TextCommandFactory -->
<property name="commandFactory">
<bean class="net.rubyeye.xmemcached.command.TextCommandFactory"></bean>
</property>
<!-- Distributed strategy -->
<property name="sessionLocator">
<bean class="net.rubyeye.xmemcached.impl.KetamaMemcachedSessionLocator"></bean>
</property>
<!-- Serializing transcoder -->
<property name="transcoder">
<bean class="net.rubyeye.xmemcached.transcoders.SerializingTranscoder" />
</property>
<!-- ByteBuffer allocator -->
<property name="bufferAllocator">
<bean class="net.rubyeye.xmemcached.buffer.SimpleBufferAllocator"></bean>
</property>
<!-- Failure mode -->
<property name="failureMode" value="false" />
</bean>
<bean id="cacheHandler" class="com.idoo.ott.core.cache.CacheHandlerImpl">
<property name="memcachedClient" ref="memcachedClient"></property>
<property name="cacheKeys">
<map>
<!-- key service类名 媒资同步接口 -->
<entry key="AssetAddService"
value="getAssetList,getAssetListByPackageCode,getAssetDetail,getRecommendResource,getRelateAsset,getAssetTrailer,searchByKeyWord" />
<!-- 栏目同步接口 -->
<entry key="ColumnDelService" value="getCatalog" />
<entry key="ColumnSynService" value="getCatalog" />
</map>
</property>
</bean>
<!-- <aop:aspectj-autoproxy /> -->
<aop:config>
<aop:aspect ref="cacheHandler">
<aop:pointcut id="pointcut"
expression="execution(* com.idoo.ott.iservice*..*.execute*(..))" /> <!-- 对所有的类以add开头的任何方法使用该方法。可以看spring参考手册 -->
<!-- method 指出before要调用的方法 -->
<aop:after-returning method="freshCache"
pointcut-ref="pointcut" />
</aop:aspect>
</aop:config>
</beans>