Redis实践(八)-Sentinal

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 1目录2 主从复制高可用?故障出现主节点挂掉主从复制-mster宕掉故障处理3 Redis Sentinel 架构可监控多套4 安装与配置...

1

img_742264da5503e67c0b21b64921eec70c.png
目录

2 主从复制高可用?

img_dcbb957c8941905492e901a137b3775a.png

img_a1fc6ca9fa028b53537930ba1d79c1fa.png
故障出现主节点挂掉

img_bd08b548c11f99d8bbf02cc7686da60e.png
主从复制-mster宕掉故障处理

3 Redis Sentinel 架构

img_bdf184e6de0cfa55bb5da150049033eb.png

img_e0b200c272a4acabc6788752f84f0e0c.png

img_9fde9e8f4c736b7dbc0d1d59159020d8.png
可监控多套

4 安装与配置

img_694148219e4fb69b24754d8ab889e60b.png
安装与配置

img_c33df64e4b278a1a6713d2a3e866ef23.png

img_2565f19586f554db1f8918e08af41f1f.png
Redis 主节点

img_f030e6f7899366e5d9748a0614df1aff.png
Redis 从节点

img_f2d03ee89f5e2aba62ce9ae516de5327.png
Sentinel 主要配置

5 安装与演示

img_ce79f2574c103be96714034e7a6a1ec6.png

img_1591a8673bd2bce39fc038834167c648.png
主节点配置

img_6945df7b66c866c0ee00b33802c62aa0.png
快速生成从节点配置文件

img_8297b8e624b9667ff1b4e8a1ac10c355.png
重定向

img_34c9230872797ce7ca10be46bede3156.png
打印检查配置文件

img_7ded2bb8d063348f46cf0d1da345a640.png
启动

6 客户端

img_ede75704ba8fe40f36dd8b9560588a3f.png
客户端

img_f3d54a69b76dd8d4dd806f5e58202ef3.png
直连?

img_cf287f79c0991ec83d546a87a434f6e9.png
客户端实现基本原理-1

img_94aa602a5ec8929180a7e5c8a89fbd49.png
客户端实现基本原理-2

img_3c4d6cc87345b0ae58bff8e717a4c9a0.png
客户端实现基本原理-3 验证

img_5ea744f7ec6b56060241a309a916e28c.png
客户端实现基本原理-4 通知(发布订阅))

img_bdd90002120a4b99dc892b5dd44fca14.png

img_672c298837e9b8859a94eafbb0cfd7ed.png
客户端接入流程

img_4fabc34675efa18dd881ad8719a679ae.png
Jedis

11 三个定时任务

img_60f207d3869019f248ba042aab43680b.png
三个定时任务

img_0ef29445096e6b1d9a4266c8b8e651f6.png
每 10s info

img_738c312813b75327f7119c3701a16c81.png
第2个监控任务,每 2s 发布订阅

img_b45be99c4f5a88ccdd41ba9cd947eec2.png
第3个监控任务,每 1s PING

12 主观下线和客观下线

img_35731bd2779d5ece19c52b9da880ed2a.png
主观下线和客观下线

13 领导者选举

img_2eec950258b9d0fa273faf1097d2b114.png
领导者选举

img_db4ea40558a8ea8bd57c9feafeefb551.png
选举实例

14 故障转移

img_1619ba802e5764c29eea14257f42d926.png
领导者节点完成

img_301f05e6951cbd11c4c86b2e78739c11.png
选择合适的slave节点

15 常见开发运维问题-目录

img_4a0cdf1eddfba57b614f9405d9fe65c7.png

16 节点运维

img_dbe52be66d165d69694773696238f84f.png

img_a736dda638752247d04960660007812a.png
主节点

img_2318618d0f03fee74428549e39335e05.png
节点下线

img_c39bd76a2bd531b0cf83d3d7e6091a97.png
节点上线

17 高可用的读写分离

看一下JedisSentinelPool的实现

