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