基于Redis的低成本高可用排行榜服务构建

引言

业务运营活动中排行榜的使用很广泛,因此在三年前组内已经将排行榜服务组件化。整个服务是基于Redis的zset数据结构实现的。

限于当时Redis的发展,这套服务在高可用性方面有所欠缺。近年来,公司内外团队在实现高可用Redis方面做了很多工作,也有很多部门提供现成的接入方案。但由于我们的Redis是定制过的(修改过源码),一方面是现有方案不支持接入,开源项目往往也需要修改源码进行适配,即便如此也不完全如意;另一方面我们自己也希望在升级迭代上能灵活掌控,所以权衡后还是决定自行部署和运维。

架构方案

早期的架构

在此之前,排行榜服务部署情况如下图所示。此时,无状态的接入层通过内部协议对外提供服务,各业务无需关注Redis的连接和调用方式。但是当redis master停止服务时,需要人工将slave提升为master,并发布配置将接入层的指向切换到slave。此方案虽然能在大多数情况下做到数据安全,但是在出现故障后人工介入之前,服务处于不可用状态。

早期的架构

高可用架构

关于Redis的高可用部署方案,常见的有twemproxy、codis等,这些第三方方案往往需要引入额外组件,增加了运维成本。Redis本身提供了哨兵做HA,官方文档就哨兵的不同部署方案做了详细介绍。本着低成本的原则,本文亦采用哨兵作高可用保障。改进的排行榜服务架构如下图所示。

高可用架构

整个服务由以下部分组成:

  • 排行榜CGI及业务模块:即服务使用方。排行榜CGI是一个通用化的供H5前端拉取排行榜数据的组件,业务无关。当业务有特殊逻辑时,亦可直接调用接入层接口。
  • 服务接入层: 1. 对业务提供惯用的内部协议接口,供业务调用 2. 对单个原生命令无法完成的操作,如插入元素并返回排名操作,使用pipelining或lua优化查询,细节对业务透明 3. 对业务隐藏从哨兵处获取redis实例地址、master实例切换后地址更新等复杂逻辑 4. 当读并发量较大时,可通过增加redis slave实现读操作水平扩容,增加的slave可通过哨兵自动发现,对业务透明 5. 提供黑名单、周期榜单等业务通用能力支持
  • Redis实例:即Redis主从实例对。可以有多个slave以实现读操作水平扩容。
  • 哨兵集群:提供高可用保证以及名服务。由3个哨兵组成,不与任何Redis实例混布。
  • 监控与告警:借助公司内部指标监控平台实现指标监控以及异常告警。下一节详述。

监控告警与自动运维

Redis存活监控与master自动切换。由哨兵负责。当实例进程终止或不可达时,哨兵会检测到该实例的sdownodown状态(主观下线与客观下线),并在客观下线后自动切换主实例。通过配置哨兵的notification-script脚本,在状态变化时哨兵可以调用运维接口发送短信和邮件通知。而配置reconfig-script,能在新的master切换成功后触发通知。

同时,接入层需要根据哨兵sentinel slaves命令返回的数据自动发现slave,并根据状态识别slave是否可用。几种情况下的master和slave可用性如下表所示。

情形

master状态

slave状态

master与slave正常

正常

正常。flagsslavemaster-link-statusok

master不可达

不可读写,等待恢复或切换

正常。flagsslavemaster-link-statusok

master切换后slave同步中

新master正常。

暂不可用。与新master成功建立连接前flags包含disconnected;与新master连接后完成同步前master-link-status不为ok

新slave上线同步中

正常

暂不可用。与新master成功建立连接前flags包含disconnected;与新master连接后完成同步前master-link-status不为ok

slave不可达

正常

不可读。flags包含sdownodown

Redis指标监控。在Redis实例机器上部署监控脚本,通过crontab定时采样,数据上报到监控平台,方便查看实时和历史数据。监控的指标项可包含CPU使用率、内存使用率、key数量等,根据业务需要确定。

哨兵间相互监控。同样由哨兵负责。但需要注意的是,当某个哨兵不可达时,其他哨兵只会触发sdown状态变化,并发送通知告警。

扩展能力

功能可扩展性。除了现有的黑名单、周期榜的能力,接入层还可以扩展丰富的业务功能,对业务屏蔽复杂的redis调用逻辑。比如,借助LUA实现一个定时消息队列(参考此文)、接口流控等。

标准组件兼容。接入层同时支持切换到其他符合Redis协议的组件,比如360 pika等。对于上层业务来说,不管是调用标准redis实例,还是其他组件,都没有差别。

安装包与配置管理

Redis安装包与配置管理

业务的线上Redis使用相同的配置,统一使用内部服务包发布系统管理Redis的安装包和配置,以后台server方式打包和部署。好处是:

  • 便于版本管理,能跟踪每一次变更情况。
  • 跟踪现网部署情况,可以看到部署了哪些实例,分别是哪个版本。当发现问题时可以方便评估受影响的范围。
  • 能将部署工作流程化。安装包内包含了监控脚本和工具,并且会自动添加指标监控的crontab。

哨兵安装包与配置管理

业务同样使用内部包发布系统管理哨兵安装包。但在配置管理方面与redis包有些不同,因为哨兵的配置文件,同时也是哨兵的状态存储,故每个哨兵的线上配置是有差异的。我们将哨兵配置项区分为以下几类:

分类

内容

特征

每实例独有

哨兵ID

配置变更后要保持不变,否则其他哨兵会认为有新哨兵加入且原哨兵不可用,将影响到故障恢复时多数派选举leader过程。哨兵之所以不清除不可用的哨兵状态,是为了防止当网络故障导致脑裂时错误的选举局部leader。

公共静态配置

端口、工作目录、日志文件等

每个实例一样,且日常运维中无需变更。

公共动态配置

监控的Redis实例及纪元信息。

这部分配置随着监控实例的增删会变化。值得注意的是,如果某个哨兵的纪元信息被重置,其可以从别的哨兵处恢复。

故可以采用如下策略管理哨兵配置:

  1. 静态配置放在sentinel-base.conf文件中,随哨兵安装包发布。
  2. 指定配置文件sentinel.conf启动哨兵,首次部署启动后会在配置sentinel.conf中生成哨兵唯一idsentinel myid,利用包部署服务等启动后脚本将其备份到myid.conf中。脚本如下:cd $install_path/conf grep -E '^sentinel myid' sentinel.conf > myid.conf
  3. 最后利用配置系统下发实例监控配置文件sentinel.conf,在配置文件开头用include方式包含sentinel-base.confmyid.conf,且实例监控配置不需要包括epoch信息。这样,就能在每次下发新的配置后,保留哨兵ID和每个被监控实例的epoch信息了。_不过需要注意的是,相比起使用配置中心动态存储配置的方式,当线上故障导致master变更后,需要手动修改配置。_include "/usr/local/services/redis_sentinel_qzmall-1.0/conf/sentinel-base.conf" include "/usr/local/services/redis_sentinel_qzmall-1.0/conf/myid.conf"
# 实例1
sentinel monitor my_redis 100.66.82.X 6479 2
sentinel down-after-milliseconds my_redis 10000
sentinel auth-pass my_redis mypasswd
sentinel parallel-syncs my_redis 1
sentinel notification-script my_redis /usr/local/services/redis_sentinel_qzmall-1.0/bin/notification-script.sh
sentinel client-reconfig-script my_redis /usr/local/services/redis_sentinel_qzmall-1.0/bin/reconfig-script.sh

结语

与大多数公共组建一样,本文的Redis部署方案也由接入层、哨兵(名服务)、Redis实例(核心服务)、监控服务等部分组成。除哨兵与Redis是官方开源组件外,其他部分均选择公司已有技术和运维平台完成。方案整体既能满足日常业务需求,也能满足日常运维与监控要求,在可用性与维护成本上取得了一个平衡。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏编程一生

《两地书》--Kubernetes(K8s)基础知识(docker容器技术)

1144
来自专栏Java架构师历程

6、选择部署策略

本书主要介绍关于如何使用微服务构建应用程序,这是本书的第六章。第一章介绍了微服务架构模式,讨论了使用微服务的优点与缺点。之后的章节讨论了微服务架构的方方面面:使...

1083
来自专栏云计算教程系列

什么是负载均衡?

负载均衡是高可用性基础架构的关键组件,通常用在多个服务器之间分配工作负载来提高网站、应用程序、数据库和其他服务的性能和可靠性。

1628
来自专栏架构师之旅

浅谈大型Web系统架构

动态应用,是相对于网站静态内容而言,是指以c/c++、php、Java、perl、.net等服务器端语言开发的网络应用软件,比如论坛、网络相册、交友、BLOG等...

2927
来自专栏顶级程序员

一张“神图”看懂单机/集群/热备/磁盘阵列(RAID)

今天是农历小年,顶级程序员祝大家小年夜快乐~ ? 单机部署(stand-alone):只有一个饮水机提供服务,服务只部署一份 集群部署(cluster):有多...

3467
来自专栏北京马哥教育

LVS集群详解

一、什么是集群 LVS(Linux Virtual Server)Linux虚拟服务器,将多台虚拟主机组织起来满足同一个需求。由国人章文嵩开发,通过LVS提...

39210
来自专栏编程一生

《两地书》--Kubernetes(K8s)基础知识(docker容器技术)

  大家都知道历史上有段佳话叫“司马相如和卓文君”。“皑如山上雪,皎若云间月”。卓文君这么美,却也抵不过多情女儿薄情郎。

1894
来自专栏IT大咖说

基于Spring Cloud及K8S构建微服务应用

摘要 广发证券蔡波斯先生通过三个大方向来为我们分享基于Spring Cloud及K8S构建微服务应用。 ? 基于Spring Cloud构建微服务 Netfli...

6788
来自专栏SAP最佳业务实践

SAP最佳业务实践:使用看板的生产制造(233)-6经典看板:使用数量信号及触发点的内部生产(重复制造)

image.png 在典型看板流程中,完全清空看板后,从事生产的员工可使用看板信号将看板状态设置为空。将看板设置为空之前,系统都会认为此数量仍在看板中。 使用数...

3075
来自专栏JAVA烂猪皮

基于 Docker 的微服务架构实践

基于 Docker 的容器技术是在2015年的时候开始接触的,两年多的时间,作为一名 Docker 的 DevOps,也见证了 Docker 的技术体系的快速发...

832

扫码关注云+社区