img_2139ae53ccd12b5c5b51b96914ede49b.png

img_68971df81d79e0035ae7388a28a159dd.png

img_cd7d86f47ee381f2e815c0427a0f13c5.png

img_ef522f0e3e5f4578969a1c0fe257a84f.png

private HostAndPort initSentinels(Set<String> sentinels, final String masterName) {

    HostAndPort master = null;
    boolean sentinelAvailable = false;

    log.info("Trying to find master from available Sentinels...");
    // 遍历所有 Sentinel 节点
    for (String sentinel : sentinels) {
      final HostAndPort hap = toHostAndPort(Arrays.asList(sentinel.split(":")));

      log.fine("Connecting to Sentinel " + hap);

      Jedis jedis = null;
      try {
        // 找到一个可运行的,并用jedis连接上去
        jedis = new Jedis(hap.getHost(), hap.getPort());

        // 通过 mastername 区分 sentinel 节点,得到其地址
        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 (JedisException e) {
        // resolves #1036, it should handle JedisException there's another chance
        // of raising JedisDataException
        log.warning("Cannot get master address from sentinel running @ " + hap + ". Reason: " + e
            + ". 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...");
    //当拿到master节点后,所要做的就是订阅那个消息,客户端只需订阅该频道即可
    for (String sentinel : sentinels) {
      final HostAndPort hap = toHostAndPort(Arrays.asList(sentinel.split(":")));
      MasterListener masterListener = new MasterListener(masterName, hap.getHost(), hap.getPort());
      // whether MasterListener threads are alive or not, process can be stopped
      masterListener.setDaemon(true);
      masterListeners.add(masterListener);
      masterListener.start();
    }

以下为监听线程类

protected class MasterListener extends Thread {

    protected String masterName;
    protected String host;
    protected int port;
    protected long subscribeRetryWaitTimeMillis = 5000;
    protected volatile Jedis j;
    protected AtomicBoolean running = new AtomicBoolean(false);

    protected MasterListener() {
    }

    public MasterListener(String masterName, String host, int port) {
      super(String.format("MasterListener-%s-[%s:%d]", masterName, host, port));
      this.masterName = masterName;
      this.host = host;
      this.port = port;
    }

    public MasterListener(String masterName, String host, int port,
        long subscribeRetryWaitTimeMillis) {
      this(masterName, host, port);
      this.subscribeRetryWaitTimeMillis = subscribeRetryWaitTimeMillis;
    }

    @Override
    public void run() {

      running.set(true);

      while (running.get()) {

        j = new Jedis(host, port);

        try {
          // double check that it is not being shutdown
          if (!running.get()) {
            break;
          }

          j.subscribe(new JedisPubSub() {
            @Override
            public void onMessage(String channel, String message) {
              log.fine("Sentinel " + host + ":" + port + " published: " + message + ".");

              String[] switchMasterMsg = message.split(" ");

              if (switchMasterMsg.length > 3) {

                if (masterName.equals(switchMasterMsg[0])) {
                  initPool(toHostAndPort(Arrays.asList(switchMasterMsg[3], switchMasterMsg[4])));
                } else {
                  log.fine("Ignoring message on +switch-master for master name "
                      + switchMasterMsg[0] + ", our master name is " + masterName);
                }

              } else {
                log.severe("Invalid message received on Sentinel " + host + ":" + port
                    + " on channel +switch-master: " + message);
              }
            }
          }, "+switch-master");

        } catch (JedisConnectionException e) {

          if (running.get()) {
            log.log(Level.SEVERE, "Lost connection to Sentinel at " + host + ":" + port
                + ". Sleeping 5000ms and retrying.", e);
            try {
              Thread.sleep(subscribeRetryWaitTimeMillis);
            } catch (InterruptedException e1) {
              log.log(Level.SEVERE, "Sleep interrupted: ", e1);
            }
          } else {
            log.fine("Unsubscribing from Sentinel at " + host + ":" + port);
          }
        } finally {
          j.close();
        }
      }
    }

    public void shutdown() {
      try {
        log.fine("Shutting down listener on " + host + ":" + port);
        running.set(false);
        // This isn't good, the Jedis object is not thread safe
        if (j != null) {
          j.disconnect();
        }
      } catch (Exception e) {
        log.log(Level.SEVERE, "Caught exception while shutting down: ", e);
      }
    }
  }
img_399af9258990e13b25a40b207116e291.png
感知到主从切换时,接收消息并重新初始化连接池

img_a90f4a247bb5fe61a9fc355160ef3aa6.png

img_f054fa5438fe8178cc05548c89df0162.png
从节点的作用

由于Redis Sentinel只会对主节点进行故障转移,对从节点采取主观的下线,所以需要自定义一个客户端来监控对应的事件


img_28b34d21e1b75dd8d615578644e882ef.png
三个消息

img_b735c55edada8f7255d4a4c855091a84.png
高可用读写分离

18 总结

img_6ec3d52ffd585ba06a3e5260f11edbcf.png

img_9e1e7f686cfbfd2d0bb513c7cd4d2569.png

img_f92acdf0db9d59465b2753946b2899b0.png
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
2月前
|
存储 缓存 NoSQL
蚂蚁金服P7私藏的Redis原理与实践内部笔记
Redis 是完全开源免费的,是一个高性能的key-value类型的内存数据库。整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB。
59 1
|
3月前
|
缓存 NoSQL Java
Spring Cache 缓存原理与 Redis 实践
Spring Cache 缓存原理与 Redis 实践
139 0
|
7月前
|
NoSQL Unix Linux
Redis核心技术与实践 03 | 高性能IO模型:为什么单线程Redis能那么快?
Redis核心技术与实践 03 | 高性能IO模型:为什么单线程Redis能那么快?
|
7月前
|
NoSQL Redis 数据库
Redis核心技术与实践 02 | 数据结构:快速的Redis有哪些慢操作?
Redis核心技术与实践 02 | 数据结构:快速的Redis有哪些慢操作?
|
5月前
|
存储 NoSQL Linux
VLDB顶会论文Async-fork解读与Redis在得物的实践(1)
VLDB顶会论文Async-fork解读与Redis在得物的实践
41 0
|
5月前
|
NoSQL 测试技术 Linux
VLDB顶会论文Async-fork解读与Redis在得物的实践(3)
VLDB顶会论文Async-fork解读与Redis在得物的实践
63 0
VLDB顶会论文Async-fork解读与Redis在得物的实践(3)
|
5月前
|
NoSQL 测试技术 Linux
VLDB顶会论文Async-fork解读与Redis在得物的实践(2)
VLDB顶会论文Async-fork解读与Redis在得物的实践
36 0
VLDB顶会论文Async-fork解读与Redis在得物的实践(2)
|
1月前
|
弹性计算 NoSQL 测试技术
倚天使用|Redis性能高30%,阿里云倚天ECS性能摸底和迁移实践
Redis在倚天ECS环境下与同规格的基于 x86 的 ECS 实例相比,Redis 部署在基于 Yitian 710 的 ECS 上可获得高达 30% 的吞吐量优势。成本方面基于倚天710的G8y实例售价比G7实例低23%,总性价比提高50%;按照相同算法,相对G8a,性价比为1.4倍左右。
137501 3
|
5月前
|
NoSQL 测试技术 Redis
VLDB顶会论文Async-fork解读与Redis在得物的实践(4)
VLDB顶会论文Async-fork解读与Redis在得物的实践
48 0
VLDB顶会论文Async-fork解读与Redis在得物的实践(4)
|
8月前
|
缓存 监控 NoSQL
分布式文件存储与数据缓存 Redis高可用分布式实践(下)(三)
分布式文件存储与数据缓存 Redis高可用分布式实践(下)(三)

热门文章

最新文章