初步搭建Redis集群
克隆已经安装Redis的虚拟机,我们使用这两个虚拟机中的Redis来搭建集群。
master:192.168.2.129 端口:7001 slave:192.168.2.132 端口:7002 sentinel:192.168.2.129 端口:26379
来说一下这个sentinel,sentinel是一个管理redis实例的工具,它可以实现对redis的监控、通知、自动故障转移。sentinel不断的检测redis实例是否可以正常工作,通过API向其他程序报告redis的状态,如果redis master不能工作,则会自动启动故障转移进程,将其中的一个slave提升为master,其他的slave重新设置新的master服务器。
来配置一下sentinel.conf,内容如下:
port 26379 daemonize yes logfile "/var/log/redis/sentinel.log" sentinel monitor master1 192.168.1.129 7001 1 sentinel down-after-milliseconds master1 1000 sentinel failover-timeout master1 5000
做为master的redis不需要修改redis.conf配置,但需要修改一下slave的redis配置,将端口修改为7002,并且添加如下的配置:
slaveof 192.168.1.129 7001
执行如下的命令所在的目录为:redis-stable/src
./redis-server ../redis.conf // 启动master与slave ./redis-sentinel ../sentinel.conf // 启动sentinel
使用客户端来查看:
./redis-cli -p 26379 -h 192.168.2.129
内容如下图:
2、Spring Session Date Redis访问Redis Sentinel
使用上次新建的模块mazhi-redis进行测试。pom.xml文件不需要改变。但是redis.properties的配置需要改变,如下:
spring.redis.database=0 spring.redis.host=192.168.2.129 # Login password of the redis server. spring.redis.password= spring.redis.pool.max-active=8 spring.redis.pool.max-idle=8 spring.redis.pool.max-wait=-1 spring.redis.pool.min-idle=0 spring.redis.port=7001 # Name of Redis server. spring.redis.sentinel.master=master1 # Comma-separated list of host:port pairs. spring.redis.sentinel.nodes=192.168.2.129:26379 spring.redis.timeout=0
注意必须是redis.properties这个名称,而且必须要放到src/main/resources目录下,这是一种约定。
spring.redis.sentinel.master必须与sentinel.conf文件中指定的值一致,如下:
sentinel monitor master1 192.168.1.129 7001 1
spring.redis.sentinel.nodes值为sentinel的ip:端口,可以有多个。
在org.mazhi.redis.config目录下新建RedisSentinalConfig.java文件,内容如下:
@Configuration @PropertySource(value = "classpath:/redis.properties") @EnableCaching public class RedisSentinalConfig extends CachingConfigurerSupport{ @Bean public KeyGenerator wiselyKeyGenerator(){ // 配置key的生成规则 return new KeyGenerator() { public Object generate(Object target, Method method, Object... params) { StringBuilder sb = new StringBuilder(); sb.append(target.getClass().getName()); sb.append(method.getName()); for (Object obj : params) { sb.append(obj.toString()); } return sb.toString(); } }; } @Bean public CacheManager cacheManager(@SuppressWarnings("rawtypes") RedisTemplate redisTemplate) { return new RedisCacheManager(redisTemplate); } @Bean public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) { StringRedisTemplate template = new StringRedisTemplate(factory); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); template.setValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } }
新建一个User的实体对象,如下:
package org.mazhi.redis.bean; public class User { private Long id; private String name; private String address; public User(Long id,String name, String address) { this.id = id ; this.name = name; this.address = address; } public User() { } ... }
在org.mazhi.redis.service目录下新建DemoService.java文件,内容如下:
@Service public class DemoService { @Cacheable(value = "usercache",keyGenerator = "wiselyKeyGenerator") public User findUser(Long id,String firstName,String lastName){ System.out.println("======当Redis中不存在这条数据时会执行这里========="); return new User(id,firstName,lastName); } }
在org.mazhi.redis.web目录下新建RedisSentinelController.java文件,内容如下:
@Autowired DemoService demoService; @RequestMapping("/addToRedis") @ResponseBody public void putCache() { demoService.findUser(1l, "mazhi", "ordos"); System.out.println("添加成功!"); } @RequestMapping("/findFromRedis") @ResponseBody public void testCache() { User user = demoService.findUser(1l, "mazhi", "ordos"); System.out.println("user:" + "/" + user.getName() + "/" + user.getAddress()); } }
启动Spring Boot后,在浏览器中输入如下地址:
http://localhost:8081/redis-sentinel/addToRedis
Eclipse的控制台打印如下信息:
======当Redis中不存在这条数据时会执行这里========= 添加成功! 添加成功!
接着输入如下地址进行访问:
http://localhost:8081/redis-sentinel/getFromRedis
打印结果如下:
user:/mazhi/ordos user:/mazhi/ordos
来看一下Redis的数据库,如下图所示。
看Key的生成形式,这就是调用我们在RedisSentinalConfig.java文件中指定的方法wiselyKeyGenerator()生成的。
看一下192.168.2.132上的redis,可以看到两个Redis的信息是同步的。
使用如下的命令来封闭192.168.2.129上的7001端口到达任何地方的路由,即人为造成了一次master服务的“宕机”。
/sbin/iptables -I INPUT -p tcp --dport 7001 -j DROP
Eclipse的控制台输出如下信息:
2016-04-01 09:02:35.188 INFO 6980 --- [ Thread-2] redis.clients.jedis.JedisSentinelPool : Created JedisPool to master at 192.168.2.132:7002
master变为了192.168.2.132机器。或者我们可以在sentinel客户端查看,如下:
address已经变成了192.168.2.132了。
恢复192.168.2.129上的7001端口,输入如下的命令:
/sbin/iptables -I INPUT -p tcp --dport 7001 -j ACCEPT
在192.168.2.129上输入如下命令查看:
./redis-cli -h 192.168.2.129 -p 7001
可以看到如下信息:
角色由以前的master变为slave了,而现在的master是192.168.2.132主机。