测试redis的主从配置
redis实例
文件夹名称如下
redis_master_s
redis_slaver1_s
redis_slaver2_s
redis.conf文件
master的redis.conf文件(其余是默认设置)
1 port 6379 2 daemonize yes 3 # 这个文件夹要改成自己的目录 4 dir "/Users/vobile_lzl/redis_master_s"
slaver1的redis.conf文件
1 port 6378 2 # 主服务器端口为6379 3 slaveof 127.0.0.1 6379 4 dir "/Users/vobile_lzl/redis_slaver1_s"
slaver2的redis.conf文件
1 port 6377 2 # 主服务器端口为6379 3 slaveof 127.0.0.1 6379 4 dir "/Users/vobile_lzl/redis_slaver2_s"
这个主从服务器就配置好了。
启动服务(命令大致如此)
./redis-server redis.conf
测试一下主从复制的功能
1. 主服务器写入,从服务器可以读取到
2. 从服务器不能写入
注意端口,6379表示主服务器,6377、6378是从服务器
127.0.0.1:6379> set name lzl OK 127.0.0.1:6377> get name "lzl" 127.0.0.1:6378> get name "lzl" # 从服务器不能写入 127.0.0.1:6378> set name lzl (error) READONLY You can't write against a read only slave. 127.0.0.1:6377> set nam fdk (error) READONLY You can't write against a read only slave.
sentinel.conf文件
sentinel是哨兵,用于监视主从服务器的运行状况,如果主服务器挂掉,会在从服务器中选举一个作为主服务器。
配置文件如下
master的sentinel.conf
1 port 26379 2 # 初次配置时的状态,这个sentinel会自动更新 3 sentinel monitor mymaster 127.0.0.1 6379 2 4 daemonize yes 5 logfile "./sentinel_log.log"
slaver1的sentinel.conf
1 port 26378 2 # 初次配置时的状态,这个sentinel会自动更新 3 sentinel monitor mymaster 127.0.0.1 6379 2 4 daemonize yes 5 logfile "./sentinel_log.log"
slaver2的sentinel.conf
1 port 26377 2 # 初次配置时的状态,这个sentinel会自动更新 3 sentinel monitor mymaster 127.0.0.1 6379 2 4 daemonize yes 5 logfile "./sentinel_log.log"
再次启动redis所有的服务端
./redis-server redis.conf
./redis-server sentinel.conf --sentinel
分别开启redis的客户端
./redis-cli ./redis-cli -h 127.0.0.1 -p 6378 ./redis-cli -h 127.0.0.1 -p 6377
使用一下命令查看三个redis服务的状态
info replication
master
role:master
127.0.0.1:6379> info replication # Replication role:master connected_slaves:2 slave0:ip=127.0.0.1,port=6378,state=online,offset=4102,lag=1 slave1:ip=127.0.0.1,port=6377,state=online,offset=4102,lag=1 master_repl_offset:4102 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:2 repl_backlog_histlen:4101
slaver1
127.0.0.1:6378> info replication # Replication role:slave master_host:127.0.0.1 master_port:6379 master_link_status:up master_last_io_seconds_ago:0 master_sync_in_progress:0 slave_repl_offset:15931 slave_priority:100 slave_read_only:1 connected_slaves:0 master_repl_offset:0 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0
slaver2
127.0.0.1:6377> info replication # Replication role:slave master_host:127.0.0.1 master_port:6379 master_link_status:up master_last_io_seconds_ago:1 master_sync_in_progress:0 slave_repl_offset:21629 slave_priority:100 slave_read_only:1 connected_slaves:0 master_repl_offset:0 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0
将master服务杀死
vobile-lzldeMacBook-Pro:~ vobile_lzl$ ps -ef | grep redis 501 13258 1 0 9:52下午 ?? 0:00.37 ./redis-server *:6379 kill -9 13258
再次查看master的状态
说明master已经宕机
127.0.0.1:6379> info replication
Could not connect to Redis at 127.0.0.1:6379: Connection refused
再观察一段时间,6377的从服务器成为主服务器
127.0.0.1:6377> info replication # Replication role:master connected_slaves:0 master_repl_offset:0 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0
恢复主服务器,并设置为master
springboot中配置主从redis
RedisCacheConfig
1 package com.config; 2 3 import com.fasterxml.jackson.annotation.JsonAutoDetect; 4 import com.fasterxml.jackson.annotation.PropertyAccessor; 5 import com.fasterxml.jackson.databind.ObjectMapper; 6 import org.springframework.beans.factory.annotation.Value; 7 import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 8 import org.springframework.cache.annotation.CachingConfigurerSupport; 9 import org.springframework.cache.annotation.EnableCaching; 10 import org.springframework.cache.interceptor.KeyGenerator; 11 import org.springframework.context.annotation.Bean; 12 import org.springframework.context.annotation.Configuration; 13 import org.springframework.data.redis.cache.RedisCacheManager; 14 import org.springframework.data.redis.connection.RedisNode; 15 import org.springframework.data.redis.connection.RedisSentinelConfiguration; 16 import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; 17 import org.springframework.data.redis.core.RedisTemplate; 18 import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 19 import org.springframework.data.redis.serializer.StringRedisSerializer; 20 21 import java.lang.reflect.Method; 22 23 /** 24 * @author zhujinmin6 25 */ 26 @Configuration 27 @EnableAutoConfiguration 28 @EnableCaching //加上这个注解是的支持缓存注解 29 public class RedisCacheConfig extends CachingConfigurerSupport { 30 31 @Value("${spring.redis.host}") 32 private String host; 33 34 @Value("${spring.redis.port}") 35 private int port; 36 37 @Value("${spring.redis.timeout}") 38 private int timeout; 39 40 @Value("${spring.redis.database}") 41 private int database; 42 43 @Value("${spring.redis.password}") 44 private String password; 45 46 @Value("${spring.redis.sentinel.nodes}") 47 private String redisNodes; 48 49 @Value("${spring.redis.sentinel.master}") 50 private String master; 51 52 53 /** 54 * redis哨兵配置 55 * @return 56 */ 57 @Bean 58 public RedisSentinelConfiguration redisSentinelConfiguration(){ 59 RedisSentinelConfiguration configuration = new RedisSentinelConfiguration(); 60 String[] host = redisNodes.split(","); 61 for(String redisHost : host){ 62 String[] item = redisHost.split(":"); 63 String ip = item[0]; 64 String port = item[1]; 65 configuration.addSentinel(new RedisNode(ip, Integer.parseInt(port))); 66 } 67 configuration.setMaster(master); 68 return configuration; 69 } 70 71 /** 72 * 连接redis的工厂类 73 * 74 * @return 75 */ 76 @Bean 77 public JedisConnectionFactory jedisConnectionFactory() { 78 JedisConnectionFactory factory = new JedisConnectionFactory(redisSentinelConfiguration()); 79 factory.setHostName(host); 80 factory.setPort(port); 81 factory.setTimeout(timeout); 82 factory.setPassword(password); 83 factory.setDatabase(database); 84 return factory; 85 } 86 87 /** 88 * 配置RedisTemplate 89 * 设置添加序列化器 90 * key 使用string序列化器 91 * value 使用Json序列化器 92 * 还有一种简答的设置方式,改变defaultSerializer对象的实现。 93 * 94 * @return 95 */ 96 @Bean 97 public RedisTemplate<Object, Object> redisTemplate() { 98 //StringRedisTemplate的构造方法中默认设置了stringSerializer 99 RedisTemplate<Object, Object> template = new RedisTemplate<>(); 100 //设置开启事务 101 template.setEnableTransactionSupport(true); 102 //set key serializer 103 StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); 104 template.setKeySerializer(stringRedisSerializer); 105 template.setHashKeySerializer(stringRedisSerializer); 106 107 template.setConnectionFactory(jedisConnectionFactory()); 108 template.afterPropertiesSet(); 109 return template; 110 } 111 112 /** 113 * 设置RedisCacheManager 114 * 使用cache注解管理redis缓存 115 * 116 * @return 117 */ 118 @Override 119 @Bean 120 public RedisCacheManager cacheManager() { 121 RedisCacheManager redisCacheManager = new RedisCacheManager(redisTemplate()); 122 return redisCacheManager; 123 } 124 125 /** 126 * 自定义生成redis-key 127 * 128 * @return 129 */ 130 @Override 131 public KeyGenerator keyGenerator() { 132 return new KeyGenerator() { 133 @Override 134 public Object generate(Object o, Method method, Object... objects) { 135 StringBuilder sb = new StringBuilder(); 136 sb.append(o.getClass().getName()).append("."); 137 sb.append(method.getName()).append("."); 138 for (Object obj : objects) { 139 sb.append(obj.toString()); 140 } 141 System.out.println("keyGenerator=" + sb.toString()); 142 return sb.toString(); 143 } 144 }; 145 } 146 }
SampleController
package com.controller; import com.dao.UseRedisDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author zhujinming6 * @create 2017-10-24 9:25 **/ @RestController @RequestMapping("/sample") public class SampleController { @Autowired private UseRedisDao useRedisDao; @RequestMapping("/hi") public String sayHello(String key,String value){ useRedisDao.setValue(key,value); return useRedisDao.getValue(key); } }
UseRedisDao
package com.dao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.ListOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Repository; import javax.annotation.PostConstruct; import java.util.Map; /** * @Author: zhujinmin6 * @Date: create in 15:44 17/9/21. * @description:整合redis的实例,简单了解RedisTemplate的API */ @Repository public class UseRedisDao { @Autowired private RedisTemplate<Object,Object> redisTemplate; private ValueOperations<Object,Object> valueOperations; private ListOperations<Object,Object> listOperations; private HashOperations hashOperations; @PostConstruct public void getValueOperation(){ valueOperations = redisTemplate.opsForValue(); listOperations = redisTemplate.opsForList(); hashOperations = redisTemplate.opsForHash(); } public void setValue(String key, String value){ valueOperations.set(key, value); } public String getValue(String key){ return (String) valueOperations.get(key); } public void addList(String key, String value){ listOperations.leftPush(key, value); } public Long getListSize(String key){ return listOperations.size(key); } public void setHashMap(String key, Map map){ hashOperations.putAll(key, map); } public Map getHashMap(String key){ return hashOperations.entries(key); } }
Application
package com; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.boot.web.support.SpringBootServletInitializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.context.annotation.ImportResource; /** * Web容器启动主类 * @author zhujinmin6 */ @SpringBootApplication(scanBasePackages = { "com" }) @EnableAutoConfiguration @ServletComponentScan public class Application extends SpringBootServletInitializer { public static void main(String [] args){ SpringApplication.run(Application.class,args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(Application.class); } }
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>redis_clu</groupId> <artifactId>redis_clu</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity4</artifactId> </dependency> <!-- spring boot and redis--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>1.5.7.RELEASE</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
application.properties
#springSession \u9009\u62E9\u540C\u6B65session\u7684\u5916\u90E8\u7F13\u5B58 #spring.session.store-type=redis #========================redis \u914D\u7F6E============================= # Redis\u6570\u636E\u5E93\u7D22\u5F15\uFF08\u9ED8\u8BA4\u4E3A0\uFF09,\u5982\u679C\u8BBE\u7F6E\u4E3A1\uFF0C\u90A3\u4E48\u5B58\u5165\u7684key-value\u90FD\u5B58\u653E\u5728select 1\u4E2D spring.redis.database=0 # Redis\u670D\u52A1\u5668\u5730\u5740 spring.redis.host=localhost # Redis\u670D\u52A1\u5668\u8FDE\u63A5\u7AEF\u53E3 spring.redis.port=6379 # Redis\u670D\u52A1\u5668\u8FDE\u63A5\u5BC6\u7801\uFF08\u9ED8\u8BA4\u4E3A\u7A7A\uFF09 spring.redis.password= #\u8FDE\u63A5\u6C60\u6700\u5927\u8FDE\u63A5\u6570\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09 spring.redis.pool.max-active=8 # \u8FDE\u63A5\u6C60\u6700\u5927\u963B\u585E\u7B49\u5F85\u65F6\u95F4\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09 spring.redis.pool.max-wait=-1 # \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5927\u7A7A\u95F2\u8FDE\u63A5 spring.redis.pool.max-idle=8 # \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5 spring.redis.pool.min-idle=0 # \u8FDE\u63A5\u8D85\u65F6\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09 spring.redis.timeout=0 ### \u4E3B\u4ECE\u914D\u7F6E # name of Redis server \u54E8\u5175\u76D1\u542C\u7684Redis server\u7684\u540D\u79F0 spring.redis.sentinel.master=mymaster # comma-separated list of host:port pairs \u54E8\u5175\u7684\u914D\u7F6E\u5217\u8868 spring.redis.sentinel.nodes=127.0.0.1:26379,127.0.0.1:26378,127.0.0.1:26377
启动成功
调用redis
结果