CacheService.java 4.78 KB
package com.yoho.search.cache;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;

import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.yoho.search.dal.model.SearchParam;
import com.yoho.search.dal.model.SearchResult;
import com.yoho.search.utils.MD5Util;
import com.yoho.search.utils.SearchParamUtils;

@Service
public class CacheService {
	
	private static final Logger logger = LoggerFactory.getLogger(CacheService.class);
	
	private Map<String,CacheObject> cache = new ConcurrentHashMap<String,CacheObject>();
	private CacheCount cacheCount = new CacheCount();
	private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);
	
	private static final int cacheTimeInMinute = 3;//结果缓存的时间
	private static final int logPeriodInMinute = 3;//记录缓存命中的时间
	private static final int clearCachePeriodInMinute = 15;//清除整个缓存对象的时间
	
	@PostConstruct
	void init(){
		//每3分钟记录下缓存命中率
		scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				logger.info("do log cache matchPercent,logPeriodInMinute is [{}],[{}]",logPeriodInMinute,cacheCount);
				cacheCount.clear();
			}
		}, logPeriodInMinute, logPeriodInMinute, TimeUnit.MINUTES);
		
		//每15分钟清除缓存对象,防止内存爆掉
		scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				logger.info("do clear cacheObject...");
				cache = new ConcurrentHashMap<String,CacheObject>();
			}
		}, clearCachePeriodInMinute, clearCachePeriodInMinute, TimeUnit.MINUTES);
	}
	
	private Object getObjectFromCache(String key){
		cacheCount.incTotalCount();
		CacheObject cacheObject = cache.get(key);
		if(cacheObject==null){
			return null;
		}
		if(cacheObject.getExpireTime() < System.currentTimeMillis()){
			cache.remove(key);
			return null;
		}
		cacheCount.incMatchCount();
		return cacheObject.getObject();
	}
	
	private void addObjectToCache(String key,Object object){
		CacheObject cacheObject = new CacheObject(object, cacheTimeInMinute * 60);
		cache.put(key, cacheObject);
	}

	/***********************************for SearchParam and SearchResult*****************************************/
	private String genSearchParamString(String indexName, SearchParam searchParam) {
		StringBuilder sb = new StringBuilder();
		// 拼装索引名称
		sb.append("indexName:").append(indexName).append(";");
		// 拼装搜索类型
		sb.append("searchType:").append(searchParam.getSearchType() == null ? "" : searchParam.getSearchType().name()).append(";");
		// 拼装报文
		SearchSourceBuilder searchSourceBuilder = SearchParamUtils.genSearchSourceBuilderFromSearchParam(searchParam);
		sb.append("searchSource:").append(searchSourceBuilder.toString()).append(";");
		// 打印拼装结果
		// logger.info("cacheKey is [{}]",sb.toString());
		return MD5Util.string2MD5(sb.toString());
	}
	
	public SearchResult getSearchResultFromCache(String indexName, SearchParam searchParam) {
		String key = this.genSearchParamString(indexName, searchParam);
		return (SearchResult) this.getObjectFromCache(key);
	}

	public void addSearchResultToCache(String indexName, SearchParam searchParam, SearchResult result) {
		String key = this.genSearchParamString(indexName, searchParam);
		this.addObjectToCache(key, result);
	}
	
	/***********************************for multiGet*****************************************/
	private String genMultiGetParamString(String indexName, Set<String> idList, List<String> fields) {
		StringBuilder sb = new StringBuilder();
		// 拼装索引名称
		sb.append("indexName:").append(indexName).append(";");
		// 拼装搜索类型
		sb.append("idList:").append(idList.toString()).append(";");
		// 拼装报文
		sb.append("fields:").append(fields==null?"":fields.toString()).append(";");
		// 打印拼装结果
		// logger.info("cacheKey is [{}]",sb.toString());
		return MD5Util.string2MD5(sb.toString());
	}
	
	@SuppressWarnings("unchecked")
	public List<Map<String, Object>> getMultiGetResultFromCache(String indexName, Set<String> idList, List<String> fields) {
		String key = this.genMultiGetParamString(indexName, idList, fields);
		return (List<Map<String, Object>>) this.getObjectFromCache(key);
	}
	
	public void addMultiGetResultResultToCache(String indexName, Set<String> idList, List<String> fields, List<Map<String, Object>> result) {
		String key = this.genMultiGetParamString(indexName, idList, fields);
		this.addObjectToCache(key, result);
	}
	
}