我指的是这个 SO question ,并且我在此基准测试中做了一些补充。主要问题是随着服务器负载的增加,我的 api 越来越慢。我正在使用 jedis 池配置。
// get a new instance
public synchronized Jedis getJedi() {
try {
return jedisPool.getResource();
} catch (Exception e) {
log.fatal("REDIS CONN ERR:", e);
return null;
}
}
// intialize at start
public void initialize() {
if (jedisPool == null) {
IniUtils cp = PropertyReader.getConnPoolIni();
String host = cp.get(REDIS, REDIS_HOST);
int port = Integer.parseInt(cp.get(REDIS, REDIS_PORT));
String password = cp.get(REDIS, REDIS_PASSWORD);
int timeout = Integer.parseInt(cp.get(REDIS, REDIS_TIMEOUT));
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(Integer.parseInt(cp.get(REDIS, REDIS_MAX_TOTAL_CONNECTIONS)));
poolConfig.setMaxIdle(Integer.parseInt(cp.get(REDIS, REDIS_MAX_IDLE)));
poolConfig.setMinIdle(Integer.parseInt(cp.get(REDIS, REDIS_MIN_IDLE)));
poolConfig.setMaxWaitMillis(Long.parseLong(cp.get(REDIS, REDIS_MAX_WAIT_TIME_MILLIS)));
poolConfig.setTestOnBorrow(true);
poolConfig.setTestOnReturn(true);
poolConfig.setTestWhileIdle(true);
if (password != null && !password.trim().isEmpty()) {
jedisPool = new JedisPool(poolConfig, host, port, timeout, password);
} else {
jedisPool = new JedisPool(poolConfig, host, port, timeout);
}
test();
}
}
@Override
public void destroy() {
if (jedisPool.isClosed() == false)
jedisPool.destroy();
}
private void test() {
try (Jedis test = getJedi()) {
log.info("Testing Redis:" + test.ping());
}
}
在使用时,我在 try-with-resources 中获取 Jedis 实例并对其进行处理。我使用的流水线非常少,并且有各种对 Redis 的调用,所以每次方法调用时,都会创建一个新的 jedis 实例。
根据共享的 SO 问题,我的实现将导致非常缓慢的结果。那么,我可以将 Jedis 实例传递给方法并根据业务逻辑使用管道吗? 像这样的 -
public void push5(int n) {
try (Jedis jedi = redisFactory.getJedi()) {
pushWithResource(n, jedi, 0);
}
}
public void pushWithResourceAndPipe(int n, Jedis jedi, int k) {
if (k >= n)
return;
Pipeline pipeline = jedi.pipelined();
map.put("id", "" + i);
map.put("name", "lyj" + i);
pipeline.hmset("m" + i, map);
++i;
pushWithResourceAndPipe(n, jedi, ++k);
pipeline.sync();
}
public void pushWithResource(int n, Jedis jedi, int k) {
if (k >= n)
return;
map.put("id", "" + i);
map.put("name", "lyj" + i);
jedi.hmset("m" + i, map);
++i;
pushWithResource(n, jedi, ++k);
}
有什么方法可以改进 api 调用吗? 你能推荐一些在服务器端使用jedis的项目吗,这样我就能更好地理解如何有效地使用jedis。
Redis/Jedis 配置
绝地武士版本:2.8.1 Redis版本:2.8.4 Java版本:1.8
最佳答案
- getJedi 不需要“同步”,因为 JedisPool 是线程安全的。
- 如果您的逻辑可以容忍 setTestOnBorrow 增加延迟,您可以禁用其他功能(setTestOnReturn、setTestWhileIdle)。如果您的逻辑可以容忍重试,禁用 setTestOnBorrow 应该会有所帮助。 (因为它总是对每次借贷进行乒乓检查)
- 您的 pushWithResourceAndPipe 有错误:您正在为每个递归调用创建管道实例,这可能比 pushWithResource“慢”。我认为您打算将所有请求添加到一个管道并同步,然后您需要传递管道实例并从调用方调用同步。
关于java - 在方法之间传递 jedis 实例是一种不好的做法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40722479/