|
|
package com.yoho.search.recall.scene.component;
|
|
|
|
|
|
import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder;
|
|
|
import com.yoho.search.base.utils.CollectionUtils;
|
|
|
import com.yoho.search.base.utils.Transfer;
|
|
|
import com.yoho.search.common.cache.impls.EhCache;
|
|
|
import com.yoho.search.core.redis.components.YohoSearchRedisComponent;
|
|
|
import com.yoho.search.recall.scene.models.cache.CacheRequestResponse;
|
|
|
import org.apache.commons.lang.StringUtils;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
|
import java.util.*;
|
|
|
|
|
|
@Component
|
|
|
public class CacheRequestResponseComponent {
|
|
|
|
|
|
private static final Logger logger = LoggerFactory.getLogger(CacheRequestResponseComponent.class);
|
|
|
|
|
|
@Autowired
|
|
|
private YohoSearchRedisComponent yohoSearchRedisComponent;
|
|
|
@Autowired
|
|
|
private EhCache ehCache;
|
|
|
|
|
|
/**
|
|
|
* 从缓存中获取response
|
|
|
* @param cacheRequestResponses
|
|
|
* @param useEhCache
|
|
|
* @param <K>
|
|
|
* @param <V>
|
|
|
* @param <T>
|
|
|
*/
|
|
|
public <K, V, T extends CacheRequestResponse<K, V>> void batchFillResponseFromCache(final List<T> cacheRequestResponses, boolean useEhCache) {
|
|
|
try {
|
|
|
Collection<RedisKeyBuilder> keys = new ArrayList<>();
|
|
|
for (T requestResponse : cacheRequestResponses) {
|
|
|
RedisKeyBuilder redisKeyBuilder = requestResponse.getRequestRedisKeyBuilder();
|
|
|
keys.add(redisKeyBuilder);
|
|
|
}
|
|
|
List<String> cachedValues = this.mutiGetFromCache(keys, useEhCache);
|
|
|
for (int i = 0; i < cacheRequestResponses.size(); i++) {
|
|
|
T requestResponse = cacheRequestResponses.get(i);
|
|
|
String cachedValue = cachedValues.get(i);
|
|
|
if (!StringUtils.isBlank(cachedValue)) {
|
|
|
V response = requestResponse.getToResponseTransfer().transfer(cachedValue);
|
|
|
requestResponse.setResponse(response, false);
|
|
|
}
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
logger.error(e.getMessage(), e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 过滤出未命中缓存的结果
|
|
|
* @param cacheRequestResponses
|
|
|
* @param <K>
|
|
|
* @param <V>
|
|
|
* @param <T>
|
|
|
* @return
|
|
|
*/
|
|
|
public <K, V, T extends CacheRequestResponse<K, V>> List<T> filterMissCacheRequests(List<T> cacheRequestResponses){
|
|
|
List<T> notCachedRequests = new ArrayList<>();
|
|
|
for (T requestResponse : cacheRequestResponses) {
|
|
|
if (requestResponse != null && requestResponse.getResponse()==null) {
|
|
|
notCachedRequests.add(requestResponse);
|
|
|
}
|
|
|
}
|
|
|
return notCachedRequests;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 使用查询结果填充response
|
|
|
* @param cacheRequestResponses
|
|
|
* @param queryResults
|
|
|
* @param <K>
|
|
|
* @param <V>
|
|
|
* @param <T>
|
|
|
*/
|
|
|
public <K, V, T extends CacheRequestResponse<K, V>> void batchFillResponseWithQueryResults(List<T> cacheRequestResponses,Map<RedisKeyBuilder,V> queryResults){
|
|
|
for (T sknInfoRequestResponse : cacheRequestResponses) {
|
|
|
if(sknInfoRequestResponse.getResponse()!=null){
|
|
|
continue;
|
|
|
}
|
|
|
RedisKeyBuilder redisKeyBuilder = sknInfoRequestResponse.getRequestRedisKeyBuilder();
|
|
|
V response = queryResults.get(redisKeyBuilder);
|
|
|
if(response!=null){
|
|
|
sknInfoRequestResponse.setResponse(response,true);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 将未缓存的response添加至缓存
|
|
|
* @param cacheRequestResponses
|
|
|
* @param useEhCache
|
|
|
* @param <K>
|
|
|
* @param <V>
|
|
|
* @param <T>
|
|
|
*/
|
|
|
public <K, V, T extends CacheRequestResponse<K, V>> void batchAddResponseToCache(List<T> cacheRequestResponses, boolean useEhCache) {
|
|
|
//1、按缓存时间分组
|
|
|
Map<Integer, List<T>> groupMap = CollectionUtils.toListMap(cacheRequestResponses, new Transfer<T, Integer>() {
|
|
|
@Override
|
|
|
public Integer transfer(T t) {
|
|
|
return t.getCacheTimeInSecond();
|
|
|
}
|
|
|
});
|
|
|
//2、按缓存时间大小直接加入缓存
|
|
|
for (Map.Entry<Integer, List<T>> entry : groupMap.entrySet()) {
|
|
|
this.batchAddResponseToCache(entry.getValue(), useEhCache, entry.getKey());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private <K, V, T extends CacheRequestResponse<K, V>> void batchAddResponseToCache(List<T> cacheRequestResponses, boolean useEhCache, int timeOutInSecond) {
|
|
|
try {
|
|
|
Map<RedisKeyBuilder, String> toCacheMap = new HashMap<>();
|
|
|
for (T requestResponse : cacheRequestResponses) {
|
|
|
if (!requestResponse.isNeedRecache()){
|
|
|
continue;
|
|
|
}
|
|
|
RedisKeyBuilder redisKeyBuilder = requestResponse.getRequestRedisKeyBuilder();
|
|
|
V response = requestResponse.getResponse();
|
|
|
if(redisKeyBuilder==null || response==null){
|
|
|
continue;
|
|
|
}
|
|
|
String cacheValue = requestResponse.getFromResponseTransfer().transfer(response);
|
|
|
toCacheMap.put(redisKeyBuilder, cacheValue);
|
|
|
}
|
|
|
if (toCacheMap.isEmpty()) {
|
|
|
return;
|
|
|
}
|
|
|
this.batchAddToCache(toCacheMap, useEhCache, timeOutInSecond);
|
|
|
} catch (Exception e) {
|
|
|
logger.error(e.getMessage(), e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private List<String> mutiGetFromCache(Collection<RedisKeyBuilder> keys, boolean useEhCache) {
|
|
|
if (useEhCache) {
|
|
|
return ehCache.mutiGet(keys);
|
|
|
} else {
|
|
|
return yohoSearchRedisComponent.getValueOperations().multiGet(keys);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void batchAddToCache(Map<RedisKeyBuilder, String> toCacheMap, boolean useEhCache, int timeOutInSecond) {
|
|
|
if (useEhCache) {
|
|
|
ehCache.mutiSet(toCacheMap, timeOutInSecond);
|
|
|
} else {
|
|
|
yohoSearchRedisComponent.getRedisTemplate().mset(toCacheMap, timeOutInSecond);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
} |