上一章节我们通过jedis学习了实现存放机制,本章节我们通过jedisPool的操作理解连接池的应用,jedisPool的源码实现。
jedisPool连接池示例
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class JedisPoolUtil {
private volatile JedisPool pool;
private Jedis jedis;
private final String host;
private final int port;
private String password;
public JedisPoolUtil(final String host, final int port) {
this.host = host;
this.port = port;
initPool();
}
public JedisPoolUtil(final String host, final int port, final String password) {
this.host = host;
this.port = port;
this.password = password;
initPool();
}
public JedisPool initPool() {
if (pool == null) {
if (password != null) {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxIdle(100);
config.setMaxWaitMillis(1000);
// 设置空间连接
config.setMaxIdle(10);
pool = new JedisPool(config, host, port, 2000, password);
} else {
pool = new JedisPool(host, port);
}
System.out.println("连接池创建成功");
}
return pool;
}
public Jedis initJedis() {
if(jedis==null) {
jedis = pool.getResource();
}
System.out.println("jedis创建成功");
return jedis;
}
public String set(String key, String value) {
if (jedis == null) {
jedis = initJedis();
}
String result = jedis.set(key, value);
if ("OK".equals(result)) {
jedis.close();
}
return result;
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
JedisPoolUtil jedisPoolUtil = new JedisPoolUtil("127.0.0.1", 4100);
System.out.println(jedisPoolUtil.set("test" + i, "value" + i));
}
}
}
使用jedisPool连接池,实例化jedisPool对象,jedisPool类提供了很多构造方法,可以根据自己的需要去选择构造方法,
public
JedisPool(String
host
,
int
port
) {
this
(
new
GenericObjectPoolConfig(),
host
,
port
, Protocol.
DEFAULT_TIMEOUT
,
null
,
Protocol.
DEFAULT_DATABASE
,
null
);
}
public
JedisPool
(
final
GenericObjectPoolConfig
poolConfig
,
final
String
host
,
int
port
,
final
int
connectionTimeout
,
final
int
soTimeout
,
final
String
password
,
final
int
database
,
final
String
clientName
,
final
boolean
ssl
,
final
SSLSocketFactory
sslSocketFactory
,
final
SSLParameters
sslParameters
,
final
HostnameVerifier
hostnameVerifier
) {
super
(
poolConfig
,
new
JedisFactory(
host
,
port
,
connectionTimeout
,
soTimeout
,
password
,
database
,
clientName
,
ssl
,
sslSocketFactory
,
sslParameters
,
hostnameVerifier
));
}
public
JedisPool(
final
GenericObjectPoolConfig
poolConfig
,
final
URI
uri
,
final
int
timeout
,
final
SSLSocketFactory
sslSocketFactory
,
final
SSLParameters
sslParameters
,
final
HostnameVerifier
hostnameVerifier
) {
this
(
poolConfig
,
uri
,
timeout
,
timeout
,
sslSocketFactory
,
sslParameters
,
hostnameVerifier
);
}
public
JedisPool(
final
GenericObjectPoolConfig
poolConfig
,
final
URI
uri
,
final
int
connectionTimeout
,
final
int
soTimeout
) {
super
(
poolConfig
,
new
JedisFactory(
uri
,
connectionTimeout
,
soTimeout
,
null
,
false
,
null
,
null
,
null
));
}
public
JedisPool(
final
GenericObjectPoolConfig
poolConfig
,
final
URI
uri
,
final
int
connectionTimeout
,
final
int
soTimeout
,
final
SSLSocketFactory
sslSocketFactory
,
final
SSLParameters
sslParameters
,
final
HostnameVerifier
hostnameVerifier
) {
super
(
poolConfig
,
new
JedisFactory(
uri
,
connectionTimeout
,
soTimeout
,
null
,
(
uri
.getScheme() !=
null
&&
uri
.getScheme().equals(
"rediss"
)),
sslSocketFactory
,
sslParameters
,
hostnameVerifier
));
}
这里实例化了一个实现了
org.apache.commons.pool2.PooledObjectFactory<Jedis>接口类的JedisFactory工厂类对象,该所有对象的创建销毁、激活和有效性验证都在JedisFactory工厂类中进行,
poolObjectFactory提供了五个接口方法:
public
interface
PooledObjectFactory<T> {
PooledObject<T> makeObject()
throws
Exception;//
创建对象的方法
void
destroyObject(PooledObject<T>
p
)
throws
Exception;//
销毁对象的方法。
boolean
validateObject(PooledObject<T>
p
);
//
校验对象有消息的方法。
void
activateObject(PooledObject<T>
p
)
throws
Exception;//
激活对象的方法
void
passivateObject(PooledObject<T>
p
)
throws
Exception;//
钝化对象的方法。
返回到空闲对象实例池
}
由于jedisPool继承了
Pool<Jedis>,Pool实现了
Closeable接口,最终委托了pool的实例化方法,调用了Pool类中的initPoll方法,在initPool方法中new了一个
GenericObjectPool方法,该方法是
org
.
apache
.
commons
.
pool2
.
impl
.
GenericObjectPool
.GenericObjectPool中的连接池实现方法
public
Pool
(
final
GenericObjectPoolConfig
poolConfig
, PooledObjectFactory<T>
factory
) {
initPool(
poolConfig
,
factory
);
}
public
void
initPool(
final
GenericObjectPoolConfig
poolConfig
, PooledObjectFactory<T>
factory
) {
if
(
this
.
internalPool
!=
null
) {
try
{
closeInternalPool();
}
catch
(Exception
e
) {
}
}
this
.
internalPool
=
new
GenericObjectPool
<T>(
factory
,
poolConfig
);
}
GenericObjectPool方法中有两个参数:一个
GenericObjectPoolConfig配置项分装类,一个是
PooledObjectFactory工厂类
获取到连接池后从连接池中获取jedis连接对象
@Override
public
Jedis
getResource
() {
Jedis
jedis
=
super
.getResource();
jedis
.setDataSource(
this
);
return
jedis
;
}
public
T
getResource
() {
try
{
return
internalPool
.borrowObject();
}
catch
(NoSuchElementException
nse
) {
throw
new
JedisException(
"Could not get a resource from the pool"
,
nse
);
}
catch
(Exception
e
) {
throw
new
JedisConnectionException(
"Could not get a resource from the pool"
,
e
);
}
}
对于jedis Pool只能进行单实例的链接操作,但是对于数据量大的时候,单实例不能满足需求.
这个时候就需要对实例进行“分片”。Jedis也是提供了分片的支持,后面也会总结一个jedis分片的实现.