1. 程式人生 > >劍指架構師系列-Redis集群部署

劍指架構師系列-Redis集群部署

cnblogs con pom.xml文件 執行 bili ngs 報告 new body

初步搭建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 
配完了master, slave和sentinel後,必須按照如下順序來啟動redis集群: master->slave->sentinel

執行如下的命令所在的目錄為: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主機。



劍指架構師系列-Redis集群部署