我已经读过redis是每个用户/客户端的单线程。
是否可以使用jedis连接池来实现多线程行为?
基本上不同的jedis客户端请求将使用从jedis连接池中获取的不同连接,将其命令发送到一个redis服务器。
由于客户端请求使用不同的连接,因此一个redis应该是服务器多个请求并行吗?
答案 0 :(得分:0)
我回答了类似的问题here,您可以查看详情。
TL / DR :Redis本身仍然是单线程的,但在Redis用来回答时间的宏观方案中,比网络使用的时间少了几个数量级。你会从多线程中受益,是的。
编辑:在请求管道中,您将有3个点可以按顺序处理请求。当数据包通过线路(您只有一根线路,但来自不同请求的数据包将被混合)向前和向后发送时,以及当Redis为您的请求提供服务时。但Redis本身也不傻。您的请求将来自网络套接字,并将进行预处理并写入客户端缓冲区。该部分是并行处理的。然后Redis的主循环将从队列中选择命令,处理并将响应写入客户端缓冲区。这部分是按顺序完成的。然后,客户端缓冲区的响应将被打包并通过电汇发回给您。这也是同时进行的。
答案 1 :(得分:0)
是否可以使用jedis连接池来实现多线程行为?
虽然您使用多个连接或线程或处理来与redis通信,但这些命令都放在一个队列中,redis将逐个获取并逐个执行。每个命令都是原子的。所以这仍然是redis方面的单线程行为。
由于客户端请求使用不同的连接,因此一个redis应该是服务器多个请求并行吗?
并非总是如此,来自不同客户端的命令可能以任意顺序到达redis,因此如果这些命令有一些数据关系,则会发生危险的事情。
考虑这个简单的场景,如果redis有一个计数器S,如果所有客户端都执行INCR命令,那就没关系,因为每个命令都是以原子方式执行的,但是如果某个客户端的代码是这样的话:< / p>
s = get S
t = s + 10
set S t
那么事情就错了。您应该使用Multi / exec命令来确保多个命令只是一个命令才是原子命令。有关redis中交易的更多信息,请参考this page。详细说明。
答案 2 :(得分:0)
这在我的(基于Web的)多线程环境中工作正常。
确保RedisInterface实例在您的类中是静态的。
public class RedisInterface implements Closeable
{
/*
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
*/
private JedisPool jedisPool = null;
private synchronized void initializePool()
{
if(jedisPool!=null) return;
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(Integer.parseInt(AppConfig.REDIS_MAX_CONN)); //max conn count
poolConfig.setMaxIdle(Integer.parseInt(AppConfig.REDIS_MAX_IDLE_CONN)); //max idle conn count
poolConfig.setMaxWaitMillis(Long.parseLong(AppConfig.REDIS_MAX_WAIT_TIME)); // max wait time for new connection (before throwing exception)
jedisPool = new JedisPool(poolConfig,
AppConfig.REDIS_IP,
Integer.parseInt(AppConfig.REDIS_PORT),
Integer.parseInt(AppConfig.REDIS_CONN_TIMEOUT));
}
//not synchronized after testing thread safety of jedisPool.getResource()
protected Jedis getJedis()
{
if(jedisPool==null)
initializePool();
Jedis jedis = jedisPool.getResource();
return jedis;
}
public Long set(final byte[] key, final byte[] field, final byte[] value)
{
Jedis redis = null;
Long ret =0L;
try
{
redis = getJedis();
ret = redis.hset(key, field, value);
redis.expire(key, Integer.parseInt(AppConfig.REDIS_EXPIRE_MIN)*60); //
}
finally
{
if(redis!=null)
redis.close();
}
return ret;
}
public byte[] get(final byte[] key, final byte[] field) {
Jedis redis = null ;
byte[] valueBytes = null;
try
{
redis = getJedis();
valueBytes = redis.hget(key, field);
}
finally
{
if(redis!=null)
redis.close();
}
return valueBytes;
}
@Override
public void close() throws IOException {
if(jedisPool!=null)
jedisPool.close();
}
}