一个高性能的支持丰富数据结构的 NoSQL 数据库, 用于替代 Redis.,目前有一些互联网公司都在使用ssdb,比如360,百度等。官方提供了多种语言的client实现,但是没有给出一个高效的连接池方案,因此本文结合项目的使用,给出一个java版本的ssdb连接池方案。
(注意:SSDB,Link,Response,MemoryStream,4个类的实现,请参考官方代码,这里不提供)
public class SSDBPool {
private static final Logger logger = LogManager.getLogger(SSDBPool.class);
private String host; //连接ip
private int port; //连接端口
private int timeoutMs; //连接超时
private int count; //连接数大小
private final Map connMap;
public SSDBPool(String host, int port) {
this(host, port, 5,0);
}
public SSDBPool(String host, int port, int count) {
this(host, port, count, 0);
}
public SSDBPool(String host, int port, int count, int timeoutMs) {
if (count <= 0) {
throw new IllegalArgumentException("Illegal connect count: " + count);
}
this.host = host;
this.port = port;
this.timeoutMs = timeoutMs;
this.count = count;
this.connMap = new HashMap<>(this.count);
try {
for (int i = 0; i < this.count; i++) {
connMap.put(new SSDB(host,port,timeoutMs),0);
}
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
private SSDB getSSDB() throws Exception {
while(true) {
// 线程同步处理,没有可以用的连接,则线程阻塞
synchronized (connMap) {
for (Map.Entry entry : connMap.entrySet()) {
if (entry.getValue() == 0) {
entry.setValue(1);
return entry.getKey();
}
}
if (connMap.size() < count) {
SSDB ssdb = new SSDB(host, port, timeoutMs);
connMap.put(ssdb, 1);
return ssdb;
} else {
connMap.wait();
}
}
}
}
private void releaseSSDB(SSDB ssdb, boolean remove) {
// 线程同步处理,释放连接,唤醒阻塞线程
synchronized (connMap) {
try {
if (remove) {
connMap.remove(ssdb);
} else if (ssdb != null){
connMap.put(ssdb, 0);
}
} catch (Exception e) {
logger.warn("releaseSSDB fail, mgs={}", e.getMessage());
}
connMap.notifyAll();
}
}
public String getValue(String key) {
//针对异常连接进行重试,重试次数为连接数,防止连接自动断开
return getValue(key, count);
}
private String getValue(String key, int tryTimes) {
SSDB ssdb = null;
try {
ssdb = this.getSSDB();
byte[] content = ssdb.get(key);
if (null != content) {
this.releaseSSDB(ssdb, false);
return new String(content,"UTF-8");
}
this.releaseSSDB(ssdb, false);
return null;
} catch (Exception e) {
logger.warn("key={},msg={}", key, e.getMessage());
this.releaseSSDB(ssdb, true);
//针对异常连接进行重试
if (tryTimes > 0) {
return getValue(key, tryTimes -1);
} else {
return null;
}
}
}
public int getTtl(String key) {
return getTtl(key, count);
}
private int getTtl(String key, int tryTime) {
SSDB ssdb = null;
try {
ssdb = this.getSSDB();
byte[] content = ssdb.ttl(key);
if (null != content) {
this.releaseSSDB(ssdb, false);
String ttlStr = new String(content,"UTF-8");
return Integer.parseInt(ttlStr);
}
this.releaseSSDB(ssdb, false);
return -1;
} catch (Exception e) {
logger.warn(e.getMessage());
this.releaseSSDB(ssdb, true);
if (tryTime > 0) {
return getTtl(key, tryTime -1);
} else {
return -1;
}
}
}
public void save(String key, String value) {
save(key, value, count);
}
private void save(String key, String value, int tryTimes) {
SSDB ssdb = null;
try {
ssdb = this.getSSDB();
ssdb.set(key, value.getBytes("UTF-8"));
this.releaseSSDB(ssdb, false);
} catch (Exception e) {
logger.warn("key={},value={},msg={}", key, value, e.getMessage());
this.releaseSSDB(ssdb, true);
if (tryTimes > 0) {
save(key, value, tryTimes -1);
}
}
}
public void save(String key, String value, Integer ttl) {
save(key, value, ttl, count);
}
private void save(String key, String value, Integer ttl, int tryTimes) {
SSDB ssdb = null;
try {
ssdb = this.getSSDB();
ssdb.setx(key, value.getBytes("UTF-8"), ttl);
this.releaseSSDB(ssdb, false);
} catch (Exception e) {
logger.warn("key={},value={},msg={}", key, value, e.getMessage());
this.releaseSSDB(ssdb, true);
if (tryTimes > 0) {
save(key, value, ttl,tryTimes -1);
}
}
}
public void del(String key) {
this.del(key, count);
}
private void del(String key, int tryTimes) {
SSDB ssdb = null;
try {
ssdb = this.getSSDB();
ssdb.del(key);
this.releaseSSDB(ssdb, false);
} catch (Exception e) {
logger.warn("key={},msg={}", key, e.getMessage());
this.releaseSSDB(ssdb, true);
if (tryTimes > 0) {
del(key,tryTimes -1);
}
}
}
public String monitor() {
return "connect state:" + this.connMap.values();
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public int getTimeoutMs() {
return timeoutMs;
}
public void setTimeoutMs(int timeoutMs) {
this.timeoutMs = timeoutMs;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}