redis单例提供了一种数据缓存方式和丰富的数据操作api,但是将数据完全存储在单个redis中主要存在两个问题:数据备份和数据体量较大造成的性能降低。这里redis的主从模式为这两个问题提供了一个较好的解决方案。
主从模式指的是使用一个redis实例作为主机,其余的实例作为备份机。主机和从机的数据完全一致,主机支持数据的写入和读取等各项操作,而从机则只支持与主机数据的同步和读取,也就是说,客户端可以将数据写入到主机,由主机自动将数据的写入操作同步到从机。
主从模式很好的解决了数据备份问题,并且由于主从服务数据几乎是一致的,因而可以将写入数据的命令发送给主机执行,
而读取数据的命令发送给不同的从机执行,从而达到读写分离的目的。如下所示主机redis-A分别有redis-B、redis-C、redis-D、redis-E四个从机:
一:搭建Redis的主从模式环境:
redis主从模式的配置可以理解为多个不同的redis实例通过一定的配置告知其相互之间的主从关系。
而前面已经介绍,每个redis实例都会占用一个本机的端口号,主从模式的配置主要的配置点有两个:当前实例端口号和当前实例是主机还是从机,是从机的话其主机的ip和端口是什么。一般的redis目录下的redis.conf保存的是默认配置,尽量不要对其进行修改,这里我们复制三份redis.conf文件,分别命名为6379.conf,6380.conf和6381.conf,如下是端口为6379的主机的主要配置:
每一个对应的配置如下,注意修改端口号和主机名称
bind 127.0.0.1
port 6381
logfile "6381.log"
dbfilename "dump-6381.rdb"
slaveof 127.0.0.1 6379
依次修改配置后启动:
./src/redis-server 6379.conf
./src/redis-server 6380.conf
./src/redis-server 6381.conf
分别在三个命令行工具中执行一个get命令,获取键名为msg的数据,如下所示:
客户端连接:
采用Redission客户端进行连接:
导入依赖如下:
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>2.6.0</version>
</dependency>
package com.ishangjie.config;
import org.redisson.Redisson;
import org.redisson.api.*;
import org.redisson.client.codec.Codec;
import org.redisson.codec.CodecProvider;
import org.redisson.config.Config;
import org.redisson.liveobject.provider.ResolverProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import java.util.concurrent.TimeUnit;
/**
* redisson分布式锁解决方案
* @author liuty
*
*/
@Configuration
public class RedissonProxy implements RedissonClient{
@Value("${redis.hostname}")
private String hostName;
@Value("${redis.port}")
private String port;
private String password;
@Value("${redis.connectionMinimumIdleSize}")
private int connectionMinimumIdleSize;
@Value("${redis.connectionPoolSize}")
private int connectionPoolSize;
private int connectTimeout = 10000;
/**
* Redis server response timeout. Starts to countdown when Redis command was succesfully sent.
* Value in milliseconds.
*
*/
private int timeout = 3000;
private RedissonClient delegateRedissonClient;
public String getHostName() {
return hostName;
}
public void setHostName(String hostName) {
this.hostName = hostName;
}
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getConnectionPoolSize() {
return connectionPoolSize;
}
public void setConnectionPoolSize(int connectionPoolSize) {
this.connectionPoolSize = connectionPoolSize;
}
@PostConstruct
public void init() {
Config config = new Config();
String address = hostName + ":" + port;
config.useSingleServer()
.setAddress(address)
.setPassword(password)
.setConnectionMinimumIdleSize(connectionMinimumIdleSize)
.setConnectionPoolSize(connectionPoolSize)
.setTimeout(timeout)
.setConnectTimeout(connectTimeout);
delegateRedissonClient = Redisson.create(config);
}
@Override
public RBinaryStream getBinaryStream(String name) {
return delegateRedissonClient.getBinaryStream(name);
}
@Override
public <V> RGeo<V> getGeo(String name) {
return delegateRedissonClient.getGeo(name);
}
@Override
public <V> RGeo<V> getGeo(String name, Codec codec) {
return delegateRedissonClient.getGeo(name, codec);
}
@Override
public <V> RSetCache<V> getSetCache(String name) {
return delegateRedissonClient.getSetCache(name);
}
@Override
public <V> RSetCache<V> getSetCache(String name, Codec codec) {
return delegateRedissonClient.getSetCache(name, codec);
}
@Override
public <K, V> RMapCache<K, V> getMapCache(String name, Codec codec) {
return delegateRedissonClient.getMapCache(name, codec);
}
@Override
public <K, V> RMapCache<K, V> getMapCache(String name) {
return delegateRedissonClient.getMapCache(name);
}
@Override
public <V> RBucket<V> getBucket(String name) {
return delegateRedissonClient.getBucket(name);
}
@Override
public <V> RBucket<V> getBucket(String name, Codec codec) {
return delegateRedissonClient.getBucket(name, codec);
}
@Override
public RBuckets getBuckets() {
return delegateRedissonClient.getBuckets();
}
@Override
public RBuckets getBuckets(Codec codec) {
return delegateRedissonClient.getBuckets(codec);
}
@Override
public <V> RHyperLogLog<V> getHyperLogLog(String name) {
return delegateRedissonClient.getHyperLogLog(name);
}
@Override
public <V> RHyperLogLog<V> getHyperLogLog(String name, Codec codec) {
return delegateRedissonClient.getHyperLogLog(name, codec);
}
@Override
public <V> RList<V> getList(String name) {
return delegateRedissonClient.getList(name);
}
@Override
public <V> RList<V> getList(String name, Codec codec) {
return delegateRedissonClient.getList(name, codec);
}
@Override
public <K, V> RListMultimap<K, V> getListMultimap(String name) {
return delegateRedissonClient.getListMultimap(name);
}
@Override
public <K, V> RListMultimap<K, V> getListMultimap(String name, Codec codec) {
return delegateRedissonClient.getListMultimap(name, codec);
}
@Override
public <K, V> RListMultimapCache<K, V> getListMultimapCache(String name) {
return delegateRedissonClient.getListMultimapCache(name);
}
@Override
public <K, V> RListMultimapCache<K, V> getListMultimapCache(String name, Codec codec) {
return delegateRedissonClient.getListMultimapCache(name, codec);
}
@Override
public <K, V> RMap<K, V> getMap(String name) {
return delegateRedissonClient.getMap(name);
}
@Override
public <K, V> RMap<K, V> getMap(String name, Codec codec) {
return delegateRedissonClient.getMap(name, codec);
}
@Override
public <K, V> RSetMultimap<K, V> getSetMultimap(String name) {
return delegateRedissonClient.getSetMultimap(name);
}
@Override
public <K, V> RSetMultimap<K, V> getSetMultimap(String name, Codec codec) {
return delegateRedissonClient.getSetMultimap(name, codec);
}
@Override
public <K, V> RSetMultimapCache<K, V> getSetMultimapCache(String name) {
return delegateRedissonClient.getSetMultimapCache(name);
}
@Override
public <K, V> RSetMultimapCache<K, V> getSetMultimapCache(String name, Codec codec) {
return delegateRedissonClient.getSetMultimapCache(name, codec);
}
@Override
public RSemaphore getSemaphore(String name) {
return delegateRedissonClient.getSemaphore(name);
}
@Override
public RPermitExpirableSemaphore getPermitExpirableSemaphore(String name) {
return delegateRedissonClient.getPermitExpirableSemaphore(name);
}
@Override
public RLock getLock(String name) {
return delegateRedissonClient.getLock(name);
}
@Override
public RLock getFairLock(String name) {
return delegateRedissonClient.getFairLock(name);
}
@Override
public RReadWriteLock getReadWriteLock(String name) {
return delegateRedissonClient.getReadWriteLock(name);
}
@Override
public <V> RSet<V> getSet(String name) {
return delegateRedissonClient.getSet(name);
}
@Override
public <V> RSet<V> getSet(String name, Codec codec) {
return delegateRedissonClient.getSet(name, codec);
}
@Override
public <V> RSortedSet<V> getSortedSet(String name) {
return delegateRedissonClient.getSortedSet(name);
}
@Override
public <V> RSortedSet<V> getSortedSet(String name, Codec codec) {
return delegateRedissonClient.getSortedSet(name, codec);
}
@Override
public <V> RScoredSortedSet<V> getScoredSortedSet(String name) {
return delegateRedissonClient.getScoredSortedSet(name);
}
@Override
public <V> RScoredSortedSet<V> getScoredSortedSet(String name, Codec codec) {
return delegateRedissonClient.getScoredSortedSet(name, codec);
}
@Override
public RLexSortedSet getLexSortedSet(String name) {
return delegateRedissonClient.getLexSortedSet(name);
}
@Override
public <M> RTopic<M> getTopic(String name) {
return delegateRedissonClient.getTopic(name);
}
@Override
public <M> RTopic<M> getTopic(String name, Codec codec) {
return delegateRedissonClient.getTopic(name, codec);
}
@Override
public <M> RPatternTopic<M> getPatternTopic(String pattern) {
return delegateRedissonClient.getPatternTopic(pattern);
}
@Override
public <M> RPatternTopic<M> getPatternTopic(String pattern, Codec codec) {
return delegateRedissonClient.getPatternTopic(pattern, codec);
}
@Override
public <V> RQueue<V> getQueue(String name) {
return delegateRedissonClient.getQueue(name);
}
@Override
public <V> RQueue<V> getQueue(String name, Codec codec) {
return delegateRedissonClient.getQueue(name, codec);
}
@Override
public <V> RBlockingQueue<V> getBlockingQueue(String name) {
return delegateRedissonClient.getBlockingDeque(name);
}
@Override
public <V> RBlockingQueue<V> getBlockingQueue(String name, Codec codec) {
return delegateRedissonClient.getBlockingQueue(name, codec);
}
@Override
public <V> RBoundedBlockingQueue<V> getBoundedBlockingQueue(String name) {
return delegateRedissonClient.getBoundedBlockingQueue(name);
}
@Override
public <V> RBoundedBlockingQueue<V> getBoundedBlockingQueue(String name, Codec codec) {
return delegateRedissonClient.getBoundedBlockingQueue(name, codec);
}
@Override
public <V> RDeque<V> getDeque(String name) {
return delegateRedissonClient.getDeque(name);
}
@Override
public <V> RDeque<V> getDeque(String name, Codec codec) {
return delegateRedissonClient.getDeque(name, codec);
}
@Override
public <V> RBlockingDeque<V> getBlockingDeque(String name) {
return delegateRedissonClient.getBlockingDeque(name);
}
@Override
public <V> RBlockingDeque<V> getBlockingDeque(String name, Codec codec) {
return delegateRedissonClient.getBlockingDeque(name, codec);
}
@Override
public RAtomicLong getAtomicLong(String name) {
return delegateRedissonClient.getAtomicLong(name);
}
@Override
public RAtomicDouble getAtomicDouble(String name) {
return delegateRedissonClient.getAtomicDouble(name);
}
@Override
public RCountDownLatch getCountDownLatch(String name) {
return delegateRedissonClient.getCountDownLatch(name);
}
@Override
public RBitSet getBitSet(String name) {
return delegateRedissonClient.getBitSet(name);
}
@Override
public <V> RBloomFilter<V> getBloomFilter(String name) {
return delegateRedissonClient.getBloomFilter(name);
}
@Override
public <V> RBloomFilter<V> getBloomFilter(String name, Codec codec) {
return delegateRedissonClient.getBloomFilter(name, codec);
}
@Override
public RScript getScript() {
return delegateRedissonClient.getScript();
}
@Override
public RScheduledExecutorService getExecutorService(String name) {
return delegateRedissonClient.getExecutorService(name);
}
@Override
@Deprecated
public RScheduledExecutorService getExecutorService(Codec codec, String name) {
return delegateRedissonClient.getExecutorService(codec, name);
}
@Override
public RRemoteService getRemoteService() {
return delegateRedissonClient.getRemoteService();
}
@Override
public RRemoteService getRemoteService(Codec codec) {
return delegateRedissonClient.getRemoteService(codec);
}
@Override
public RRemoteService getRemoteService(String name) {
return delegateRedissonClient.getRemoteService(name);
}
@Override
public RRemoteService getRemoteService(String name, Codec codec) {
return delegateRedissonClient.getRemoteService(name, codec);
}
@Override
public RBatch createBatch() {
return delegateRedissonClient.createBatch();
}
@Override
public RKeys getKeys() {
return delegateRedissonClient.getKeys();
}
@Override
public RLiveObjectService getLiveObjectService() {
return delegateRedissonClient.getLiveObjectService();
}
@Override
public void shutdown() {
delegateRedissonClient.shutdown();
}
@Override
public void shutdown(long quietPeriod, long timeout, TimeUnit unit) {
delegateRedissonClient.shutdown(quietPeriod,timeout,unit);
}
@Override
public Config getConfig() {
return delegateRedissonClient.getConfig();
}
@Override
public NodesGroup<Node> getNodesGroup() {
return delegateRedissonClient.getNodesGroup();
}
@Override
public ClusterNodesGroup getClusterNodesGroup() {
return delegateRedissonClient.getClusterNodesGroup();
}
@Override
public boolean isShutdown() {
return delegateRedissonClient.isShutdown();
}
@Override
public boolean isShuttingDown() {
return delegateRedissonClient.isShuttingDown();
}
@Override
public CodecProvider getCodecProvider() {
return delegateRedissonClient.getCodecProvider();
}
@Override
public <K, V> RLocalCachedMap<K, V> getLocalCachedMap(String key, LocalCachedMapOptions options) {
return delegateRedissonClient.getLocalCachedMap(key, options);
}
@Override
public <K, V> RLocalCachedMap<K, V> getLocalCachedMap(String key, Codec codec, LocalCachedMapOptions options) {
return delegateRedissonClient.getLocalCachedMap(key, codec,options);
}
@Override
public ResolverProvider getResolverProvider() {
return delegateRedissonClient.getResolverProvider();
}
public int getConnectionMinimumIdleSize() {
return connectionMinimumIdleSize;
}
public void setConnectionMinimumIdleSize(int connectionMinimumIdleSize) {
this.connectionMinimumIdleSize = connectionMinimumIdleSize;
}
public int getConnectTimeout() {
return connectTimeout;
}
public void setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
}
application.yml 的配置信息如下
redis:
hostname: 192.168.63.133
port: 6379
connectionMinimumIdleSize: 10
connectTimeout: 1000
timeout: 3000
connectionPoolSize: 64
调用方式如下:
package com.ishangjie.controller;
import com.ishangjie.config.RedissonProxy;
import com.ishangjie.service.Aservice;
import org.redisson.api.RBucket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
/**
* @describe: 注册功能
* author: liutengyuan
* @date: Created in 2019/2/27 16:19
**/
@RestController
public class Acontroller {
@Autowired
private Aservice aservice;
@Autowired
RedissonProxy redissonProxy;
public Acontroller() {
System.out.println("Acontroller is been created, Aservice = " + aservice );
}
@PostConstruct
public void init (){
System.out.println("执行了postConstruct 方法");
}
@RequestMapping("/spring/A")
public String getA(){
RBucket<Object> key = redissonProxy.getBucket("key");
key.set("aa");
return (String) redissonProxy.getBucket("key").get();
}
}
最后启动Spring Boot 项目,在浏览器进行访问URL:
而key的值也发生了变化: