使用future进行并行redis缓存调用

时间:2015-08-17 15:03:06

标签: java redis future callable jedis

我正在尝试在我的redis数据存储上进行多次获取,该存储分布在多个分片上。但是,我想要执行此操作的键不属于同一个分片,因此我无法使用redis'内置的multi-get。

相反,我试图用期货来实现这一目标。但是在检查查找时间之后,几乎看起来这些缓存调用都是串行进行的。

服务器上的请求/秒约为1.5k,响应时间平均为10 ms。我读过的文献告诉我,我的线程池大小应该是request / sec *响应时间。由于我正在产生3个线程,因此它变为1500 * 0.010 * 3 = 45.我尝试使用50,100,300的线程池大小。但这也没有帮助。

我正在使用Jedis作为客户端。我认为这可能是超出Jedis的最大总/空闲连接限制的问题。但即使将此值从8增加到24,我发现查找时间没有差异。

我知道会有一些开销,因为会有上下文切换和产生新线程的开销。

任何人都可以帮我弄清楚我错过的地方。如果您需要更多信息,请告诉我。

                for(String recordKey : pidArr) {
                //Adding futures. Max 3
                if(count >= 3) {
                    break;
                }
                count++;
                Callable<String> a = new FeedCacheCaller(recordKey);

                Future<String> future = feedThreadPool.submit(a);
                futureList.add(future);
            }

            //Getting the data from the futures

            for(Future<String> foo : futureList) {
                try {
                    String data = foo.get();
                    logger.debug(data);
                    feedDataList.add(parseInfo(data));

                } catch (Exception e) {
                    logger.error("somethings going wrong in retrieval",e);
                }
            }

这是Callable类

公共类FeedCacheCaller实现Callable {

String pid = null;
FeedCache feedCache;
public FeedCacheCaller(String pid) {
    this.pid = pid;
    this.feedCache =  new FeedCache();
}
@Override
public String call() throws Exception {
    return feedCache.get(pid);
}

}

编辑1:

这是Jedis的侧面代码。

    public class FeedCache {

    private ShardedJedisPool feedClient = RedisPool.getPool("feed");

    public String get(String key) {
    ShardedJedis client = null;
    String value = null;
    try {
        client = feedClient.getResource();
        byte[] valueByteArray = client.get(key.getBytes(Constants.CHARSET));
        if (valueByteArray != null) {
            value = new String(CacheUtils.decompress(valueByteArray),
                               Constants.CHARSET);
        }
    } catch (JedisConnectionException e) {
        if (client != null) {
            feedClient.returnBrokenResource(client);
            client = null;
        }
        logger.error(e.getMessage());
    } finally {
        if (client != null) {
            feedClient.returnResource(client);
        }
    }

    return value;
}

}

以下是初始化ShardedJedisPool

的代码
public class RedisPool {

private static final Logger logger = LoggerFactory.getLogger(
        RedisPool.class);

private static ConcurrentHashMap<String, ShardedJedisPool> redisPools = new ConcurrentHashMap<String, ShardedJedisPool>();

public static void initializePool(String poolName) {
    List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
    ArrayList<String> servers = new ArrayList<String>(Arrays.asList(
            Constants.config.getStringArray(
                poolName + "_redis_servers")));
    for (int i = 0; i < servers.size(); i++) {
        JedisShardInfo shardInfo = new JedisShardInfo(servers.get(i).split(":")[0], Integer.parseInt(servers.get(i).split(":")[1]));
        shards.add(shardInfo);
    }
    redisPools.putIfAbsent(poolName,
            new ShardedJedisPool(new GenericObjectPoolConfig(), shards));
}

public static ShardedJedisPool getPool(String poolName) {
    if (!redisPools.containsKey(poolName)) {
        synchronized (RedisPool.class) {
            if (!redisPools.containsKey(poolName)) {
                initializePool(poolName);
            }
        }
    }
    return redisPools.get(poolName);
}

public static void shutdown(String poolName) {
    ShardedJedisPool pool = getPool(poolName);
    pool.destroy();
    redisPools.remove(poolName);
}

public static void main(String args[]) {
    initializePool("vizidtoud");
}

}

0 个答案:

没有答案