您的位置:首页 > 数据库 > Redis

jedis针对三种redis工作模式、哨兵模式的源码阅读分析

2016-07-04 17:28 656 查看
只要是非单机模式,一定要配置JedisPoolConfig,无论何种集群,最终都是要通过它的源码中是这样写的

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

public class JedisPoolConfig extends GenericObjectPoolConfig {
public JedisPoolConfig() {
// defaults to make your life with connection pool easier :)
setTestWhileIdle(true);
setMinEvictableIdleTimeMillis(60000);
setTimeBetweenEvictionRunsMillis(30000);
setNumTestsPerEvictionRun(-1);
}
}

在spring配置中,如果想要更改其参数值,直接覆写该值即可。在Spring中这个基本连接池一般这样配置

<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="200" />
<property name="maxIdle" value="30" />
<property name="maxWaitMillis" value="30000" />
<property name="testOnBorrow" value="false" /><!-- 向调用者输出“链接”资源时,是否检测是有有效,如果无效则从连接池中移除,并尝试获取继续获取。设为true,一个挂都不能用 -->
<property name="testOnReturn" value="true" /><!-- 向连接池“归还”链接时,是否检测“链接”对象的有效性。 -->
</bean>


这里说的三种工作模式是指:

1、单机模式

Jedis jedis=new Jedis("192.168.0.100", 6379);

这种是最纯粹的单机模式,一般都采用连接池+连接工厂(JedisConnectionFactory)的模式进行开发

public class JedisConnectionFactory implements InitializingBean, DisposableBean, RedisConnectionFactory {

private final static Log log = LogFactory.getLog(JedisConnectionFactory.class);
private static final ExceptionTranslationStrategy EXCEPTION_TRANSLATION = new PassThroughExceptionTranslationStrategy(
JedisConverters.exceptionConverter());

private static final Method SET_TIMEOUT_METHOD;
private static final Method GET_TIMEOUT_METHOD;

private JedisShardInfo shardInfo;
private String hostName = "localhost";
private int port = Protocol.DEFAULT_PORT;
private int timeout = Protocol.DEFAULT_TIMEOUT;
private String password;
private boolean usePool = true;
private Pool<Jedis> pool;
private JedisPoolConfig poolConfig = new JedisPoolConfig();
private int dbIndex = 0;
private boolean convertPipelineAndTxResults = true;
private RedisSentinelConfiguration sentinelConfig;


由源码中分析可以得到,默认的主机名是localhst这个显然不行,肯定要覆盖重新主机为真是的IP地址,然后加上连接池信息,通过注入方式即可实现。

2、分片模式

通过分片池ShardedJedisPool 实现

通过阅读源码,我们可以看到它的其中一个构造函数为(CTRL+SHIFT_T直接源码中查找)

public class ShardedJedisPool extends Pool<ShardedJedis> {
public ShardedJedisPool(final GenericObjectPoolConfig poolConfig, List<JedisShardInfo> shards) {
this(poolConfig, shards, Hashing.MURMUR_HASH);
}

根据这个构造函数,我们可以在spring实现它

<!-- redis sharding -->
<bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool">
<constructor-arg index="0" ref="jedisPoolConfig" />
<constructor-arg index="1">
<list>
<bean name="redis1" class="com.my.cache.MyJedisShardInfo">
<constructor-arg index="0" value="${redis.slaver1.host}" />
<constructor-arg index="1" value="${redis.client.connectionTimeout}" />
<constructor-arg index="2" value="${redis.client.soTimeout}" />
</bean>
<bean name="redis2" class="com.my.cache.MyJedisShardInfo">
<constructor-arg index="0" value="${redis.slaver2.host}" />
<constructor-arg index="1" value="${redis.client.connectionTimeout}" />
<constructor-arg index="2" value="${redis.client.soTimeout}" />
</bean>
</list>
</constructor-arg>
</bean>


3、集群模式(since 3.0)

通过JedisCluster实现,源码构造函数如下所示,一般集群环境中,我们要加上基本连接池,所以选择第一个构造函数。

public class JedisCluster implements JedisCommands, BasicCommands, Closeable {
public static final short HASHSLOTS = 16384;
private static final int DEFAULT_TIMEOUT = 2000;
private static final int DEFAULT_MAX_REDIRECTIONS = 5;

public static enum Reset {
SOFT, HARD
}

private int maxRedirections;

private JedisClusterConnectionHandler connectionHandler;

public JedisCluster(Set<HostAndPort> nodes, final GenericObjectPoolConfig poolConfig) {
this(nodes, DEFAULT_TIMEOUT, DEFAULT_MAX_REDIRECTIONS, poolConfig);
}

public JedisCluster(Set<HostAndPort> nodes) {
this(nodes, DEFAULT_TIMEOUT);
}


哨兵模式是通过JedisSentinelPool 实现的,源代码如下

public class JedisSentinelPool extends Pool<Jedis> {

protected GenericObjectPoolConfig poolConfig;

protected int timeout = Protocol.DEFAULT_TIMEOUT;

protected String password;

protected int database = Protocol.DEFAULT_DATABASE;

protected Set<MasterListener> masterListeners = new HashSet<MasterListener>();

protected Logger log = Logger.getLogger(getClass().getName());

private volatile JedisFactory factory;
private volatile HostAndPort currentHostMaster;

public JedisSentinelPool(String masterName, Set<String> sentinels,
final GenericObjectPoolConfig poolConfig) {
this(masterName, sentinels, poolConfig, Protocol.DEFAULT_TIMEOUT, null,
Protocol.DEFAULT_DATABASE);
}

这样在spring就可以这样写,第一个构造函数的参数为master服务器,这个由于在源码中没有单独写出来,所以我们只能用构造器方式去射入值。

<bean id="jedisPool" class="redis.clients.jedis.JedisSentinelPool">
<constructor-arg index="0" value="mymaster" />
<constructor-arg index="1">
<set>
<value>127.0.0.1:26379</value>
<value>127.0.0.1:36379</value><!--配置了两个哨兵 -->
</set>
</constructor-arg>
<constructor-arg index="2" ref="jedisPoolConfig" />
</bean>


通过配置后,在程序中就可以直接引用:

@Resource
private JedisSentinelPool jedisSentinelPool;

然后通过jedis=jedisSentinelPool.getResource();就可以获取当前的jedis了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: