Redisson config rework. Master/Slave support. #24
parent
96c7a19a03
commit
ca56f63d03
@ -0,0 +1,67 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2014 Nikita Koksharov, Nickolay Borbit
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.redisson;
|
||||||
|
|
||||||
|
|
||||||
|
class BaseConfig<T extends BaseConfig<T>> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Password for Redis authentication. Should be null if not needed
|
||||||
|
*/
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscriptions per Redis connection limit
|
||||||
|
*/
|
||||||
|
private int subscriptionsPerConnection = 5;
|
||||||
|
|
||||||
|
BaseConfig() {
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseConfig(T config) {
|
||||||
|
setPassword(config.getPassword());
|
||||||
|
setSubscriptionsPerConnection(config.getSubscriptionsPerConnection());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscriptions per Redis connection limit
|
||||||
|
* Default is 5
|
||||||
|
*
|
||||||
|
* @param subscriptionsPerConnection
|
||||||
|
*/
|
||||||
|
public T setSubscriptionsPerConnection(int subscriptionsPerConnection) {
|
||||||
|
this.subscriptionsPerConnection = subscriptionsPerConnection;
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
public int getSubscriptionsPerConnection() {
|
||||||
|
return subscriptionsPerConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Password for Redis authentication. Should be null if not needed
|
||||||
|
* Default is <code>null</code>
|
||||||
|
*
|
||||||
|
* @param password
|
||||||
|
*/
|
||||||
|
public T setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2014 Nikita Koksharov, Nickolay Borbit
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.redisson;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
|
public class SingleConnectionConfig extends BaseConfig<SingleConnectionConfig> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redis server address
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private URI address;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redis connection pool size limit
|
||||||
|
*/
|
||||||
|
private int connectionPoolSize = 100;
|
||||||
|
|
||||||
|
SingleConnectionConfig() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public SingleConnectionConfig(SingleConnectionConfig config) {
|
||||||
|
super(config);
|
||||||
|
setAddress(config.getAddress());
|
||||||
|
setConnectionPoolSize(config.getConnectionPoolSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redis connection pool size limit
|
||||||
|
* Default is 100
|
||||||
|
*
|
||||||
|
* @param connectionPoolSize
|
||||||
|
*/
|
||||||
|
public SingleConnectionConfig setConnectionPoolSize(int connectionPoolSize) {
|
||||||
|
this.connectionPoolSize = connectionPoolSize;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public int getConnectionPoolSize() {
|
||||||
|
return connectionPoolSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set server address. Use follow format -- host:port
|
||||||
|
*
|
||||||
|
* @param address
|
||||||
|
*/
|
||||||
|
public SingleConnectionConfig setAddress(String address) {
|
||||||
|
try {
|
||||||
|
this.address = new URI("//" + address);
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
throw new IllegalArgumentException("Can't parse " + address);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public URI getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
public void setAddress(URI address) {
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,117 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2014 Nikita Koksharov, Nickolay Borbit
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.redisson.connection;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.lambdaworks.redis.RedisConnection;
|
||||||
|
import com.lambdaworks.redis.codec.RedisCodec;
|
||||||
|
import com.lambdaworks.redis.pubsub.RedisPubSubConnection;
|
||||||
|
|
||||||
|
abstract class BaseLoadBalancer implements LoadBalancer {
|
||||||
|
|
||||||
|
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
|
private RedisCodec codec;
|
||||||
|
|
||||||
|
List<ConnectionEntry> clients;
|
||||||
|
|
||||||
|
public void init(List<ConnectionEntry> clients, RedisCodec codec) {
|
||||||
|
this.clients = clients;
|
||||||
|
this.codec = codec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RedisPubSubConnection nextPubSubConnection() {
|
||||||
|
List<ConnectionEntry> clientsCopy = new ArrayList<ConnectionEntry>(clients);
|
||||||
|
while (true) {
|
||||||
|
if (clientsCopy.isEmpty()) {
|
||||||
|
log.warn("Slave connection pool gets exhausted! Trying to acquire connection ...");
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
// TODO wait
|
||||||
|
//entry.getPoolSize().acquireUninterruptibly();
|
||||||
|
long endTime = System.currentTimeMillis() - time;
|
||||||
|
log.warn("Connection acquired, time spended: {} ms", endTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = getIndex(clientsCopy);
|
||||||
|
ConnectionEntry entry = clientsCopy.get(index);
|
||||||
|
|
||||||
|
if (!entry.getSubscribeConnectionsSemaphore().tryAcquire()) {
|
||||||
|
clientsCopy.remove(index);
|
||||||
|
} else {
|
||||||
|
RedisPubSubConnection conn = entry.getSubscribeConnections().poll();
|
||||||
|
if (conn != null) {
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
return entry.getClient().connectPubSub(codec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public RedisConnection nextConnection() {
|
||||||
|
List<ConnectionEntry> clientsCopy = new ArrayList<ConnectionEntry>(clients);
|
||||||
|
while (true) {
|
||||||
|
if (clientsCopy.isEmpty()) {
|
||||||
|
log.warn("Slave connection pool gets exhausted! Trying to acquire connection ...");
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
// TODO wait
|
||||||
|
//entry.getPoolSize().acquireUninterruptibly();
|
||||||
|
long endTime = System.currentTimeMillis() - time;
|
||||||
|
log.warn("Connection acquired, time spended: {} ms", endTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = getIndex(clientsCopy);
|
||||||
|
ConnectionEntry entry = clientsCopy.get(index);
|
||||||
|
|
||||||
|
if (!entry.getConnectionsSemaphore().tryAcquire()) {
|
||||||
|
clientsCopy.remove(index);
|
||||||
|
} else {
|
||||||
|
RedisConnection conn = entry.getConnections().poll();
|
||||||
|
if (conn != null) {
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
return entry.getClient().connect(codec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract int getIndex(List<ConnectionEntry> clientsCopy);
|
||||||
|
|
||||||
|
public void returnSubscribeConnection(RedisPubSubConnection connection) {
|
||||||
|
for (ConnectionEntry entry : clients) {
|
||||||
|
if (entry.getClient().equals(connection.getRedisClient())) {
|
||||||
|
entry.getSubscribeConnections().add(connection);
|
||||||
|
entry.getSubscribeConnectionsSemaphore().release();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void returnConnection(RedisConnection connection) {
|
||||||
|
for (ConnectionEntry entry : clients) {
|
||||||
|
if (entry.getClient().equals(connection.getRedisClient())) {
|
||||||
|
entry.getConnections().add(connection);
|
||||||
|
entry.getConnectionsSemaphore().release();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2014 Nikita Koksharov, Nickolay Borbit
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.redisson.connection;
|
||||||
|
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
|
|
||||||
|
import com.lambdaworks.redis.RedisClient;
|
||||||
|
import com.lambdaworks.redis.RedisConnection;
|
||||||
|
import com.lambdaworks.redis.pubsub.RedisPubSubConnection;
|
||||||
|
|
||||||
|
public class ConnectionEntry {
|
||||||
|
|
||||||
|
private final RedisClient client;
|
||||||
|
|
||||||
|
private final Semaphore subscribeConnectionsSemaphore;
|
||||||
|
private final Semaphore connectionsSemaphore;
|
||||||
|
|
||||||
|
private final Queue<RedisPubSubConnection> subscribeConnections = new ConcurrentLinkedQueue<RedisPubSubConnection>();
|
||||||
|
private final Queue<RedisConnection> connections = new ConcurrentLinkedQueue<RedisConnection>();
|
||||||
|
|
||||||
|
public ConnectionEntry(RedisClient client, int poolSize, int subscribePoolSize) {
|
||||||
|
super();
|
||||||
|
this.client = client;
|
||||||
|
this.connectionsSemaphore = new Semaphore(poolSize);
|
||||||
|
this.subscribeConnectionsSemaphore = new Semaphore(subscribePoolSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RedisClient getClient() {
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Semaphore getSubscribeConnectionsSemaphore() {
|
||||||
|
return subscribeConnectionsSemaphore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Semaphore getConnectionsSemaphore() {
|
||||||
|
return connectionsSemaphore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Queue<RedisPubSubConnection> getSubscribeConnections() {
|
||||||
|
return subscribeConnections;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Queue<RedisConnection> getConnections() {
|
||||||
|
return connections;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,37 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2014 Nikita Koksharov, Nickolay Borbit
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.redisson.connection;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import com.lambdaworks.redis.RedisClient;
|
|
||||||
|
|
||||||
public class RandomLoadBalancer implements LoadBalancer {
|
|
||||||
|
|
||||||
private final Random random = new Random();
|
|
||||||
|
|
||||||
private List<RedisClient> clients;
|
|
||||||
|
|
||||||
public void init(List<RedisClient> clients) {
|
|
||||||
this.clients = clients;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RedisClient nextClient() {
|
|
||||||
return clients.get(random.nextInt(clients.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2014 Nikita Koksharov, Nickolay Borbit
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.redisson.connection;
|
||||||
|
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
|
|
||||||
|
import org.redisson.Config;
|
||||||
|
import org.redisson.MasterSlaveConnectionConfig;
|
||||||
|
import org.redisson.SingleConnectionConfig;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class SingleConnectionManager extends MasterSlaveConnectionManager {
|
||||||
|
|
||||||
|
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
|
private Semaphore connections;
|
||||||
|
|
||||||
|
public SingleConnectionManager(SingleConnectionConfig cfg, Config config) {
|
||||||
|
MasterSlaveConnectionConfig newconfig = new MasterSlaveConnectionConfig();
|
||||||
|
String addr = cfg.getAddress().getHost() + ":" + cfg.getAddress().getPort();
|
||||||
|
newconfig.setMasterAddress(addr);
|
||||||
|
newconfig.addSlaveAddress(addr);
|
||||||
|
init(newconfig, config);
|
||||||
|
|
||||||
|
connections = new Semaphore(cfg.getConnectionPoolSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
void acquireMasterConnection() {
|
||||||
|
if (!connections.tryAcquire()) {
|
||||||
|
log.warn("Master connection pool gets exhausted! Trying to acquire connection ...");
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
connections.acquireUninterruptibly();
|
||||||
|
long endTime = System.currentTimeMillis() - time;
|
||||||
|
log.warn("Connection acquired, time spended: {} ms", endTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void releaseMasterConnection() {
|
||||||
|
connections.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void acquireSlaveConnection() {
|
||||||
|
acquireMasterConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
void releaseSlaveConnection() {
|
||||||
|
releaseMasterConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue