使用redis管道(pipeline)實現批量查詢,批量修改

 Pipeline:“管道”,和很多設計模式中的“管道”具有同樣的概念,pipleline的操作,將明確client與server端的交互,都是“單向的”:你可以將多個command,依次發給server,但在此期間,你將無法獲得單個command的響應數據,此後你可以關閉“請求”,然後依次獲取每個command的響應結果。

    從簡單來說,在IO操作層面,對於client而言,就是一次批量的連續的“write”請求,然後是批量的連續的“read”操作。其實對於底層Socket-IO而言,對於client而言,只不過是多次write,然後一次read的操作;對於server端,input通道上read到數據之後,就會立即被實施,也會和非pipeline一樣在output通道上輸出執行的結果,只不過此時數據會被阻塞在網絡緩衝區上,直到client端開始read或者關閉鏈接。

redisService:

public interface RedisService {
    /**
     * 根據 redis  的key的集合批量查詢對應存在數據
     * @param keys
     * @param useParallel  是否使用parallel 在沒有順序要求的時候,提高效率,true爲表示使用,false 表示不用,默認爲true
     * @return
     */
    Map<String,Object> batchQueryByKeys(List<String> keys,Boolean useParallel);


    /**
     * 使用管道的方式,批量添加數據
     * @param keyValueMap
     * @param expire 過期時間
     * @return
     */
    List<Object> batchPutInPipelined(Map<String,Object> keyValueMap,long expire);

    /**
     * batch increment an integer value in pipelined
     *
     * @param  entityList
     *
     * @return
     *
     */
    List<MapEntity> batIncByPipelined(List<MapEntity> entityList);


}

AbstractRedisService 抽象類

public abstract class AbstractRedisService implements RedisService{
    private static final Logger logger = LoggerFactory.getLogger(AbstractRedisService.class);
    protected abstract RedisTemplate getRedisTemplate();

    @Override
    public Boolean expire(String key, long timeout, TimeUnit timeUnit) {
        return getRedisTemplate().expire(key,timeout,timeUnit);
    }


    @Override
   public Map<String,Object> batchQueryByKeys(List<String> keys,Boolean useParallel){
        if(null == keys || keys.size() == 0 ){
            return null;
        }

        if(null == useParallel){
            useParallel = true;
        }

        List<Object> results = getRedisTemplate().executePipelined(
                new RedisCallback<Object>() {
                    public Object doInRedis(RedisConnection connection) throws DataAccessException {
                        StringRedisConnection stringRedisConn = (StringRedisConnection)connection;
                        for(String key:keys) {
                            stringRedisConn.get(key);
                        }
                        return null;
                    }
                });
        if(null == results || results.size() == 0 ){return null;}

        Map<String,Object> resultMap  =  null;

        if(useParallel){

            Map<String,Object> resultMapOne  = Collections.synchronizedMap(new HashMap<String,Object>());

            keys.parallelStream().forEach(t -> {
                resultMapOne.put(t,results.get(keys.indexOf(t)));
            });

            resultMap = resultMapOne;

        }else{

            Map<String,Object> resultMapTwo  = new HashMap<>();

            for(String t:keys){
                resultMapTwo.put(t,results.get(keys.indexOf(t)));
            }

            resultMap = resultMapTwo;
        }

        return  resultMap;

    }

    @Override
   public List<Object> batchPutInPipelined(Map<String,Object> keyValueMap,long expire){

        List<Object> results = getRedisTemplate().executePipelined(
                new RedisCallback<Object>() {
                    public Object doInRedis(RedisConnection connection) throws DataAccessException {
                        StringRedisConnection stringRedisConn = (StringRedisConnection)connection;
                        for(String key:keyValueMap.keySet()) {
                            if(null != keyValueMap.get(key)){
                                stringRedisConn.set(key, keyValueMap.get(key).toString());
                                stringRedisConn.expire(key,expire);
                            }
                        }
                        return null;
                    }
                });

        return  results;

    }


    @Override
    public List<MapEntity> batIncByPipelined(List<MapEntity> params){

        List<Object> results = getRedisTemplate().executePipelined(
                new RedisCallback<Object>() {
                    public Object doInRedis(RedisConnection connection) throws DataAccessException {
                        StringRedisConnection stringRedisConn = (StringRedisConnection)connection;
                        for(MapEntity entity:params) {
                            if(null != entity){
                                stringRedisConn.incrBy(entity.getKey(), entity.getValue());
                            }
                        }
                        return null;
                    }
                });

        List<MapEntity> resultList  = Lists.newArrayList();

        for(MapEntity entity:params){
            resultList.add(new MapEntity(entity.getKey(),(Long)results.get(params.indexOf(entity))));
        }


        return  resultList;

    }
}

 RedisServiceImpl 實現類

public class RedisServiceImpl extends AbstractRedisService  {
    private RedisTemplate redisTemplate;

    public RedisServiceImpl(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    protected RedisTemplate getRedisTemplate() {
        return redisTemplate;
    }
}

補充: 具體RedisTemplate 替代 jedis 方法 點這裏 https://www.cnblogs.com/yinfengjiujian/p/9084711.html 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章