Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 在redis中使用多线程,使用jedis连接池_Multithreading_Redis - Fatal编程技术网

Multithreading 在redis中使用多线程,使用jedis连接池

Multithreading 在redis中使用多线程,使用jedis连接池,multithreading,redis,Multithreading,Redis,我已经读到redis是每个用户/客户端的单线程 可以使用jedis连接池实现多线程行为吗 基本上不同的绝地客户端请求将使用绝地连接池中启动的不同连接,向一台redis服务器发送命令 由于客户端请求使用不同的连接,因此一个redis应该是多个并行请求的服务器,对吗 我回答了类似的问题,您可以查看详细信息 TL/DR:Redis本身仍将是单线程的,但从总体上看,Redis回答问题所用的时间比联网所用的时间少一个数量级。您将从多线程中获益,是的 编辑:沿着请求管道,您将有3个点按顺序处理请求。当数据包

我已经读到redis是每个用户/客户端的单线程

可以使用jedis连接池实现多线程行为吗

基本上不同的绝地客户端请求将使用绝地连接池中启动的不同连接,向一台redis服务器发送命令


由于客户端请求使用不同的连接,因此一个redis应该是多个并行请求的服务器,对吗

我回答了类似的问题,您可以查看详细信息

TL/DR:Redis本身仍将是单线程的,但从总体上看,Redis回答问题所用的时间比联网所用的时间少一个数量级。您将从多线程中获益,是的


编辑:沿着请求管道,您将有3个点按顺序处理请求。当数据包通过一条线(您只有一条线,但来自不同请求的数据包将混合)向前和向后发送时,以及当Redis为您的请求提供服务时。但Redis本身也不是傻瓜。您的请求将来自网络套接字,并将被预处理并写入客户端缓冲区。这部分是并行处理的。然后Redis的主循环将从队列中选择命令,处理并将响应写入客户端缓冲区。这部分是按顺序完成的。然后,来自客户端缓冲区的响应将被打包并通过一条线路发送回您。这也是并行进行的。

可以使用绝地连接池实现多线程行为吗?

虽然您使用多个连接、线程或处理来与redis通信,但这些命令都放在一个队列中,redis将一个接一个地执行,而且每个命令都是原子的。因此,在redis方面,这仍然是一种单线程行为

由于客户端请求使用不同的连接,因此一个redis应该是并行处理多个请求的服务器,对吗?

并非总是,来自不同客户端的命令可能以任意顺序到达redis,因此如果这些命令具有某种数据关系,就会发生危险的事情

考虑这个简单的场景,如果redis有一个计数器S,如果所有客户机都执行INCR命令,那么就可以了,因为每个命令都是原子执行的,但是如果一些客户机的代码类似于:

s = get S
t = s + 10
set S t
那么事情就错了。您应该使用Multi/exec命令来确保Multi命令是原子的,而不仅仅是一个命令。有关redis中事务的更多信息,您可以参考。详细说明。

这在我的(基于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();      
}

}
公共类接口实现可关闭
{   
/*      
redis.clients
绝地武士
2.9.0
*/
private-JedisPool=null;
私有同步的void initializePool()
{
如果(0!=null)返回;
JedisPoolConfig poolConfig=新的JedisPoolConfig();
poolConfig.setMaxTotal(Integer.parseInt(AppConfig.REDIS_MAX_CONN));//最大CONN计数
poolConfig.setMaxIdle(Integer.parseInt(AppConfig.REDIS\u MAX\u IDLE\u CONN));//最大空闲连接计数
poolConfig.setMaxWaitMillis(Long.parseLong(AppConfig.REDIS_MAX_WAIT_TIME));//新连接的最大等待时间(引发异常之前)
jedisPool=新的jedisPool(池配置,
AppConfig.REDIS_IP,
整数.parseInt(AppConfig.REDIS_端口),
parseInt(AppConfig.REDIS_CONN_TIMEOUT));
}
//测试jedisPool.getResource()的线程安全性后未同步
受保护的绝地武士
{               
if(spool==null)
initializePool();
绝地武士=jedisPool.getResource();
返回绝地;
}
公共长集(最终字节[]键、最终字节[]字段、最终字节[]值)
{
绝地redis=null;
长ret=0升;
尝试
{
redis=getJedis();
ret=redis.hset(键、字段、值);
redis.expire(key,Integer.parseInt(AppConfig.redis\u expire\u MIN)*60);//
}
最后
{
如果(redis!=null)
redis.close();
}
返回ret;
}
公共字节[]获取(最终字节[]键,最终字节[]字段){
绝地redis=null;
byte[]valueBytes=null;
尝试
{
redis=getJedis();
valueBytes=redis.hget(键,字段);
}
最后
{       
如果(redis!=null)
redis.close();
}
返回valueBytes;
}
@凌驾
public void close()引发IOException{
if(spool!=null)
关闭();
}
}

如果一台redis服务器并行处理从一个客户端的两个不同连接发出的命令,您仍然可以回答吗?如果没有,那么为什么redis单线程只在用户级别?为什么在向redis发送请求时只有一根线,而我使用了多个不同的连接,使用了jedis连接池?那么,在您的客户端和redis实例之间有多少根线?通常是这样。实际上,您可以将其多路传输,但这很少有用。如果客户机和服务器在同一台物理机器上,您很可能会在这一部分进行保存,这取决于操作系统级别的驱动程序。如果您从线程1发送请求a,同时(实际上)从线程2发送请求B,那么您可能首先得到对a或B的响应。线程不会等待彼此。@ MaasxxENA你会考虑接受其中的一个答案还是对你还不清楚?