美文网首页redis
redis sentinel 读写分离(一)

redis sentinel 读写分离(一)

作者: 8e7f75130086 | 来源:发表于2018-10-05 12:26 被阅读966次

redis sentinel 读写分离(一)
redis sentinel 读写分离(二)
redis sentinel 读写分离(三)
redis sentinel 读写分离(四)
redis sentinel 读写分离(五)
redis sentinel 读写分离(六)
redis sentinel 读写分离(七)
redis sentinel 读写分离(八)
redis sentinel 读写分离(九)

你是否想当然的认为sentinel帮你实现了读写分离


一、背景:

为了提高redis集群的高可用性,redis架构由master-slave结构切换为了sentinel模式。架构图如下:


redis架构.png
sentinel能够提供的特性:
  1. 监控(Monitoring)
    sentinel会不间断地检查Redis master和Redis slave是否正常运行
  2. 提醒(Notification)
    当其中一个被监控的Redis实例出现问题,sentinel能通过API或其他程序通知管理员
  3. 自动故障转移(Automatic failover)
    当Redis master故障不能正常工作时,sentinel会故障切换进程,将一个slave提升为master,另外的Redis slave将更新配置使用新的master,此后有新连接时,会连接到新的Redis master
  4. 配置提供者(Configuration provider)
    Redis充当客户端服务发现的权威来源:客户端连接到sentinel,以请求当前可靠的Redis master地址,若发生故障转移,sentinels将报告新地址

二、问题

引入sentinel之后如何实现读写分离呢?


三、先来看看官方推荐的客户端jedis

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.7.2</version>
</dependency>
  • redis.clients.jedis.JedisSentinelPool

通过源码分析可知,JedisSentinelPool只是建立了一个到master的连接。所有的slave仅仅起到了一个备的作用,没有任何流量会打进来,大大减低了redis集群的性能。

public JedisSentinelPool(String masterName, Set<String> sentinels,
      final GenericObjectPoolConfig poolConfig, int timeout, final String password,
      final int database) {
    this.poolConfig = poolConfig;
    this.timeout = timeout;
    this.password = password;
    this.database = database;
    HostAndPort master = initSentinels(sentinels, masterName);
    initPool(master);
  }
private HostAndPort initSentinels(Set<String> sentinels, final String masterName) {
    HostAndPort master = null;
    boolean sentinelAvailable = false;
    log.info("Trying to find master from available Sentinels...");
    for (String sentinel : sentinels) {
      final HostAndPort hap = toHostAndPort(Arrays.asList(sentinel.split(":")));
      log.fine("Connecting to Sentinel " + hap);
      Jedis jedis = null;
      try {
        jedis = new Jedis(hap.getHost(), hap.getPort());
        List<String> masterAddr = jedis.sentinelGetMasterAddrByName(masterName);
        // connected to sentinel...
        sentinelAvailable = true;
        if (masterAddr == null || masterAddr.size() != 2) {
          log.warning("Can not get master addr, master name: " + masterName + ". Sentinel: " + hap
              + ".");
          continue;
        }
        master = toHostAndPort(masterAddr);
        log.fine("Found Redis master at " + master);
        break;
      } catch (JedisConnectionException e) {
        log.warning("Cannot connect to sentinel running @ " + hap + ". Trying next one.");
      } finally {
        if (jedis != null) {
          jedis.close();
        }
      }
    }

    if (master == null) {
      if (sentinelAvailable) {
        // can connect to sentinel, but master name seems to not
        // monitored
        throw new JedisException("Can connect to sentinel, but " + masterName
            + " seems to be not monitored...");
      } else {
        throw new JedisConnectionException("All sentinels down, cannot determine where is "
            + masterName + " master is running...");
      }
    }

    log.info("Redis master running at " + master + ", starting Sentinel listeners...");

    for (String sentinel : sentinels) {
      final HostAndPort hap = toHostAndPort(Arrays.asList(sentinel.split(":")));
      MasterListener masterListener = new MasterListener(masterName, hap.getHost(), hap.getPort());
      masterListeners.add(masterListener);
      masterListener.start();
    }

    return master;
  }

四、在sentinel模式下如何才能实现读写分离呢?

自己动手吧

相关文章

网友评论

    本文标题:redis sentinel 读写分离(一)

    本文链接:https://www.haomeiwen.com/subject/nwuooftx.html