抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

系统拆分范例:不停机迁移、解耦、高可用设计一气呵成

一、业务背景

 

优惠券是电商常见的营销手段,具有灵活的特点,既可以作为促销活动的载体,也是重要的引流入口。优惠券系统是vivo商城营销模块中一个重要组成部分,早在15年vivo商城还是单体应用时,优惠券就是其中核心模块之一。随着商城的发展及用户量的提升,优惠券做了服务拆分,成立了独立的优惠券系统,提供通用的优惠券服务。目前,优惠券系统覆盖了优惠券的4个核心要点:创、发、用、计。

 

  • “创”指优惠券的创建,包含各种券规则和使用门槛的配置。

 

  • “发”指优惠券的发放,优惠券系统提供了多种发放优惠券的方式,满足针对不同人群的主动发放和被动发放。

 

  • “用”指优惠券的使用,包括正向购买商品及反向退款后的优惠券回退。

 

  • “计”指优惠券的统计,包括优惠券的发放数量、使用数量、使用商品等数据汇总。

 

vivo商城优惠券系统除了提供常见的优惠券促销玩法外,还以优惠券的形式作为其他一些活动或资产的载体,比如手机类商品的保值换新、内购福利、与外部广告商合作发放优惠券等。

 

以下为vivo商城优惠券部分场景的展示:

 

图片

 

二、系统架构及变迁

 

优惠券最早和商城耦合在一个系统中。随着vivo商城的不断发展,营销活动力度加大,优惠券使用场景增多,优惠券系统逐渐开始“力不从心”,暴露了很多问题:

 

  • 海量优惠券的发放,达到优惠券单库、单表存储瓶颈。

 

  • 与商城系统的高耦合,直接影响了商城整站接口性能。

 

  • 优惠券的迭代更新受限于商城的版本安排。

 

  • 针对多品类优惠券,技术层面没有沉淀通用优惠券能力。

 
 

1. 系统架构

 
为了解决以上问题,19年优惠券系统进行了系统独立,提供通用的优惠券服务,独立后的系统架构如下:

 

图片

 

 

2. 优惠券系统独立迁移方案

 

如何将优惠券从商城系统迁移出来,并兼容已对接的业务方和历史数据,也是一大技术挑战。系统迁移有两种方案:停机迁移和不停机迁移。

 

我们采用的是不停机迁移方案:

 

  • 迁移前,运营停止与优惠券相关的后台操作,避免产生优惠券静态数据。

 

  • 静态数据:优惠券后台生成的数据,与用户无关。

  • 动态数据:与用户有关的优惠券数据,含用户领取的券、券和订单的关系数据等。

 

  • 配置当前数据库开关为单写,即优惠券数据写入商城库(旧库)。

 

  • 优惠券系统上线,通过脚本迁移静态数据。迁完后,验证静态数据迁移准确性。

 

  • 配置当前数据库开关为双写,即线上数据同时写入商城库和优惠券新库。此时服务提供的数据源依旧是商城库。

 

  • 迁移动态数据。迁完后,验证动态数据迁移准确性。

 

  • 切换数据源,服务提供的数据源切换到新库。验证服务是否正确,出现问题时,切换回商城数据源。

 

  • 关闭双写,优惠券系统迁移完成。

 

迁移后优惠券系统请求拓扑图如下:

 

图片

 

三、系统设计

 

 

1. 优惠券分库分表

 

随着优惠券发放量越来越大,单表已经达到瓶颈。为了支撑业务的发展,综合考虑,对用户优惠券数据进行分库分表。

 

关键字:技术选型、分库分表因子

 

分库分表有成熟的开源方案,这里不做过多介绍。参考之前项目经验,采用了公司中间件团队提供的自研框架。原理是引入自研的MyBatis的插件,根据自定义的路由策略计算不同的库表后缀,定位至相应的库表。

 

用户优惠券与用户id关联,并且用户id是贯穿整个系统的重要字段,因此使用用户id作为分库分表的路由因子。这样可以保证同一个用户路由至相同的库表,既有利于数据的聚合,也方便用户数据的查询。

 

假设共分N个库M个表,分库分表的路由策略为:

 

  • 库后缀databaseSuffix = hash(userId) / M %N

 

  • 表后缀tableSuffix = hash(userId) % M

 

图片

 
 

2. 优惠券发放方式设计

 

为满足各种不同场景的发券需求,优惠券系统提供三种发券方式:统一领券接口、后台定向发券、券码兑换发放。

 

1)统一领券接口

 

① 保证领券校验的准确性

 

领券时,需要严格校验优惠券的各种属性是否满足:比如领取对象、各种限制条件等。其中,比较关键的是库存和领取数量的校验。因为在高并发的情况下,需保证数量校验的准确性,不然很容易造成用户超领。

 

存在这样的场景:A用户连续发起两次领取券C的请求,券C限制每个用户领取一张。第一次请求通过了领券数量的校验,在用户优惠券未落库的情况下,如果不做限制,第二次请求也会通过领券数量的校验。这样A用户会成功领取两张券C,造成超领。

 

为了解决这个问题,优惠券采用的是分布式锁方案,分布式锁的实现依赖于Redis。在校验用户领券数量前先尝试获取分布式锁,优惠券发放成功后释放锁,保证用户领取同一张券时不会出现超领。上面这种场景,用户第一次请求成功获取分布式锁后,直至第一次请求成功释放已获取的分布式锁或超时释放,不然用户第二次请求会获取分布式锁失败,这样保证A用户只会成功领取一张。

 

② 库存扣减

 

领券要进行库存扣减,常见库存扣减方案有两种:

 

  • 方案一:数据库扣减。

 

 

扣减库存时,直接更新数据库中库存字段。

 

  • 该方案的优点是简单便捷,查验库存时直接查库即可获取到实时库存。且有数据库事务保证,不用考虑数据丢失和不一致的问题。

 

  • 缺点也很明显,主要有两点:

  • 库存是数据库中的单个字段,在更新库存时,所有的请求需要等待行锁。一旦并发量大了,就会有很多请求阻塞在这里,导致请求超时,进而系统雪崩。

  • 频繁请求数据库,比较耗时,且会大量占用数据库连接资源。

 

  • 方案二:基于redis实现库存扣减操作。

 

将库存放到缓存中,利用redis的incrby特性来扣减库存。

 

  • 该方案的优点是突破数据库的瓶颈,速度快,性能高。

  • 缺点是系统流程会比较复杂,而且需要考虑缓存丢失或宕机数据恢复的问题,容易造成库存数据不一致。

 

从优惠券系统当前及可预见未来的流量峰值、系统维护性、实用性上综合考虑,优惠券系统采用了方案一的改进方案。改进方案是将单库存字段分散成多库存字段,分散数据库的行锁,减少并发量大的情况数据库的行锁瓶颈。

 

图片

 

库存数更新后,会将库存平均分配成M份,初始化更新到库存记录表中。用户领券,随机选取库存记录表中已分配的某一库存字段(共M个)进行更新,更新成功即为库存扣减成功。同时,定时任务会定期同步已领取的库存数。相比方案一,该方案突破了数据库单行锁的瓶颈限制,且实现简单,不用考虑数据丢失和不一致的问题。

 

③ 一键领取多张券

 

在对接的业务方的领券场景中,存在用户一键领取多张券的情形。因此统一领券接口需要支持用户一键领券,除了领取同一券模板的多张,也支持领取不同券模板的多张。一般来说,一键领取多张券指领取不同券模板的多张。在实现过程中,需要注意以下几点:

 

  • 如何保证性能

 

领取多张券,如果每张券分别进行校验、库存扣减、入库,那么接口性能的瓶颈卡在券的数量上,数量越多,性能直线下降。那么在券数量多的情况下,怎么保证高性能呢?主要采取两个措施:

 

  • 批量操作。

从发券流程来看,瓶颈在于券的入库。领券是实时的(异步的话,不能实时将券发到用户账户下,影响到用户的体验还有券的转化率),券越多,入库时与数据库的IO次数越多,性能越差。批量入库可以保证与数据库的IO的次数只有一次,不受券的数量影响。如上所述,用户优惠券数据做了分库分表,同一用户的优惠券资产保存在同一库表中,因此同一用户可实现批量入库。

 

  • 限制单次领券数量。

设置阀值,超出数量后,直接返回,保证系统在安全范围内。

 

  • 保证高并发情况下,用户不会超领

 

假如用户在商城发起请求,一键领取A/B/C/D四张券,同时活动系统给用户发放券A,这两个领券请求是同时的。其中,券A限制了每个用户只能领取一张。按照前述采用分布式锁保证校验的准确性,两次请求的分布式锁的key分别为:

 

  • 用户id+A_id+B_id+C_id+D_id

  • 用户id+A_id

 

这种情况下,两次请求的分布式锁并没有发挥作用,因为锁key是不同,数量校验依旧存在错误的可能性。为避免批量领券过程中用户超领现象的发生,在批量领券过程中,对分布锁的获取进行了改造。上例一键领取A/B/C/D四张券,需要批量获取4个分布式锁,锁key为:

 

  • 用户id+A_id

  • 用户id+B_id

  • 用户id+C_id

  • 用户id+D_id

 

获取其中任何一个锁失败,即表明此时该用户正在领取其中某一张券,需要自旋等待(在超时时间内)。获取所有的分布式锁成功,才可以进行下一步。

 

④ 接口幂等性

 

统一领券接口需保证幂等性(幂等性:用户对于同一操作发起的一次请求或者多次请求的结果是一致的)。在网络超时、异常情况下,领券结果没有及时返回,业务方会进行领券重试。如果接口不保证幂等性,会造成超发。幂等性的实现有多种方案,优惠券系统利用数据库的唯一索引来保证幂等。

 

领券最早是不支持幂等性的,表设计没有考虑幂等性。

 

  • 那么第一个需要考虑的问题:在哪个表来添加唯一索引呢?

无非两种方案:现有的表或者新建表。

 

  • 采用现有的表,不需要增加表的关联。但如上所述,因为做了分库分表,大量的表需要添加唯一字段,并且需要兼容历史数据,需要保证历史数据新增字段的唯一性。

  • 采用新建表这种方式,不需要兼容历史数据,但缺陷也很明显,增加了一层表的关联,对性能和现有逻辑都有很大影响。综合考虑,我们选取了在现有表添加唯一字段这种方式,这样更利于保证性能和后续的维护性。

 

  • 第二个考虑的问题:怎么兼容历史数据和业务方?

 

 

  • 历史数据增加了唯一字段,需要填入唯一值,不然无法添加唯一索引。我们采用脚本刷数据的方式,构造唯一值并刷新到每一行历史数据中。优惠券已对接的业务方没有传入唯一编码,针对这种情况,优惠券侧生成唯一编码作为替代,保证兼容性。

 

2)定向发券

 

定向发券用于运营在后台针对特定人群进行发券。定向发券可以弥补用户主动领券,人群覆盖不精准、覆盖面不广的问题。通过定向发券,可以精准覆盖特定人群,提高下单转化率。在大促期间,大范围人群的定向发券还可以承载活动push和降价促销双重任务。

 

定向发券主要在于人群的圈选和发券流程的设计,整体流程如下:

 

图片

 

定向发券不同于用户主动领券,定向发券的量通常会很大(亿级)。为了支撑大批量的定向发券,定向发券做了一些优化:

 

① 去除事务

 

事务逻辑过重,对于定向发券来说没必要。发券失败,记录失败的券,保证失败可以重试。

 

② 轻量化校验

 

定向发券限制了券类型,通过限制配置的方式规避需严格校验属性的配置。不同于用户主动领券校验逻辑的冗长,定向发券的校验非常轻量,大大提升发券性能。

 

③ 批量插入

 

批量券插入减少数据库IO次数,消除数据库瓶颈,提升发券速度。定向发券是针对不同的用户,用户优惠券做了分库分表,为了实现批量插入,需要在内存中先计算出不同用户对应的库表后缀,数据归集后再批量插入,最多插入M次,M为库表总个数。

 

④ 核心参数可动态配置

 

比如单次发券数量,单次读库数量,发给消息中心的消息体包含的用户数量等,可以控制定向发券的峰值速度和平均速度。

 

3)券码兑换

 

站外营销券的发放方式与其他券不同,通过券码进行兑换。券码由后台导出,通过短信或者活动的方式发放到用户,用户根据券码兑换后获取相应的券。券码的组成有一定的规则,在规则的基础上要保证安全性,这种安全性主要是券码校验的准确性,防止已兑换券码的再次兑换和无效券码的恶意兑换。

 
 

3. 精细化营销能力设计

 

通过标签组合配置的方式,优惠券提供精细化营销的能力,以实现优惠券的千人千面。标签可分为准实时和实时,值得注意的是,一些实时的标签的处理需要前提条件,比如地区属性需要用户授权。

 

优惠券的精准触达:

 

图片

 
 

4. 券和商品之间的关系

 

优惠券的使用需要和商品关联,可关联所有商品,也可以关联部分商品。为了灵活性地满足运营对于券关联商品的配置,优惠券系统有两种关联方式:

 

1)黑名单

 

可用商品 = 全部商品 - 黑名单商品。

 

黑名单适用于券的可使用商品范围比较广这种情况,全部商品排除掉黑名单商品就是券的可使用范围。

 

2)白名单

 

可用商品 = 白名单商品。

 

白名单适用于券的可使用商品范围比较小这种情况,直接配置券的可使用商品。

 

除此以外,还有超级黑名单的配置,黑名单和白名单只对单个券有效,超级黑名单对所有券有效。当前优惠券系统提供商品级的关联,后续优惠券会支持商品分类维度的关联,分类维度 + 商品维度可以更灵活地关联优惠券和商品。

 
 

5. 高性能保证

 

优惠券对接系统多,存在高流量场景,优惠券对外提供接口需保证高性能和高稳定性。

 

1)多级缓存

 

为了提升查询速度,减轻数据库的压力,同时为了应对瞬时高流量带来热点key的场景(比如发布会直播结束切换流量至特定商品商详页、热点活动商品商详页都会给优惠券系统带来瞬时高流量),优惠券采用了多级缓存的方式。

 

图片

 

2)数据库读写分离

 

优惠券除了上述所说的分库分表外,在此基础上还做了读写分离操作。主库负责执行数据更新请求,然后将数据变更实时同步到所有从库,用从库来分担查询请求,解决数据库写入影响查询的问题。主从同步存在延迟,正常情况下延迟不超过1ms,优惠券的领取或状态变更存在一个耗时的过程,主从延迟对于用户来说无感知。

 

图片

 

3)依赖外部接口隔离熔断

 

优惠券内部依赖了第三方的系统,为了防止因为依赖方服务不可用,产生连锁效应,最终导致优惠券服务雪崩的事情发生,优惠券对依赖外部接口做了隔离和熔断。

 

4)用户维度优惠券字段冗余

 

查询用户相关的优惠券数据是优惠券最频繁的查询操作之一,用户优惠券数据做了分库分表,在查询时无法关联券规则表进行查询,为了减少IO次数,用户优惠券表中冗余了部分券规则的字段。优惠券规则表字段较多,冗余的字段不能很多,要在性能和字段数之间做好平衡。

 

四、总结及展望

 

最后对优惠券系统进行一个总结

 

  • 不停机迁移,平稳过渡。自独立后已稳定运行2年,性能足以支撑vivo商城未来3-5年的高速发展。

 

  • 系统解耦,迭代效率大幅提升。

 

  • 针对业务问题,原则是选择合适实用的方案。

 

  • 具备完善的优惠券业务能力。

 

展望:目前优惠券系统主要服务于vivo商城,未来我们希望将优惠券能力开放,为内部其他业务方提供通用一体化的优惠券平台。

 

作者丨Yan Chao
来源丨公众号:vivo互联网技术(ID:vivoVMIC)
dbaplus社群欢迎广大技术人员投稿,投稿邮箱:editor@dbaplus.cn

“融新汇智_竞促发展”_第三届中国人工智能大赛即将启动

新一代人工智能正在全球蓬勃兴起,已公认是科技革命和产业变革的重要驱动力量且“头雁”效应显著。

我国“十四五”规划明确提出“大力发展人工智能产业,加快推动数字产业化”,目的就是要抢抓人工智能发展的重大战略机遇,构筑我国人工智能发展的先发优势,加快建设创新型国家和世界科技强国。

为响应党中央、国务院的相关要求和部署,深入推动我国人工智能产业创新发展,并在国内积极发现挖掘一批人工智能领域的技术领先团队,以“融新汇智,竞促发展”为主题的第三届中国人工智能大赛即将于近期在京启动,主要亮点提前揭秘如下:



规格升级 多个国家部委及厦门市政府联合主办

中国人工智能大赛是首个全国范围大型人工智能领域竞赛,也是国内最具权威的人工智能领域竞赛,迄今已成功举办两届,发掘了上百个优秀技术团队,发布了众多重要成果,被视为同类竞赛的标杆。

与往届大赛相比,第三届中国人工智能大赛规格升级,将由国家互联网信息办公室、工业和信息化部、公安部、国家广播电视总局以及厦门市人民政府联合主办,权威性前所未有。

顶级专家深度参与 专业性无可挑剔

中国人工智能大赛在专业性上始终保持着国内最高水准。大赛专家委员会由国内众多顶级专家和先进企业代表组成,并对赛事全程进行技术支持;

赛题将由中国信息通信研究院联合人工智能企业、科研院所等共同策划,重点聚焦算法治理、深度伪造音视频检测、网络安全等方向。目前初步确认大赛组委会、专家委员会将有2位院士参与,众多知名教授、研究员、企业技术专家及行业精英支持。高水准的专家库,将有效有力保障大赛成为公平、公正,高水平、高层次的顶尖赛事。

搭建合作交流平台 助力人工智能技术创新

此次人工智能大赛,将发布《人工智能白皮书(拟)》、《人脸信息处理合规操作指南(拟)》等研究成果;搭建竞赛、峰会、论坛等多种活动平台,交流研讨最新人工智能技术进展,并重点以解决现实场景中需求问题为导向,利用最新人工智能技术赋能网络空间治理,寻找相应解决技术方法或解决方案。

大赛还将以人工智能创新型技术、产品、解决方案及应用案例为评选范围,发现挖掘一批人工智能领域的技术领先团队,并从参赛单位中评选出一批“创新之星”。

以赛促产 推进技术快速落地

大赛将通过以赛促产的方式,依托厦门得天独厚的科研资源和产业基础,开展人才引进、技术研究、产品开发、成果转化和投资孵化等活动,促进人工智能与实体经济深度融合。

侧重方向是在智能制造、智能消费、智慧城市、智慧医疗、疫情防控等重点领域,为新一代人工智能产业创新应用提供试验场,加快推动大赛成果快速转化,加速构建人工智能产业聚集高地,打造运营良好的人工智能生态圈和全球顶尖人工智能标杆城市,带动我国人工智能产业发展,以更好地赋能传统产业,推动消费升级和产业转型。

目前大赛的前期各项准备工作已经就绪,诚邀国内相关高校、科研单位和公司企业关注并参与,并希望以此为契机,共同推动我国人工智能的高质量发展。

欢迎关注人工智能大会官方网站,  https://ai.xm.gov.cn/  随时了解大会动态。

具体联系方式

峰会论坛合作

联系人:李婵

联系方式:010-62309514

媒体宣传合作

联系人:李政隆

联系方式:15210716962

产业成果合作

联系人:刘硕

联系方式:13426019405

整体合作

联系人:石霖

联系方式:13581563677

实战搭建Prometheus监控系统,看完不信你还不会

前言

 

Prometheus 是一款基于时序数据库的开源监控告警系统,说起 Prometheus 则不得不提 SoundCloud,这是一个在线音乐分享的平台,类似于做视频分享的 YouTube,由于他们在微服务架构的道路上越走越远,出现了成百上千的服务,使用传统的监控系统 StatsD 和 Graphite 存在大量的局限性,于是他们在 2012 年开始着手开发一套全新的监控系统。Prometheus 的原作者是 Matt T. Proud,他也是在 2012 年加入 SoundCloud 的,实际上,在加入 SoundCloud 之前,Matt 一直就职于 Google,他从 Google 的集群管理器 Borg 和它的监控系统 Borgmon 中获取灵感,开发了开源的监控系统 Prometheus,和 Google 的很多项目一样,使用的编程语言是 Go。

 

很显然,Prometheus 作为一个微服务架构监控系统的解决方案,它和容器也脱不开关系。早在 2006 年 8 月 9 日,Eric Schmidt 在搜索引擎大会上首次提出了云计算(Cloud Computing)的概念,在之后的十几年里,云计算的发展势如破竹。在 2013 年,Pivotal 的 Matt Stine 又提出了云原生(Cloud Native)的概念,云原生由微服务架构、DevOps 和以容器为代表的敏捷基础架构组成,帮助企业快速、持续、可靠、规模化地交付软件。为了统一云计算接口和相关标准,2015 年 7 月,隶属于 Linux 基金会的 云原生计算基金会(CNCF,Cloud Native Computing Foundation) 应运而生。第一个加入 CNCF 的项目是 Google 的 Kubernetes,而 Prometheus 是第二个加入的(2016 年)。

 

目前 Prometheus 已经广泛用于 Kubernetes 集群的监控系统中,对 Prometheus 的历史感兴趣的同学可以看看 SoundCloud 的工程师 Tobias Schmidt 在 2016 年的 PromCon 大会上的演讲:The History of Prometheus at SoundCloud 。

 

一、Prometheus 概述

 

我们在 SoundCloud 的官方博客中可以找到一篇关于他们为什么需要新开发一个监控系统的文章 Prometheus: Monitoring at SoundCloud,在这篇文章中,他们介绍到,他们需要的监控系统必须满足下面四个特性:

 

  • A multi-dimensional data model, so that data can be sliced and diced at will, along dimensions like instance, service, endpoint, and method.

  • Operational simplicity, so that you can spin up a monitoring server where and when you want, even on your local workstation, without setting up a distributed storage backend or reconfiguring the world.

  • Scalable data collection and decentralized architecture, so that you can reliably monitor the many instances of your services, and independent teams can set up independent monitoring servers.

  • Finally, a powerful query language that leverages the data model for meaningful alerting (including easy silencing) and graphing (for dashboards and for ad-hoc exploration).

 

简单来说,就是下面四个特性:

 

  • 多维度数据模型

  • 方便的部署和维护

  • 灵活的数据采集

  • 强大的查询语言

 

实际上,多维度数据模型和强大的查询语言这两个特性,正是时序数据库所要求的,所以 Prometheus 不仅仅是一个监控系统,同时也是一个时序数据库。那为什么 Prometheus 不直接使用现有的时序数据库作为后端存储呢?这是因为 SoundCloud 不仅希望他们的监控系统有着时序数据库的特点,而且还需要部署和维护非常方便。

 

纵观比较流行的时序数据库(参见下面的附录),他们要么组件太多,要么外部依赖繁重,比如:Druid 有 Historical、MiddleManager、Broker、Coordinator、Overlord、Router 一堆的组件,而且还依赖于 ZooKeeper、Deep storage(HDFS 或 S3 等),Metadata store(PostgreSQL 或 MySQL),部署和维护起来成本非常高。而 Prometheus 采用去中心化架构,可以独立部署,不依赖于外部的分布式存储,你可以在几分钟的时间里就可以搭建出一套监控系统。

 

此外,Prometheus 数据采集方式也非常灵活。要采集目标的监控数据,首先需要在目标处安装数据采集组件,这被称之为 Exporter,它会在目标处收集监控数据,并暴露出一个 HTTP 接口供 Prometheus 查询,Prometheus 通过 Pull 的方式来采集数据,这和传统的 Push 模式不同。

 

不过 Prometheus 也提供了一种方式来支持 Push 模式,你可以将你的数据推送到 Push Gateway,Prometheus 通过 Pull 的方式从 Push Gateway 获取数据。目前的 Exporter 已经可以采集绝大多数的第三方数据,比如 Docker、HAProxy、StatsD、JMX 等等,官网有一份 Exporter 的列表。

 

除了这四大特性,随着 Prometheus 的不断发展,开始支持越来越多的高级特性,比如:服务发现,更丰富的图表展示,使用外部存储,强大的告警规则和多样的通知方式。下图是 Prometheus 的整体架构图

 

图片

 

从上图可以看出,Prometheus 生态系统包含了几个关键的组件:Prometheus server、Pushgateway、Alertmanager、Web UI 等,但是大多数组件都不是必需的,其中最核心的组件当然是 Prometheus server,它负责收集和存储指标数据,支持表达式查询,和告警的生成。接下来我们就来安装 Prometheus server。

 

二、安装 Prometheus server

 

Prometheus 可以支持多种安装方式,包括 Docker、Ansible、Chef、Puppet、Saltstack 等。下面介绍最简单的两种方式,一种是直接使用编译好的可执行文件,开箱即用,另一种是使用 Docker 镜像。

 

 
1、开箱即用

 

首先从 官网的下载页面 获取 Prometheus 的最新版本和下载地址,目前最新版本是 2.4.3(2018年10月),执行下面的命令下载并解压:

 

  •  
  •  
$ wget https://github.com/prometheus/prometheus/releases/download/v2.4.3/prometheus-2.4.3.linux-amd64.tar.gz$ tar xvfz prometheus-2.4.3.linux-amd64.tar.gz

 

然后切换到解压目录,检查 Prometheus 版本:

 

  •  
  •  
  •  
  •  
  •  
  •  
$ cd prometheus-2.4.3.linux-amd64$ ./prometheus --versionprometheus, version 2.4.3 (branch: HEAD, revision: 167a4b4e73a8eca8df648d2d2043e21bdb9a7449)  build user:       root@1e42b46043e9  build date:       20181004-08:42:02  go version:       go1.11.1

 

运行 Prometheus server:

 

  •  
$ ./prometheus --config.file=prometheus.yml

 

 

 
2、使用 Docker 镜像

 

使用 Docker 安装 Prometheus 更简单,运行下面的命令即可:

 

  •  
$ sudo docker run -d -p 9090:9090 prom/prometheus

一般情况下,我们还会指定配置文件的位置:

 

  •  
  •  
  •  
$ sudo docker run -d -p 9090:9090 \    -v ~/docker/prometheus/:/etc/prometheus/ \    prom/prometheus

 

我们把配置文件放在本地 ~/docker/prometheus/prometheus.yml,这样可以方便编辑和查看,通过 -v 参数将本地的配置文件挂载到 /etc/prometheus/ 位置,这是 prometheus 在容器中默认加载的配置文件位置。如果我们不确定默认的配置文件在哪,可以先执行上面的不带 -v 参数的命令,然后通过 docker inspect 命名看看容器在运行时默认的参数有哪些(下面的 Args 参数):

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
$ sudo docker inspect 0c  [...]          "Id": "0c4c2d0eed938395bcecf1e8bb4b6b87091fc4e6385ce5b404b6bb7419010f46",          "Created": "2018-10-15T22:27:34.56050369Z",          "Path": "/bin/prometheus",          "Args": [              "--config.file=/etc/prometheus/prometheus.yml",              "--storage.tsdb.path=/prometheus",              "--web.console.libraries=/usr/share/prometheus/console_libraries",              "--web.console.templates=/usr/share/prometheus/consoles"          ],     [...]

 

 
3、配置 Prometheus

 

正如上面两节看到的,Prometheus 有一个配置文件,通过参数 --config.file 来指定,配置文件格式为 YAML。我们可以打开默认的配置文件 prometheus.yml 看下里面的内容:

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
/etc/prometheus $ cat prometheus.yml # my global configglobal:  scrape_interval:     15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.  # scrape_timeout is set to the global default (10s).
# Alertmanager configurationalerting:  alertmanagers:  - static_configs:    - targets:      # - alertmanager:9093# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.rule_files:  # - "first_rules.yml"  # - "second_rules.yml"# A scrape configuration containing exactly one endpoint to scrape:# Here it's Prometheus itself.scrape_configs:  # The job name is added as a label `job=` to any timeseries scraped from this config.  - job_name: 'prometheus'
    # metrics_path defaults to '/metrics'    # scheme defaults to 'http'.    static_configs:    - targets: ['localhost:9090']

 

Prometheus 默认的配置文件分为四大块:

 

  • global 块:Prometheus 的全局配置,比如 scrape_interval 表示 Prometheus 多久抓取一次数据,evaluation_interval 表示多久检测一次告警规则;

 

  • alerting 块:关于 Alertmanager 的配置,这个我们后面再看;

 

  • rule_files 块:告警规则,这个我们后面再看;

 

  • scrape_config 块:这里定义了 Prometheus 要抓取的目标,我们可以看到默认已经配置了一个名称为 prometheus 的 job,这是因为 Prometheus 在启动的时候也会通过 HTTP 接口暴露自身的指标数据,这就相当于 Prometheus 自己监控自己,虽然这在真正使用 Prometheus 时没啥用处,但是我们可以通过这个例子来学习如何使用 Prometheus;可以访问 http://localhost:9090/metrics 查看 Prometheus 暴露了哪些指标;

 

三、学习 PromQL

 

通过上面的步骤安装好 Prometheus 之后,我们现在可以开始体验 Prometheus 了。Prometheus 提供了可视化的 Web UI 方便我们操作,直接访问 http://localhost:9090/ 即可,它默认会跳转到 Graph 页面:

 

图片

 

第一次访问这个页面可能会不知所措,我们可以先看看其他菜单下的内容,比如:Alerts 展示了定义的所有告警规则,Status 可以查看各种 Prometheus 的状态信息,有 Runtime & Build Information、Command-Line Flags、Configuration、Rules、Targets、Service Discovery 等等。

 

实际上 Graph 页面才是 Prometheus 最强大的功能,在这里我们可以使用 Prometheus 提供的一种特殊表达式来查询监控数据,这个表达式被称为 PromQL(Prometheus Query Language)。通过 PromQL 不仅可以在 Graph 页面查询数据,而且还可以通过 Prometheus 提供的 HTTP API 来查询。查询的监控数据有列表和曲线图两种展现形式(对应上图中 Console 和 Graph 这两个标签)。

 

我们上面说过,Prometheus 自身也暴露了很多的监控指标,也可以在 Graph 页面查询,展开 Execute 按钮旁边的下拉框,可以看到很多指标名称,我们随便选一个,譬如:promhttp_metric_handler_requests_total,这个指标表示 /metrics 页面的访问次数,Prometheus 就是通过这个页面来抓取自身的监控数据的。在 Console 标签中查询结果如下:

 

图片

 

上面在介绍 Prometheus 的配置文件时,可以看到 scrape_interval 参数是 15s,也就是说 Prometheus 每 15s 访问一次 /metrics 页面,所以我们过 15s 刷新下页面,可以看到指标值会自增。在 Graph 标签中可以看得更明显:

 

图片

 

 
1、数据模型

 

要学习 PromQL,首先我们需要了解下 Prometheus 的数据模型,一条 Prometheus 数据由一个指标名称(metric)和 N 个标签(label,N >= 0)组成的,比如下面这个例子:

 

  •  
promhttp_metric_handler_requests_total{code="200",instance="192.168.0.107:9090",job="prometheus"} 106

 

这条数据的指标名称为 promhttp_metric_handler_requests_total,并且包含三个标签 code、instance 和 job,这条记录的值为 106。上面说过,Prometheus 是一个时序数据库,相同指标相同标签的数据构成一条时间序列。如果以传统数据库的概念来理解时序数据库,可以把指标名当作表名,标签是字段,timestamp 是主键,还有一个 float64 类型的字段表示值(Prometheus 里面所有值都是按 float64 存储)。

 

这种数据模型和 OpenTSDB 的数据模型是比较类似的,详细的信息可以参考官网文档 Data model。另外,关于指标和标签的命名,官网有一些指导性的建议,可以参考 Metric and label naming 。

 

虽然 Prometheus 里存储的数据都是 float64 的一个数值,但如果我们按类型来分,可以把 Prometheus 的数据分成四大类:

 

  • Counter

  • Gauge

  • Histogram

  • Summary

 

Counter 用于计数,例如:请求次数、任务完成数、错误发生次数,这个值会一直增加,不会减少。Gauge 就是一般的数值,可大可小,例如:温度变化、内存使用变化。Histogram 是直方图,或称为柱状图,常用于跟踪事件发生的规模,例如:请求耗时、响应大小。它特别之处是可以对记录的内容进行分组,提供 count 和 sum 的功能。Summary 和 Histogram 十分相似,也用于跟踪事件发生的规模,不同之处是,它提供了一个 quantiles 的功能,可以按百分比划分跟踪的结果。例如:quantile 取值 0.95,表示取采样值里面的 95% 数据。更多信息可以参考官网文档 Metric types。Summary 和 Histogram 的概念比较容易混淆,属于比较高阶的指标类型,可以参考 Histograms and summaries 这里的说明。

 

这四种类型的数据只在指标的提供方作区分,也就是上面说的 Exporter,如果你需要编写自己的 Exporter 或者在现有系统中暴露供 Prometheus 抓取的指标,你可以使用 Prometheus client libraries,这个时候你就需要考虑不同指标的数据类型了。

 

如果你不用自己实现,而是直接使用一些现成的 Exporter,然后在 Prometheus 里查查相关的指标数据,那么可以不用太关注这块,不过理解 Prometheus 的数据类型,对写出正确合理的 PromQL 也是有帮助的。

 

 
2、PromQL 入门

 

我们从一些例子开始学习 PromQL,最简单的 PromQL 就是直接输入指标名称,比如:

 

  •  
  •  
# 表示 Prometheus 能否抓取 target 的指标,用于 target 的健康检查up

 

这条语句会查出 Prometheus 抓取的所有 target 当前运行情况,譬如下面这样:

 

  •  
  •  
  •  
  •  
up{instance="192.168.0.107:9090",job="prometheus"}    1up{instance="192.168.0.108:9090",job="prometheus"}    1up{instance="192.168.0.107:9100",job="server"}    1up{instance="192.168.0.108:9104",job="mysql"}    0

也可以指定某个 label 来查询:

 

  •  
up{job="prometheus"}

 

这种写法被称为 Instant vector selectors,这里不仅可以使用 = 号,还可以使用 !=、=~、!~,比如下面这样:

 

  •  
  •  
  •  
up{job!="prometheus"}up{job=~"servermysql"}up{job=~"192\.168\.0\.107.+"}

 

=~ 是根据正则表达式来匹配,必须符合 RE2 的语法。

 

和 Instant vector selectors 相应的,还有一种选择器,叫做 Range vector selectors,它可以查出一段时间内的所有数据:

 

  •  
http_requests_total[5m]

 

这条语句查出 5 分钟内所有抓取的 HTTP 请求数,注意它返回的数据类型是 Range vector,没办法在 Graph 上显示成曲线图,一般情况下,会用在 Counter 类型的指标上,并和 rate() 或 irate() 函数一起使用(注意 rate 和 irate 的区别)。

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
# 计算的是每秒的平均值,适用于变化很慢的 counter# per-second average rate of increase, for slow-moving countersrate(http_requests_total[5m])
# 计算的是每秒瞬时增加速率,适用于变化很快的 counter# per-second instant rate of increase, for volatile and fast-moving countersirate(http_requests_total[5m])

 

此外,PromQL 还支持 count、sum、min、max、topk 等 聚合操作,还支持 rate、abs、ceil、floor 等一堆的 内置函数,更多的例子,还是上官网学习吧。如果感兴趣,我们还可以把 PromQL 和 SQL 做一个对比,会发现 PromQL 语法更简洁,查询性能也更高。

 

 
3、HTTP API

 

我们不仅仅可以在 Prometheus 的 Graph 页面查询 PromQL,Prometheus 还提供了一种 HTTP API 的方式,可以更灵活的将 PromQL 整合到其他系统中使用,譬如下面要介绍的 Grafana,就是通过 Prometheus 的 HTTP API 来查询指标数据的。实际上,我们在 Prometheus 的 Graph 页面查询也是使用了 HTTP API。

 

我们看下 Prometheus 的 HTTP API 官方文档,它提供了下面这些接口:

 

  • GET /api/v1/query

  • GET /api/v1/query_range

  • GET /api/v1/series

  • GET /api/v1/label//values

  • GET /api/v1/targets

  • GET /api/v1/rules

  • GET /api/v1/alerts

  • GET /api/v1/targets/metadata

  • GET /api/v1/alertmanagers

  • GET /api/v1/status/config

  • GET /api/v1/status/flags

 

从 Prometheus v2.1 开始,又新增了几个用于管理 TSDB 的接口:

 

  • POST /api/v1/admin/tsdb/snapshot

  • POST /api/v1/admin/tsdb/delete_series

  • POST /api/v1/admin/tsdb/clean_tombstones

 

四、安装 Grafana

 

虽然 Prometheus 提供的 Web UI 也可以很好的查看不同指标的视图,但是这个功能非常简单,只适合用来调试。要实现一个强大的监控系统,还需要一个能定制展示不同指标的面板,能支持不同类型的展现方式(曲线图、饼状图、热点图、TopN 等),这就是仪表盘(Dashboard)功能。因此 Prometheus 开发了一套仪表盘系统 PromDash,不过很快这套系统就被废弃了,官方开始推荐使用 Grafana 来对 Prometheus 的指标数据进行可视化,这不仅是因为 Grafana 的功能非常强大,而且它和 Prometheus 可以完美的无缝融合。

 

Grafana 是一个用于可视化大型测量数据的开源系统,它的功能非常强大,界面也非常漂亮,使用它可以创建自定义的控制面板,你可以在面板中配置要显示的数据和显示方式,它 支持很多不同的数据源,比如:Graphite、InfluxDB、OpenTSDB、Elasticsearch、Prometheus 等,而且它也 支持众多的插件。

 

下面我们就体验下使用 Grafana 来展示 Prometheus 的指标数据。首先我们来安装 Grafana,我们使用最简单的 Docker 安装方式:

 

  •  
$ docker run -d -p 3000:3000 grafana/grafana

 

运行上面的 docker 命令,Grafana 就安装好了!你也可以采用其他的安装方式,参考 官方的安装文档。安装完成之后,我们访问 http://localhost:3000/ 进入 Grafana 的登陆页面,输入默认的用户名和密码(admin/admin)即可。

 

图片

 

要使用 Grafana,第一步当然是要配置数据源,告诉 Grafana 从哪里取数据,我们点击 Add data source 进入数据源的配置页面:

 

图片

 

我们在这里依次填上:

 

  • Name: prometheus

  • Type: Prometheus

  • URL: http://localhost:9090

  • Access: Browser

 

要注意的是,这里的 Access 指的是 Grafana 访问数据源的方式,有 Browser 和 Proxy 两种方式。Browser 方式表示当用户访问 Grafana 面板时,浏览器直接通过 URL 访问数据源的;而 Proxy 方式表示浏览器先访问 Grafana 的某个代理接口(接口地址是 /api/datasources/proxy/),由 Grafana 的服务端来访问数据源的 URL,如果数据源是部署在内网,用户通过浏览器无法直接访问时,这种方式非常有用。

 

配置好数据源,Grafana 会默认提供几个已经配置好的面板供你使用,如下图所示,默认提供了三个面板:Prometheus Stats、Prometheus 2.0 Stats 和 Grafana metrics。点击 Import 就可以导入并使用该面板。

 

图片

 

我们导入 Prometheus 2.0 Stats 这个面板,可以看到下面这样的监控面板。如果你的公司有条件,可以申请个大显示器挂在墙上,将这个面板投影在大屏上,实时观察线上系统的状态,可以说是非常 cool 的。

 

图片

 

五、使用 Exporter 收集指标

 

目前为止,我们看到的都还只是一些没有实际用途的指标,如果我们要在我们的生产环境真正使用 Prometheus,往往需要关注各种各样的指标,譬如服务器的 CPU负载、内存占用量、IO开销、入网和出网流量等等。

 

正如上面所说,Prometheus 是使用 Pull 的方式来获取指标数据的,要让 Prometheus 从目标处获得数据,首先必须在目标上安装指标收集的程序,并暴露出 HTTP 接口供 Prometheus 查询,这个指标收集程序被称为 Exporter,不同的指标需要不同的 Exporter 来收集,目前已经有大量的 Exporter 可供使用,几乎囊括了我们常用的各种系统和软件,官网列出了一份 常用 Exporter 的清单,各个 Exporter 都遵循一份端口约定,避免端口冲突,即从 9100 开始依次递增,这里是 完整的 Exporter 端口列表。

 

另外值得注意的是,有些软件和系统无需安装 Exporter,这是因为他们本身就提供了暴露 Prometheus 格式的指标数据的功能,比如 Kubernetes、Grafana、Etcd、Ceph 等。

 

这一节就让我们来收集一些有用的数据。

 

 
1、收集服务器指标

 

首先我们来收集服务器的指标,这需要安装 node_exporter,这个 exporter 用于收集 *NIX 内核的系统,如果你的服务器是 Windows,可以使用 WMI exporter。

 

和 Prometheus server 一样,node_exporter 也是开箱即用的:

 

  •  
  •  
  •  
  •  
$ wget https://github.com/prometheus/node_exporter/releases/download/v0.16.0/node_exporter-0.16.0.linux-amd64.tar.gz$ tar xvfz node_exporter-0.16.0.linux-amd64.tar.gz$ cd node_exporter-0.16.0.linux-amd64$ ./node_exporter

 

node_exporter 启动之后,我们访问下 /metrics 接口看看是否能正常获取服务器指标:

 

  •  
$ curl http://localhost:9100/metrics

 

如果一切 OK,我们可以修改 Prometheus 的配置文件,将服务器加到 scrape_configs 中:

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
scrape_configs:  - job_name: 'prometheus'    static_configs:      - targets: ['192.168.0.107:9090']  - job_name: 'server'    static_configs:      - targets: ['192.168.0.107:9100']

 

修改配置后,需要重启 Prometheus 服务,或者发送 HUP 信号也可以让 Prometheus 重新加载配置:

 

  •  
$ killall -HUP prometheus

 

在 Prometheus Web UI 的 Status -> Targets 中,可以看到新加的服务器:

 

图片

 

在 Graph 页面的指标下拉框可以看到很多名称以 node 开头的指标,譬如我们输入 node_load1 观察服务器负载:

 

图片

 

如果想在 Grafana 中查看服务器的指标,可以在 Grafana 的 Dashboards 页面 搜索 node exporter,有很多的面板模板可以直接使用,譬如:Node Exporter Server Metrics 或者 Node Exporter Full 等。我们打开 Grafana 的 Import dashboard 页面,输入面板的 URL(https://grafana.com/dashboards/405)或者 ID(405)即可。

 

图片

 

注意事项

 

一般情况下,node_exporter 都是直接运行在要收集指标的服务器上的,官方不推荐用 Docker 来运行 node_exporter。如果逼不得已一定要运行在 Docker 里,要特别注意,这是因为 Docker 的文件系统和网络都有自己的 namespace,收集的数据并不是宿主机真实的指标。可以使用一些变通的方法,比如运行 Docker 时加上下面这样的参数:

 

  •  
  •  
  •  
  •  
  •  
  •  
docker run -d \  --net="host" \  --pid="host" \  -v "/:/host:ro,rslave" \  quay.io/prometheus/node-exporter \  --path.rootfs /host

 

关于 node_exporter 的更多信息,可以参考 node_exporter 的文档 和 Prometheus 的官方指南 Monitoring Linux host metrics with the Node Exporter,另外,Julius Volz 的这篇文章 How To Install Prometheus using Docker on Ubuntu 14.04 也是很好的入门材料。

 

 
2、收集 MySQL 指标

 

mysqld_exporter 是 Prometheus 官方提供的一个 exporter,我们首先 下载最新版本 并解压(开箱即用):

 

  •  
  •  
  •  
$ wget https://github.com/prometheus/mysqld_exporter/releases/download/v0.11.0/mysqld_exporter-0.11.0.linux-amd64.tar.gz$ tar xvfz mysqld_exporter-0.11.0.linux-amd64.tar.gz$ cd mysqld_exporter-0.11.0.linux-amd64/

mysqld_exporter 需要连接到 mysqld 才能收集它的指标,可以通过两种方式来设置 mysqld 数据源。第一种是通过环境变量 DATA_SOURCE_NAME,这被称为 DSN(数据源名称),它必须符合 DSN 的格式,一个典型的 DSN 格式像这样:user:password@(host:port)/。

 

  •  
  •  
$ export DATA_SOURCE_NAME='root:123456@(192.168.0.107:3306)/'$ ./mysqld_exporter

另一种方式是通过配置文件,默认的配置文件是 ~/.my.cnf,或者通过 --config.my-cnf 参数指定:

 

  •  
$ ./mysqld_exporter --config.my-cnf=".my.cnf"

 

配置文件的格式如下:

 

 

  •  
  •  
  •  
  •  
  •  
  •  
$ cat .my.cnf[client]host=localhostport=3306user=rootpassword=123456

 

如果要把 MySQL 的指标导入 Grafana,可以参考 这些 Dashboard JSON。

 

注意事项

 

这里为简单起见,在 mysqld_exporter 中直接使用了 root 连接数据库,在真实环境中,可以为 mysqld_exporter 创建一个单独的用户,并赋予它受限的权限(PROCESS、REPLICATION CLIENT、SELECT),最好还限制它的最大连接数(MAX_USER_CONNECTIONS)。

 

  •  
  •  
CREATE USER 'exporter'@'localhost' IDENTIFIED BY 'password' WITH MAX_USER_CONNECTIONS 3;GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'localhost';

 

 
3、收集 Nginx 指标

 

官方提供了两种收集 Nginx 指标的方式。第一种是 Nginx metric library,这是一段 Lua 脚本(prometheus.lua),Nginx 需要开启 Lua 支持(libnginx-mod-http-lua 模块)。为方便起见,也可以使用 OpenResty 的 OPM(OpenResty Package Manager) 或者 luarocks(The Lua package manager) 来安装。第二种是 Nginx VTS exporter,这种方式比第一种要强大的多,安装要更简单,支持的指标也更丰富,它依赖于 nginx-module-vts 模块,vts 模块可以提供大量的 Nginx 指标数据,可以通过 JSON、HTML 等形式查看这些指标。Nginx VTS exporter 就是通过抓取 /status/format/json 接口来将 vts 的数据格式转换为 Prometheus 的格式。

 

不过,在 nginx-module-vts 最新的版本中增加了一个新接口:/status/format/prometheus,这个接口可以直接返回 Prometheus 的格式,从这点这也能看出 Prometheus 的影响力,估计 Nginx VTS exporter 很快就要退役了(TODO:待验证)。

 

除此之外,还有很多其他的方式来收集 Nginx 的指标,比如:nginx_exporter 通过抓取 Nginx 自带的统计页面 /nginx_status 可以获取一些比较简单的指标(需要开启 ngx_http_stub_status_module 模块);nginx_request_exporter 通过 syslog 协议 收集并分析 Nginx 的 access log 来统计 HTTP 请求相关的一些指标;nginx-prometheus-shiny-exporter 和 nginx_request_exporter 类似,也是使用 syslog 协议来收集 access log,不过它是使用 Crystal 语言 写的。还有 vovolie/lua-nginx-prometheus 基于 Openresty、Prometheus、Consul、Grafana 实现了针对域名和 Endpoint 级别的流量统计。

 

有需要或感兴趣的同学可以对照说明文档自己安装体验下,这里就不一一尝试了。

 

 
4、收集 JMX 指标

 

最后让我们来看下如何收集 Java 应用的指标,Java 应用的指标一般是通过 JMX(Java Management Extensions) 来获取的,顾名思义,JMX 是管理 Java 的一种扩展,它可以方便的管理和监控正在运行的 Java 程序。

 

JMX Exporter 用于收集 JMX 指标,很多使用 Java 的系统,都可以使用它来收集指标,比如:Kafaka、Cassandra 等。首先我们下载 JMX Exporter:

 

  •  
$ wget https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/0.3.1/jmx_prometheus_javaagent-0.3.1.jar

 

JMX Exporter 是一个 Java Agent 程序,在运行 Java 程序时通过 -javaagent 参数来加载:

 

  •  
$ java -javaagent:jmx_prometheus_javaagent-0.3.1.jar=9404:config.yml -jar spring-boot-sample-1.0-SNAPSHOT.jar

 

其中,9404 是 JMX Exporter 暴露指标的端口,config.yml 是 JMX Exporter 的配置文件,它的内容可以 参考 JMX Exporter 的配置说明 。然后检查下指标数据是否正确获取:

 

  •  
$ curl http://localhost:9404/metrics

 

六、告警和通知

 

至此,我们能收集大量的指标数据,也能通过强大而美观的面板展示出来。不过作为一个监控系统,最重要的功能,还是应该能及时发现系统问题,并及时通知给系统负责人,这就是 Alerting(告警)。Prometheus 的告警功能被分成两部分:一个是告警规则的配置和检测,并将告警发送给 Alertmanager,另一个是 Alertmanager,它负责管理这些告警,去除重复数据,分组,并路由到对应的接收方式,发出报警。常见的接收方式有:Email、PagerDuty、HipChat、Slack、OpsGenie、WebHook 等。

 

 
1、配置告警规则

 

我们在上面介绍 Prometheus 的配置文件时了解到,它的默认配置文件 prometheus.yml 有四大块:global、alerting、rule_files、scrape_config,其中 rule_files 块就是告警规则的配置项,alerting 块用于配置 Alertmanager,这个我们下一节再看。现在,先让我们在 rule_files 块中添加一个告警规则文件:

 

  •  
  •  
rule_files:  - "alert.rules"

 

然后参考 官方文档,创建一个告警规则文件 alert.rules:

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
groups:- name: example  rules:
  # Alert for any instance that is unreachable for >5 minutes.  - alert: InstanceDown    expr: up == 0    for: 5m    labels:      severity: page    annotations:      summary: "Instance { { $labels.instance } } down"      description: "{ { $labels.instance } } of job { { $labels.job } } has been down for more than 5 minutes."    # Alert for any instance that has a median request latency >1s.  - alert: APIHighRequestLatency    expr: api_http_request_latencies_second{quantile="0.5"} > 1    for: 10m    annotations:      summary: "High request latency on { { $labels.instance } }"      description: "{ { $labels.instance } } has a median request latency above 1s (current value: { { $value } }s)"

 

这个规则文件里,包含了两条告警规则:InstanceDown 和 APIHighRequestLatency。顾名思义,InstanceDown 表示当实例宕机时(up === 0)触发告警,APIHighRequestLatency 表示有一半的 API 请求延迟大于 1s 时(api_http_request_latencies_second{quantile="0.5"} > 1)触发告警。配置好后,需要重启下 Prometheus server,然后访问 http://localhost:9090/rules 可以看到刚刚配置的规则:

 

图片

 

访问 http://localhost:9090/alerts 可以看到根据配置的规则生成的告警:

 

图片

 

这里我们将一个实例停掉,可以看到有一条 alert 的状态是 PENDING,这表示已经触发了告警规则,但还没有达到告警条件。这是因为这里配置的 for 参数是 5m,也就是 5 分钟后才会触发告警,我们等 5 分钟,可以看到这条 alert 的状态变成了 FIRING。

 

 
2、使用 Alertmanager 发送告警通知

 

虽然 Prometheus 的 /alerts 页面可以看到所有的告警,但是还差最后一步:触发告警时自动发送通知。这是由 Alertmanager 来完成的,我们首先 下载并安装 Alertmanager,和其他 Prometheus 的组件一样,Alertmanager 也是开箱即用的:

 

  •  
  •  
  •  
  •  
$ wget https://github.com/prometheus/alertmanager/releases/download/v0.15.2/alertmanager-0.15.2.linux-amd64.tar.gz$ tar xvfz alertmanager-0.15.2.linux-amd64.tar.gz$ cd alertmanager-0.15.2.linux-amd64$ ./alertmanager

 

Alertmanager 启动后默认可以通过 http://localhost:9093/ 来访问,但是现在还看不到告警,因为我们还没有把 Alertmanager 配置到 Prometheus 中,我们回到 Prometheus 的配置文件 prometheus.yml,添加下面几行:

 

  •  
  •  
  •  
  •  
  •  
  •  
alerting:  alertmanagers:  - scheme: http    static_configs:    - targets:      - "192.168.0.107:9093"

 

这个配置告诉 Prometheus,当发生告警时,将告警信息发送到 Alertmanager,Alertmanager 的地址为 http://192.168.0.107:9093。也可以使用命名行的方式指定 Alertmanager:

 

  •  
$ ./prometheus -alertmanager.url=http://192.168.0.107:9093

这个时候再访问 Alertmanager,可以看到 Alertmanager 已经接收到告警了:

 

图片

 

下面的问题就是如何让 Alertmanager 将告警信息发送给我们了,我们打开默认的配置文件 alertmanager.ym:

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
global:  resolve_timeout: 5m
route:  group_by: ['alertname']  group_wait: 10s  group_interval: 10s  repeat_interval: 1h  receiver: 'web.hook'receivers:- name: 'web.hook'  webhook_configs:  - url: 'http://127.0.0.1:5001/'inhibit_rules:  - source_match:      severity: 'critical'    target_match:      severity: 'warning'    equal: ['alertname', 'dev', 'instance']

 

参考 官方的配置手册 了解各个配置项的功能,其中 global 块表示一些全局配置;route 块表示通知路由,可以根据不同的标签将告警通知发送给不同的 receiver,这里没有配置 routes 项,表示所有的告警都发送给下面定义的 web.hook 这个 receiver;如果要配置多个路由,可以参考 这个例子:

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
routes:- receiver: 'database-pager'  group_wait: 10s  match_re:    service: mysqlcassandra
- receiver: 'frontend-pager'  group_by: [product, environment]  match:    team: frontend

 

紧接着,receivers 块表示告警通知的接收方式,每个 receiver 包含一个 name 和一个 xxx_configs,不同的配置代表了不同的接收方式,Alertmanager 内置了下面这些接收方式:

 

  • email_config

  • hipchat_config

  • pagerduty_config

  • pushover_config

  • slack_config

  • opsgenie_config

  • victorops_config

  • wechat_configs

  • webhook_config

 

虽然接收方式很丰富,但是在国内,其中大多数接收方式都很少使用。最常用到的,莫属 email_config 和 webhook_config,另外 wechat_configs 可以支持使用微信来告警,也是相当符合国情的了。

 

其实告警的通知方式是很难做到面面俱到的,因为消息软件各种各样,每个国家还可能不同,不可能完全覆盖到,所以 Alertmanager 已经决定不再添加新的 receiver 了,而是推荐使用 webhook 来集成自定义的接收方式。可以参考 这些集成的例子,譬如 将钉钉接入 Prometheus AlertManager WebHook。

 

七、学习更多

 

到这里,我们已经学习了 Prometheus 的大多数功能,结合 Prometheus + Grafana + Alertmanager 完全可以搭建一套非常完整的监控系统。不过在真正使用时,我们会发现更多的问题。

 

 
1、服务发现

 

由于 Prometheus 是通过 Pull 的方式主动获取监控数据,所以需要手工指定监控节点的列表,当监控的节点增多之后,每次增加节点都需要更改配置文件,非常麻烦,这个时候就需要通过服务发现(service discovery,SD)机制去解决。Prometheus 支持多种服务发现机制,可以自动获取要收集的 targets,可以参考 这里,包含的服务发现机制包括:azure、consul、dns、ec2、openstack、file、gce、kubernetes、marathon、triton、zookeeper(nerve、serverset),配置方法可以参考手册的 Configuration 页面。可以说 SD 机制是非常丰富的,但目前由于开发资源有限,已经不再开发新的 SD 机制,只对基于文件的 SD 机制进行维护。

 

关于服务发现网上有很多教程,譬如 Prometheus 官方博客中这篇文章 Advanced Service Discovery in Prometheus 0.14.0 对此有一个比较系统的介绍,全面的讲解了 relabeling 配置,以及如何使用 DNS-SRV、Consul 和文件来做服务发现。另外,官网还提供了 一个基于文件的服务发现的入门例子,Julius Volz 写的 Prometheus workshop 入门教程中也 使用了 DNS-SRV 来当服务发现。

 

 
2、告警配置管理

 

无论是 Prometheus 的配置还是 Alertmanager 的配置,都没有提供 API 供我们动态的修改。一个很常见的场景是,我们需要基于 Prometheus 做一套可自定义规则的告警系统,用户可根据自己的需要在页面上创建修改或删除告警规则,或者是修改告警通知方式和联系人,正如在 Prometheus Google Groups 里的 这个用户的问题:How to dynamically add alerts rules in rules.conf and prometheus yml file via API or something?

 

不过遗憾的是,Simon Pasquier 在下面说到,目前并没有这样的 API,而且以后也没有这样的计划来开发这样的 API,因为这样的功能更应该交给譬如 Puppet、Chef、Ansible、Salt 这样的配置管理系统。

 

 
3、使用 Pushgateway

 

Pushgateway 主要用于收集一些短期的 jobs,由于这类 jobs 存在时间较短,可能在 Prometheus 来 Pull 之前就消失了。官方对 什么时候该使用 Pushgateway 有一个很好的说明。

 

总结

 

这篇博客参考了网络上大量关于 Prometheus 的中文资料,有文档,也有博客,比如 1046102779 的 Prometheus 非官方中文手册,宋佳洋 的电子书《Prometheus 实战》,在这里对这些原作者表示敬意。在 Prometheus 官方文档的 Media 页面,也提供了很多学习资源。

 

关于 Prometheus,还有非常重要的一部分内容这篇博客没有涉及到,正如博客一开头所讲的,Prometheus 是继 Kubernetes 之后第二个加入 CNCF 的项目,Prometheus 和 Docker、Kubernetes 的结合非常紧密,使用 Prometheus 作为 Docker 和 Kubernetes 的监控系统也越来越主流。

 

关于 Docker 的监控,可以参考官网的一篇指南:Monitoring Docker container metrics using cAdvisor,它介绍了如何使用 cAdvisor 来对容器进行监控;不过 Docker 现在也开始原生支持 Prometheus 的监控了,参考 Docker 的官方文档 Collect Docker metrics with Prometheus;关于 Kubernetes 的监控,Kubernetes 中文社区 里有不少关于 Promehtheus 的资源,另外,《如何以优雅的姿势监控 Kubernetes》这本电子书也对 Kubernetes 的监控有一个比较全面的介绍。

 

最近两年 Prometheus 的发展非常迅速,社区也非常活跃,国内研究 Prometheus 的人也越来越多。随着微服务,DevOps,云计算,云原生等概念的普及,越来越多的企业开始使用 Docker 和 Kubernetes 来构建自己的系统和应用,像 Nagios 和 Cacti 这样的老牌监控系统会变得越来越不适用,相信 Prometheus 最终会发展成一个最适合云环境的监控系统。

 

附录:什么是时序数据库?

 

上文提到 Prometheus 是一款基于时序数据库的监控系统,时序数据库常简写为 TSDB(Time Series Database)。很多流行的监控系统都在使用时序数据库来保存数据,这是因为时序数据库的特点和监控系统不谋而合。

 

  • 增:需要频繁的进行写操作,而且是按时间排序顺序写入

  • 删:不需要随机删除,一般情况下会直接删除一个时间区块的所有数据

  • 改:不需要对写入的数据进行更新

  • 查:需要支持高并发的读操作,读操作是按时间顺序升序或降序读,数据量非常大,缓存不起作用

 

DB-Engines 上有一个关于时序数据库的排名,下面是排名靠前的几个(2018年10月):

 

  • InfluxDB:https://influxdata.com/

  • Kdb+:http://kx.com/

  • Graphite:http://graphiteapp.org/

  • RRDtool:http://oss.oetiker.ch/rrdtool/

  • OpenTSDB:http://opentsdb.net/

  • Prometheus:https://prometheus.io/

  • Druid:http://druid.io/

 

>>>>

参考资料

 

  • Prometheus 官方文档【英文】

    https://prometheus.io/docs/introduction/overview/

  • Prometheus 官方文档【中文】

    https://love2.io/@1046102779/doc/prometheus

  • The History of Prometheus at SoundCloud

    https://promcon.io/2016-berlin/talks/the-history-of-prometheus-at-soundcloud/

  • Prometheus: Monitoring at SoundCloud

    https://developers.soundcloud.com/blog/prometheus-monitoring-at-soundcloud

  • Google And Friends Add Prometheus To Kubernetes Platform

    https://www.nextplatform.com/2016/05/09/google-friends-add-prometheus-kubernetes-platform/

  • 云原生架构概述

    http://dockone.io/article/2991

  • 还不了解 CNCF?关于 CNCF 的三问三答!

    http://blog.daocloud.io/cncf-3/

  • 时序列数据库武斗大会之什么是TSDB

    http://liubin.org/blog/2016/02/18/tsdb-intro/

  • 时序列数据库武斗大会之TSDB名录 Part 1

    http://liubin.org/blog/2016/02/25/tsdb-list-part-1/

  • Prometheus 入门

    https://www.hi-linux.com/posts/25047.html

  • Prometheus 初探

    https://www.opsdev.cn/post/Prometheus-first-exploration.html

  • 监控利器之 Prometheus

    https://blog.xizhibei.me/2017/08/06/monitoring-with-prometheus/

  • 使用Prometheus+Grafana监控MySQL实践

    http://www.ywnds.com/?p=9656

  • 使用Prometheus+grafana打造高逼格监控平台

    http://blog.51cto.com/youerning/2050543

  • 初试 Prometheus + Grafana 监控系统搭建并监控 Mysql

    https://blog.csdn.net/aixiaoyang168/article/details/81354059

  • 使用Prometheus和Grafana监控Mysql服务器性能

    https://segmentfault.com/a/1190000007040144

  • 使用Prometheus监控服务器

    https://blog.frognew.com/2017/02/use-prometheus-on-centos7.html

  • Prometheus 入门与实践

    https://www.ibm.com/developerworks/cn/cloud/library/cl-lo-prometheus-getting-started-and-practice/index.html

  • 基于Prometheus的分布式在线服务监控实践

    https://zhuanlan.zhihu.com/p/24811652

  • grafana+ prometheus+php 监控系统实践

    https://segmentfault.com/a/1190000015876636

  • Grafana+prometheus+php 自动创建监控图

    https://segmentfault.com/a/1190000015922077

  • Prometheus+Grafana监控部署实践

    https://www.cnblogs.com/netonline/p/8289411.html

  • How To Install Prometheus using Docker on Ubuntu 14.04

    https://www.digitalocean.com/community/tutorials/how-to-install-prometheus-using-docker-on-ubuntu-14-04

 

作者丨aneasystone
来源丨网址:https://www.aneasystone.com/archives/2018/11/prometheus-in-action.html
dbaplus社群欢迎广大技术人员投稿,投稿邮箱:editor@dbaplus.cn

年度评选盛典!_2021_IT新治理领导力论坛评选活动邀您共聚!

图片

当前,世界正在经历百年未有之大变局,科技创新速度显著加快,以信息技术、人工智能为代表的新兴科技快速发展。新技术、新业务、新模式、新生态层出不穷,给企业传统的治理模式带来前所未有的挑战。在此背景下,新一代IT治理体系应运而生,关注发展、收益与风险间的平衡,强调科学的治理理念和运行体系,是企业高效、高质量发展的重要抓手。为了加强行业内创新交流,提升业界IT治理整体水平,2021 IT新治理领导力论坛计划于 2021年 12 月召开

 

本次大会旨在 “新治理融惠创新,数字化行稳致远” ,将围绕 “治效兼顾,构筑科技治理新生态” 和 “XOPS创新,领航运维发展新脉络” 两大主题展开。

 

除了精彩纷呈的技术演讲,本次大会还将组织进行年度评选活动。

2021 IT新治理领导力论坛年度评选活动

“2021 IT新治理领导力论坛” 由中国信息通信研究院牵头组织,所有评选活动均秉持公平公正的原则,力图对IT领域的从业者、企业进行一个年终总结。

上届回顾:2020 IT新治理领导力论坛在京召开,年度评选结果隆重公布

图片

“2021 IT新治理领导力论坛”评选活动正在火热报名中!

图片

【评选活动规则】

 本次将针对IT从业人员、企业及IT相关优秀案例进行评选,任何符合评选条件的个人、企业以及优秀案例均可参选,详情如下。

 

申报条件

一、 企业、团队或个人类: 

  •   致力于IT事业发展

  •   在IT领域作出突出贡献

  •   良好的个人美德和社会责任感

  •   在IT领域颇有建树的企业、团队或个人

二、案例类:

  •   拥有自主知识产权

  •   技术水平领先

  •   质量稳定可靠

  •   提供优质服务

  •   具有较强的治理效果与效率提升影响

评选类型设置

  • IT新治理2021年度先锋人物

  • IT新治理2021年度突出贡献专家

  • IT新治理2021年度影响力团队

  • IT新治理2021年度杰出企业

  • IT新治理2021年度卓越创新案例

注1:个人、团队、企业及案例将针对所在行业和领域进行评选。

①行业类型:通信、互联网、金融(银行、证券、保险)、能源、工业、制造业等;

②领域类型:IT治理、IT风险与合规、IT审计、IT资源运营、研发运营、智能化运维(AIOps)、安全、效能度量等。

注2:案例类申报以项目为单位,甲方单位提供项目实践案例(申报企业可与其服务提供商联合提交申报材料);乙方单位提供项目解决方案/产品案例。

评选流程

01

第一阶段:申报征集

  • 时间:即日起 - 2021年10月29日

  • 活动前期,活动组委会将在全国范围内发起征集, 收到个人及企业团队申报的候选材料后,将在评选专题栏目中向广大公众传播。同时活动组委会办公室将设立评选信箱、热线电话等方式,通过各地自荐、专家推荐以及公众推荐等各种方式,最广泛地征集候选对象。经过筛选,针对每项评选内容给出 “提名”名单。

  • 参评单位、团队或个人填写申报表并反馈邮箱(zhouyuwei@caict.ac.cn、liukailing@caict.ac.cn)进行申报,10月29日17:00报名截止。

02

第二阶段:线上投票

  •  时间:11月1日-11月7日

  • 11月7日15:00投票通道关闭。根据评选分类进行票数排名计分。

03

第三阶段:专家评审会答辩

  • 时间:11月中上旬,具体时间另行通知

  • 进行专家评审会及线上答辩,各受邀专家根据参评单位、个人提供的材料及现场答辩表现进行打分,满分为100分,专家评审会最终得分为各专家给出的平均分。

04

第四阶段:评选结果统计

  • 评选最终得分=线上投票得分+专家评审会得分

  • 各类别评选结果根据最终得分排名决定。

05

第五阶段:发布结果

  • 时间:2021年12月

  • 评选结果将在“2021 GOLF+ IT新治理领导力论坛”上隆重揭晓。

     

报名通道

(请务必认真填写真实信息,虚假信息一经审核将取消评选资格)

#01

企业、团队及个人类

图片

提取码:cNth

请长按以上二维码,下载企业、团队及个人评选申报模板。

#02

卓越创新案例类

图片

提取码:WfOx

请长按以上二维码,下载“年度卓越创新案例”评选申报模板。

*本活动最终解释权归 2021 GOLF+ IT新治理领导力论坛评选活动组委会所有。

联系人:

周雨薇 

13810031840

zhouyuwei@caict.ac.cn

刘凯铃 

15650786171

liukailing@caict.ac.cn


 

4T的数据库卡死后,没掌握MySQL源码的我后悔莫及……

作者介绍

王竹峰,去哪儿网数据库总监。擅长数据库开发、数据库管理及维护,一直致力于 MySQL 数据库源码的研究与探索,对数据库原理及实现有深刻的理解。曾就职于达梦数据库,从事多年数据库内核开发工作,是 Inception 开源项目及《MySQL运维内参》的作者,MySQL 方向的Oracle ACE 。

 

一、背景

 

最近组内同学遇到一个问题,说数据库被业务打死了,无响应,只好用 kill -9 pid 杀掉,然后重启,幸好此时的数据库角色是从库,影响不大。同学自述,在杀掉重启的时候,心里默念,千万别启不来啊,这个库的数据量有点大,快要达到 4T 了。做运维的人都知道,事情就不能念叨,一念叨,这事儿就准发生。这次也不例外,确实是出现了。现象是长时间启动不了,基本卡死状态。error log 信息如下:

 

图片

 

通过查看 Note 级别的启动日志发现,在报了最后一条之后,就再也没有新的日志出现了。很久也不会再动。

 

二、分析

 

 
1、TOP命令

 

首先通过 top 命令来确定一下当前实例是不是还在活动:

 

图片

 

PID 为 84448 ,发现 CPU 占用率是 0 ,说明当前实例已经卡死了,没有在跑了。当然也不是死循环(因为死循环的话,CPU肯定是打满的)。

 

 
2、堆栈

 

接下来就要看堆栈了,这个在查问题的时候,是一个非常好的工具。堆栈结果如下:

 

图片

 

从堆栈可以看出,IO 线程完全不工作,都处于 idle 状态,启动线程,即包括 mysqld_main 函数的堆栈,也处于 nanosleep 状态,最主要的两组线程,已经说明了,当前实例啥也不做,完全是 idle 状态,与我们在上面用 TOP 来判断的结果是一样的。

 

三、进一步分析

 

从上面的现象来判断的话,很难找到具体原因,因为很难判断当前线程为什么这么死等,当然,从启动线程基本可以确定的是,是启动时想做一次检查点,但在刷盘的时候一直等不到刷完,基本只能是这样。那我们可以试想一下,等待刷盘,一直等不到,那刷盘线程在做什么呢?这个也很好确定,知道源码的同学,应该了解,刷盘线程是buf_flush_page_cleaner_coordinator,在上面堆栈截图中有,我们再来看一次。

 

图片

 

很明显,这个线程也处于等待状态,那这样就可以大概推断,应该是 innodb 内部出现了乱子,刷盘线程认为没有东西可以刷,所以处于 idle 状态,而启动线程认为有东西需要刷的,所以一直在等,信息没有对齐,所以死等了。

 

那单纯从上面的这些信息,还能继续往下分析吗?也许可以再进步一点点。我们发现,上面的错误日志中,有一行这样的信息:

 

2021-08-27T16:50:24.433063+08:00 0 [Note] InnoDB: Completing truncate for table with id (93752) residing in file-per-table tablespace with id (12742)

 

这个信息比较少出现的,大概是表示某一个表在重启之前做过 truncate,而在重启的时候,需要把这个表redo一次 truncate 。而我们再反过来看启动的堆栈,发现调用buf_flush_wait_flushed的,正是truncate_t::fixup_tables_in_non_system_tablespace ,发现这也是 truncate ,好像能对得上,所以此时可以猜测,是不是与 truncate 有关系。

 

在咨询业务之后,发现在这个实例的生前,确实多次做过数据的 load 与 truncate ,然后知道这个业务的行为,有帮助么?试想从上面的现象,我们还能再往下分析吗?此时我认为不可以了。

 

那怎么办?我认为只能上源码了。

 

四、源码分析

 

我们用源码分析,首先需要解开的是,为什么信息不对称,即刷盘线程认为没有页面需要刷了,而启动线程认为需要刷盘呢?用源码分析,一个很重要的入手点,就是先编译一个相同版本的 Debug mysqld ,然后启动复现这个问题,因为这个问题是必现的,所以查找起来容易很多。

 

等到复现之后,我们把上面的堆栈再看一次:

 

图片

 

有没有发现有很大的不同,信息多了很多,可以具体地看到每一个函数对应的文件,行数等等,上面展示的是刷盘线程buf_flush_page_cleaner_coordinator的状态,代码版本是Percona 5.7.26,可以看出 os_event 的等待位置是在 buf0flu.cc 的 3212 这行,我们拿到对应的代码,看看这行是在做什么。

 

图片

 

可以看到,3212 行的代码是 os_event_wait(buf_flush_event)。这行之上,是刷盘线程的开始位置,熟悉代码的同学都知道,这个位置是用来把innodb恢复过程中,REDO重放产生的脏页刷到文件中去的,而在这行之后,即从下面我们所看到的一行代码 while  (srv_shutdown_state == SRV_SHUTDOWN_NONE){开始,才是真正地刷掉我们数据库正常运行过程中产生的所有脏页的,innodb 是把启动过程中和启动之后正常运行所产生的脏页分阶段刷掉的。

 

知道这个之后,我们就可以知道,3212 这行,是两个阶段的分界线,也就是说,刷盘线程认为数据库的 REDO 已经做完了,而还没有启动完成,所以正常的刷盘还不能开始做,所以就静静地等待在这里。

 

我们此时再回过头来看启动线程所处的位置,堆栈如下:

 

图片

 

熟悉代码的同学知道,innobase_start_or_create_for_mysql是innodb启动的关键函数,在这里调用了truncate_t::fixup_tables_in_non_system_tablespace,这个函数从名字上就能推断出来是干什么的,与日志中最后一行非常相关,我们可以顺便看看日志在哪里打印出来的,代码如下:

 

图片

 

一目了然,即自从日志文件打印这行之后,这个启动就卡死在这里了。非常明确,通过代码验证了我们的推测。

 

那我们现在需要考虑的问题是,为什么在这个位置,innodb认为是需要刷盘的呢?我们再看代码:

 

图片

 

这里是函数 truncate_t::fixup_tables_in_non_system_tablespace 最后的位置,在这里我们能看到对函数 log_make_checkpoint_at 的调用,这个我们能在堆栈中看到,其实他就是卡在了里面。这里还是那个问题,为什么需要刷盘?因为在这个 fixup 过程中,做了很多修改操作,修改的内容可以参考函数 row_truncate_update_sys_tables_during_fix_up 的实现,在上图中有,里面做了大量的修改,以及 SQL 语句的执行,肯定会产生很多脏页。所以 innodb 需要将其刷盘。

 

但为什么刷盘线程不刷了呢?很明显,上面已经解释过了,他已经执行完了 redo 重放产生的脏页,所以已经处于 idle 状态了,他认为在数据库启动之前,他不会再刷盘了,除非 buf_flush_event 事件被 set 一次。那我们的好奇来了, buf_flush_event 正常情况下,是什么时候被 set 的呢?再看代码,总共有两个地方,先看第一个:

 

图片

 

从上图可以看到,他是在 srv0start.cc 的 2892 行被 set 的,如果执行了这行,那刷盘线程就会继续向下执行了,就说明 innodb 启动完成可以正常工作了,而我们现在再看truncate_t::fixup_tables_in_non_system_tablespace()是什么时候调用的呢?从堆栈可以看出来,就是 srv0start.cc:2644 行位置,即是在 buf_flush_event 被 Set 之前的位置,也就是说,innodb 认为 fixup 执行所产生的脏页,还算做是 REDO 重放所产生的(姑且这么认为),那疑问来了,既然这样,刷盘线程怎么就提前退出了呢?我们再通过代码来看,刷盘线程针对 REDO 重放所产生的脏页刷盘工作,在什么情况下会退出:

 

图片

 

可以看到,这个循环退出条件之一,就是recv_sys->heap == NULL,也就是说,只要recv_sys->heap == NULL了,刷盘操作就退出了,我们再看recv_sys→heap是什么时候被设置为NULL的:

 

图片

 

不难发现,recv_sys→heap是在recv_sys_debug_free 中设置为NULL的,那现在问题就变为 recv_recovery_from_checkpoint_finish 是在什么时候调用的了,熟悉代码的同学应该对这个很清楚,这正是完成 REDO 重放的一个重要函数,我们搜索发现:

 

图片

 

可以看到,recv_recovery_from_checkpoint_finish 的调用位置,在 2618 行,是在 fixup_tables_in_non_system_tablespace 被调用之前,细心的同学可能也会从上图中发现,还有一个相似的函数truncate_t::fixup_tables_in_system_tablespace(),从名字可以看到,这是针对系统表的。总之,不管系统表,还是 NON 系统表,都是在 recv_recovery_from_checkpoint_finish 后面被调用,因为之前分析了,只要 recv_recovery_from_checkpoint_finish 调用了,刷盘线程就认为 innodb 再产生的脏页就是正常运行的脏页了,就不负责刷盘了,就会走到等待 buf_flush_event 的位置,而启动线程不这么认为,在重放完成之后,又产生了新的脏页,同时他认为,这里所产生的脏页必须要刷完,此时 buf_flush_event 又没有被 Set ,所以启动线程只能死等了。是的,会一直等下去。

 

我们现在再看 buf_flush_event 被 Set 的第二个位置,即是 buf_flush_request_force ,而这个函数被调用的位置,我们就比较熟悉了,请看:

 

图片

 

同时发现,在 buf_flush_request_force 下面,就是我们当前陷入死循环的函数,也就是说, InnoDB 也认为 fixup 产生的脏页应该由启动之后的刷盘线程来刷掉,即只有等待到事件 buf_flush_event 之后才去做刷盘。所以上面在进入等待状态 buf_flush_wait_flushed 之前,先做一次 buf_flush_event 的 Set 操作,让刷盘线程继续向下执行,进入到正常刷盘状态。

 

然而,当前启动线程,已经处于等待状态了,为什么刷盘线程还处于等待事件 buf_flush_event 的状态呢?细心的同学应该已经注意到了,在上图中,buf_flush_request_force 的调用是有条件的,有一个参数 srv_flush_sync ,此时我看了一下当前参数的值,他是 0 ,这样就可以解释了,正是因为这个参数,导致这个机制失效了,这里的 buf_flush_event 的 Set 失效了,就需要依靠上面第一种情况所说的 Set 了,而此时已经明白,永远不会执行到那里去了,会一直等下去。

 

那现在应该清楚了,本身针对这个问题,流程整体上是没有问题的,只不过有参数 srv_flush_sync ,导致逻辑上面存在了漏洞,那我们如何避免这样的问题,很显然,能用参数控制的办法避免问题,是最友好不过的了,我们只需要把参数 srv_flush_sync (其实就是 InnoDB 参数  innodb_flush_sync)设置为 ON 即可。

 

 
buf_flush_wait_flushed函数状态

 

问题清楚之后,我们再回过头来,看看在buf_flush_wait_flushed函数死等的位置,状态是什么样子的,如下图所示:

 

图片

 

从图中可以看到有很多脏页,并且 oldest 都是小于任何一个 buffer instance 里面的 newest lsn 的,感兴趣的同学可以对照源代码看看,循环退出的条件是 oldest 要大于每一个 instance_newest ,而oldset是一直不变的,一直是 103036344355008,比每一个都小,那为什么一直等不到 oldest 的变大呢?就是因为 buf_flush_page_cleaner_coordinator 线程没有正常工作。

 

而这里也需要纠正在上面我的一个判断,即在 TOP 中看到 CPU 很闲,占用率是 0,所以认为不是死循环,这里是不准确的,因为我们看代码会发现,在 buf_flush_wait_flushed 函数中的等待,也是死循环,只不过有一行代码为:

 

图片

 

注释都说了, sleep 然后 retry ,而 buf_flush_wait_flushed_sleep_time 是多少呢?从代码中看到,是硬编码写死的,为 10000 microseconds ,那很明显,以这样的频率做死循环,确实不至于让 CPU 忙起来。

 

五、解决方法

 

问题现在已经清楚了,那如何解决呢?数据不会变,在实例生前做了 truncate ,这个改不了,一种最简单的办法就是,我们把数据重做了就好了,这确实是的,很简单,但想想,4T 的数据,这个时间成本太高了,DBA 已经很烦做这样的事情了。

 

 
1、解决方法一

 

那有没有更简单,快捷的办法呢?这是有的,既然我们已经编译好了一个debug版本,并且上面也看到了, buf_flush_wait_flushed 函数已经是死循环了,也知道是因为 new_oldest 参数传入的 LSN_MAX 值导致循环结束的条件不能满足,所以死循环,那我们如果可以让这个循环提前结束,条件满足了,不就可以了吗?

 

用 GDB 可以实现这样的功能,直接实战图:

 

图片

 

看到这里,感觉就像是驾驶特斯拉,一踩“油门”,deng 一下就被弹出去一样,数据库瞬间快速正常运转起来,死循环一下子就破了,马上启动完成。

 

 
2、解决方法二

 

还有一种解决办法,就是不依赖当前这次启动过程,而是直接重启一次,重启之前将参数 innodb_flush_sync 修改为 ON ,这样启动就没有任何问题了,成功地避免了这样的问题。

 

 
3、解决方法三

 

具体到这个问题,如果能确定是 truncate 本身操作,而不是其它内部原因,可以将 data 目录下面,对应的 *_trunc.log 文件都删掉,这样数据库启动的时候就不会加载相关信息了,也就不会有问题了,当然,这种办法要谨慎使用,因为毕竟是在做物理上面的数据破坏的,并且有了上面能用参数控制来避免问题的办法,其它解决问题的办法就可以不屑一顾了。

 

本人因为选择了 gdb 的办法来解决此问题,所以其它两种办法都没有机会实践了,叹叹叹!!!

 

六、进一步疑问

 

按照上面的启动方法,数据库是可以正常启动了,但如果下次再 shutdown ,再启动,是不是问题还会出现。答案是否定的,因为正常启动之后,truncate 相关的 log 已经被清掉了,所以再启动的时候,就不会再调用 truncate_t::fixup_tables_in_non_system_tablespace 函数了,所以也就不会有问题了。

 

七、问题澄清

 

本来准备给 bugs.mysql.com 报个 bug 的,为了更准确地表明问题,找到了 MySQL 官方的代码版本,找到了函数 log_preflush_pool_modified_pages ,发现与我们上面分析的代码不太一样,如下图所示:

 

图片

 

可以看出,官方版本代码是没有这个问题的,因为出问题的时候, new_oldest 是 LSN_MAX  ,这种情况下会进入图中有横线的那个分支中去,这里不存在死等的问题,而只有指定刷盘到某一个具体的 LSN 值的时候,才会走到下面的分支。

 

可以大胆猜测一下,这个问题应该是 Percona 改出来的新的问题,并且至今没有被发现。

 

八、总 结

 

问题我们现在清楚了,很明显这个是一个 bug ,通过我们的分析,改 bug 的方式,可以把 fixup 放到 buf_flush_event 后面去做,应该就没有这个问题了,但这个还需要推动官方去修改,我们做为运维人员,只需要学会遇到问题如何去避免,就够了(当然应该去报一个 bug ),当然如果想去尝试改掉这个问题,也是可以的,只不过要维护起来,就很不简单了,如果没有相应的人力,团队,最好不要走这条路。万一改出来问题呢?这个损失可能更大了。

 

这个问题,遇到的人也可能比较少,所以在看了 Percona 5.7.33 最新版本,看着代码也没什么变化,说明至今没有被修改好,同时也说明,针对 truncate 这个问题,官方也没有测试充分。

 

另外,还需要去思考一个问题,对于这个 bug ,如果我们对源码不太了解,这个问题还能解决掉吗?能知道什么原因吗?我想可能做不到,应该是做不到的,这也从侧面说明,DBA 掌握点源码是多么的重要,这是活生生地用源码解决问题的案例啊,或者反过来讲,如果不知道源码,如何能把这个问题,与参数 innodb_flush_sync 能联系起来?MySQL 手册可不会告诉你这些。

 

DBA 这个职业,一直被业界很多人认为即将要被机器替代了,的确,因为云时代的出现,自动化平台的出现,很多操作,都被机器替代了,所以得出的结论是,DBA 不重要了,即将会被淘汰。我认为,这个结论很明显是错误的,云时代以及自动化平台的出现,只能是让 DBA 的入门门槛变得更高,让 DBA 的工作效率更高,让 DBA 承担起更重要的工作,有时间解决更复杂的问题,有精力构建更好的平台、架构,做更多的有价值的输出。而学习源码,就是做一个不会被淘汰的 DBA 的最好的捷径。

 

而更重要的是,你的职业是一个 MySQL DBA,MySQL 给了你一个学习源码的机会,让你有源码可学,这是其它数据库所不能替代的。

 

MYSQL is The world's most popular open source database!

 

作者丨去哪儿网DBA团队
来源丨公众号:Qunar技术沙龙(ID:QunarTL)
dbaplus社群欢迎广大技术人员投稿,投稿邮箱:editor@dbaplus.cn

PPT下载丨2021_Gdevops全球敏捷运维峰会-广州站精华回放

 
 

重磅开篇!大量干货PPT开放下载

方式1:登录以下链接并输入提取码1015

https://pan.baidu.com/s/1Hd1v9qPm04dyfOI6oWaGVw

方式2:点击文末【阅读原文】

并输入提取码1015

移步文末还可报名参加DAMS峰会上海站

 
 
 

10月15日,2021 Gdevops全球敏捷运维峰会在广州成功举办,近30位来自运维、数据库、金融科技领域的产研技术专家,带着国内外前沿理念、独家落地实践等满满干货点燃火爆现场,一起来回顾不容错过的精彩!

 

图片

 

 
 
 
主会场

 

图片

中国信息通信研究院

云计算与大数据研究所副所长 魏凯

《DataOps与新型数据基础设施》

 

峰会开场之际,由中国信息通信研究院云计算与大数据研究所副所长魏凯老师发表致辞,并带来了《DataOps与新型数据基础设施》的前沿分享。他分析了数据基础设施发展的四大趋势:整合一体、智能驱动、全面云化、内生安全,基于此,中国信通院与业界伙伴多年来共同定义面向数据要素的新型数据基础设施,推出面向全品类数据基础平台技术产品的标准、评测及行业研究。他还为大家全面介绍了DataOps(数据运维开发一体化)理念,并指出数据要素需要基础设施建设和数据管理方法的变革,总结为三点:数据要素需要新型数据基础设施;数据治管理能力为数据应用奠定基础;DataOps是企业数字化转型必备能力。

 

图片

新炬网络副总裁 吴珑

《企业数字化下的运维敏捷化转型》

 

曾在国内外多家大型IT企业任职高管的新炬网络副总裁吴珑老师,对企业运维体系建设具有丰富的研究与实践经验。会上,他对新炬网络提纲挈领总结出的企业运维敏捷转型3P要素(Platform技术平台、People人员团队、Process流程)展开了详细分享,并基于新炬网络在电信、金融、交通、政府等行业客户十多年的服务经验,明确指出把数字化理念落实到运维工作的关键点:1、聚焦于业务连续性的运维;2、运维开发转型,实现敏捷化工具运维;3、全栈运维,贯穿整个系统生命周期当中;4、流程自动化,平衡效率与稳定;5、逐步实现运维数字化与智能化。展望未来,新炬网络将坚持“HI+AI”的双向赋能路径,持续优化并升级自有产品和技术,通过创建数字空间、拉通多边价值效应、指引智能落地,与客户共同实现运维数字化。

 

图片

OceanBase资深研发总监/开源负责人 封仲淹

《OceanBase开源核心解读及未来展望》

 

自正式开源后的140天,OceanBase开源版已经驶入了快车道。会上,OceanBase资深研发总监及开源负责人封仲淹老师,分别从高可用、高并发写、TP & AP融合、历史库、多租户、高可用&两地三中心部署等应用场景,对OceanBase社区版展开了详细介绍,并分享了OceanBase RoadMap、生态工具及ISV合作等未来规划。

 

图片

建信金科(河南)总裁 朱志

《敏捷的力量之源》

 

在建行及建信金科历任技术及管理数职的朱志老师,在会上向大家发出了灵魂拷问:我们追求的是什么样的敏捷?敏捷了就一定幸福吗?通过多年研究经验和身体力行,他总结得出敏捷的力量,其实来源于“快”与“远”的抉择,并剖析了敏捷的三层力量:1、认知技术本质;2、参透业务方向;3、坚定组织意志。最后,他特别强调,未来无论是做敏捷的转型还是技术的变革等任何事情,都应该记住这三个M的叠加,即:Agility = Margin × Market × Member。

 

图片

华为云数据库服务产品部CTO 庄乾锋

《解读企业级云原生分布式数据库—GaussDB》

 

企业数字化转型,已经从过去的ON Cloud走到了新阶段的IN Cloud,所以云时代的数据库同样需要这样的转变。由此,华为云数据库服务产品部CTO庄乾锋老师,介绍了华为云在数据库及相关工具研发上的经验,包括GaussDB(for openGauss)、GaussDB(for MySQL)、GaussDB NoSQL多模系列产品,以及UGO和DRS两款工具,最后还分享了三个典型实践案例及开源社区、人才培养等未来规划。

 

图片

贝壳找房高级总监 史海峰

《浅析数字化转型与产业互联网》

 

“看懂层出不穷的新名词,理解技术进步的价值与影响,探寻产业发展的真实场景,明晰技术的定位和目标”,出于对技术从业者这样的建议,贝壳找房高级总监史海峰老师展开了分享。他依次帮大家理清了数字化转型和产业互联网的概念,信息化、数字化、智能化的区别,B端与C端产品的差异,以及互联网下半场较上半场的转变,最后基于贝壳找房的发展历程和战略规划,总结出实现数字化转型的架构方法。

 

图片

 

感谢以上六位嘉宾老师,为我们谱写出一幅关键技术领域的发展蓝图!

 

 
 
 
数据库专场

 

开源、分布式、低延迟、高吞吐、实时、上云……在这些纷繁的关键词中,我们到底需要怎样的数据库?怎么选择和改造最适合自身的数据库?本次Gdevops峰会的数据库专场给大家带来了不少建议和启发。

 

图片

 

  • vivo通用存储研发负责人肖博分享《ABC场景驱动下,如何制定数据库与存储技术规划》

  • 爱可生技术总监洪斌分享《如何打造稳健的数据库管理平台》

  • 货拉拉DBA负责人蔡鹏分享《混合云环境下的数据库治理挑战与实践》

  • 涛思数据创始人&CEO陶建辉分享《性能提升十倍:TDengine高效时序数据处理实践》

  • 建信金科DB产品负责人陈晓新分享《超大规模数仓集群在大型商业银行的落地实践》

  • 甲骨文MySQL首席架构师王伟分享《MySQL在OLTP和OLAP云服务上的最新技术实践》

  • 携程高级研发经理蔡岳毅分享《基于ClickHouse+StarRocks,构建支撑千亿级数据量的高可用查询引擎》

 

 
 
 
金融专场

 

后疫情叠加新基建时代的到来,金融企业须从被动式技术创新,走向主动改革式创造,才可在数字化转型之路上占领制高点,成败或将在此一举。本次Gdevops峰会的金融专场带来了备受关注的议题内容,吸引众多技术朋友的观看。

 

图片

 

  • 中邮消费金融部门负责人/区块链工程博士李远鑫分享《消费金融数据中台及智能营销运营体系建设实践》

  • 新炬网络运维产品部总经理宋辉分享《“中台能力+场景生态”的智慧运维管理平台架构实践》

  • 招商银行总行资深架构师郑丹分享《招商银行高可用架构与云平台建设实践》

  • 汇丰科技数据分析经理吴仕橹分享《大数据的智能处理和数据可视化实践》

  • 中信银行DevOps实施牵头人李红涛分享《中信银行的DevOps新实践》

 

 
 
 
运维 & DevOps专场

 

过去一年,云原生技术发展如火如荼,在容器、微服务等技术普及和加持下,IT基础设施已然发生了新一轮变化。运维作为IT基础设施的管理者,在云原生时代的职能要求也将随之改变。在本次Gdevops峰会的运维 & DevOps专场,就分享了不少云运维的最新实践。

 

图片

 

  • 美图SRE负责人石鹏分享《美图:低成本全链路监控实战与SRE稳定性运营》

  • 端点科技基础平台/DevOps负责人郑嘉涛分享《云原生架构下,企业一站式DevOps平台建设实践》

  • 腾讯游戏混沌工程负责人吴召军分享《持续保障系统的稳定性和高可用:腾讯游戏混沌工程实践》

  • 平安银行数据库团队经理王鹏冲分享《传统银行关键业务和复杂架构挑战下,如何做到数据库敏捷运维》

  • 京东科技数据库团队负责人高新刚分享《维稳618和双11:京东科技数据库海量运维的生态体系建设与实践》

  • 网易游戏团队负责人林香鑫分享《运维能力可管理:网易游戏面向终态的应用交付管理实践》

  • 平安集团E敏捷DevOps平台负责人熊星分享《大型金融行业DevOps工具链的建设实践》

 

 
 
 
特别鸣谢

 

2021 Gdevops全球敏捷运维峰会-广州站的成功举办,有赖于一众专家老师、合作单位、媒体平台的倾情相助,在此衷心感谢所有专家老师、台前幕后的工作人员,以及以下合作单位和支持媒体:

 

图片

 

 
 
 

<来不了广州,还有上海站等你>

 
 
 

 

错过了广州站峰会的朋友也不必遗憾,因为同样由dbaplus社群主办的DAMS中国数据智能管理峰会将于11月5日在上海举办,同样准备了干货满满的议题期待大家的到来:

 

2021 DAMS中国数据智能管理峰会-上海站

 

演讲嘉宾所在单位:中国信通院云大所、阿里、腾讯、京东、百度、中国移动、中国电信、蚂蚁集团、美团、携程、快手、工商银行、农业银行、平安银行、光大银行、汇丰银行、哈啰出行、复旦大学等产学研界技术领跑单位。

 

演讲议题聚焦:

  • 大数据:数据治理丨数据仓库丨数据中台丨搜索平台机器学习

  • 数据库:分布式丨迁移丨上云丨HTAP丨国产丨开源丨图数据库

  • 运维:AIOps丨DataOps丨CI/CD丨混沌工程丨数据安全丨数智化

  • 金融科技:开源数据库丨分布式选型丨中台丨智能丨数字化转型

    ↓点这里并输入提取码1015可下载本次峰会PPT
    阅读原文

从银行到BAT,为何云才是数字金融的未来?

一、开篇忆往事:往事并非云烟

 

2010年云计算的概念火起来。

 

当年的中国IT领袖峰会上,BAT大佬华山论剑,对于云计算诸位如是说。

 

技术出身的李彦宏讲:“云计算这个东西,不客气一点讲,它是新瓶装旧酒,没有新东西。”

 

产品出身的马化腾讲:“云计算这个话题比较技术性,它是一个比较超前的概念。可能你过几百年、一千年后,到‘阿凡达’时代,那确实有可能。但现在还是过于早了。”

 

不懂技术的马云讲:“我的理解,云计算最后是一种分享,数据的处理、存储并分享的机制。我们对云计算是充满信心和希望,觉得这又找到一个新的矿产,阿里拥有大量消费数据、支付宝交易数据,这些数据对我们有用,对社会更有用。”

 

世事往往如此,不懂的人往往破局。

 

天龙八部中不懂对弈的虚竹,破了珍珑棋局。

 

图片

 

一年后,2011年的双十一,马云把淘宝商城更名为天猫。

 

潮水般的用户,零点涌入后台,程序崩溃。技术负责人南天把自己和同事关在小黑屋内,张勇都不敢敲门询问。

 

系统濒临崩溃4秒前,危机解除。

 

后来,南天说,那晚要是修复不了,跳楼的心都有。

 

银行同样疲于奔命。几家主要网银,在那一夜轮流挂掉、抢修、再挂、再修。

 

当年,刚进阿里时,工程师胡喜设计订单号,数字上限9999万。他以为这远超国人购买力顶峰,在支付宝的有生之年,是不会用完的。

 

然而,2012年双十一的订单数便超1亿。世界末日没到来,但数据的潘多拉魔盒已打开。

 

逝者如斯夫,不舍昼夜。

 

2013年,双十一全天成交额350亿,2014年571亿。2015年,双十一成交额开始按秒计算。

 

2018年,双十一成交额定格在2135亿元。

 

没有任何卡顿宕机,一切云淡风轻。背后强大的阿里云计算能力,依靠自研的飞天,驯服了全世界“剁手党”的疯狂。

 

这一年,阿里云用了三年时间从季度营收4.85亿到突破50亿,用了一年半的时间付费用户数从50万突破100万。

 

这一年,工信部印发《推动企业上云实施指南(2018-2020年)》。

 

问世间,云为何物?

 

支撑双十一惊人交易量的云架构给出了答案。

 

19世纪80年代,电的发明带来了第二次工业革命,人类从此步入电气时代,数字化时代的种种奇迹底色依然是电。

 

十八世纪末,前往英国中部的记者称,那里的棉纺厂深夜不休,铸造厂灯火通明,巨大烟柱直冲夜空。

 

马克思说:工业革命后,昼夜的概念,已变得模糊不清。

 

云计算是数字时代的算力。

 

云计算是这个时代的电力。

 

二、云,是技术,是文化

 

问世间,云计算究竟为何物?

 

专业人士会专业地告诉你,云计算(cloud computing)是一种分布式计算,通过网络“云”将巨大的数据计算处理程序分解成无数个小程序,然后,通过多部服务器组成的系统处理分析这些小程序,得到结果并返回给用户。这项技术可以在很短的时间内(几秒钟)完成对数以万计的数据的处理。如今的云服务已不仅是分布式计算,而是分布式计算、效用计算、负载均衡、并行计算、网络存储、热备份冗杂和虚拟化等计算机技术混合演进并跃升的结果。

 

专业人士会通俗地告诉你,“云”实质上就是一种提供资源的网络,云服务商将计算能力作为一种商品,在互联网上出售,使用者可以随时获取,按需使用,无限扩展,按量付费。“云”就像电力和自来水一样,我们可以随时用,不限量,按照使用量付费给电厂和自来水厂即可。 

 

如此看来,云是技术。

 

佛利德曼在《世界是平的》中说,技术平台每隔5至7年就要发生一次颠覆性改变,但很多人却需要用10至15年才能适应。

 

颠覆世界的从非技术,而是人适应技术变化的过程。

 

2019年,中国人民银行出台的《金融科技(Fin-Tech)发展规划(2019-2021年)》提出,合理布局云计算,统筹规划云计算在金融领域的应用。

 

云计算成为当下中国金融科技的题中应有之义。

 

上云之路,是中国金融机构,特别是大型商业银行IT架构的“成长”之路。因为历史的必然,国内银行普遍基于国外核心基础软硬件,构建起了集中式IT架构。这种架构下“竖井式”开发模式自然而生,造成大量单系统、紧耦合,不仅业务响应不够敏捷,而且资源利用率不高、运维复杂、投入居高不下。

 

这场IT架构的云化之路,技术只是手段,事关的是时间、人力、物力、财力,更深层次关乎的是传统金融机构能不能摆脱复杂架构的束缚,以更加敏捷的身姿、更有效率的行动专注于创新。

 

数字化转型的底层逻辑是一场关于效率的革命。

 

云,一项跨时代的技术,在传统金融机构数字化转型的道路上,赋能敏捷与效率。

 

春风化雨,润物无声,文而化之。

 

云是技术,更是文化。

 

三、银行数字化转型,云知道

 

这个世界越来越复杂。

 

复杂的根源诉诸于客户的个性化、产品的复合化、场景的多元化等等因素。

 

一个世纪前,福特说“不管消费者需要什么,我生产的汽车都是黑色”。2019年“双11”,欧莱雅中国总裁说“22年前进入中国时,美妆行业千人一面,现在是一人千面”。

 

这是当下客户的变化,对汽车与美妆行业如此,对银行亦如此。

 

过去十年和看得见的未来,商业银行最大的不确性是客户的变化。“九五之尊”与“千禧一代”的崛起,老龄化时代的来临;家庭财富管理的渴求;个人金融需要在衣食住行中更加有效感知、更加实时智能;公司金融,特别是挖掘中小微的数字化蓝海,不仅是流程产品的数字化,更要步入工业互联网和产业生态圈……

 

在充满不确定的变化中转型,变中有变,何其难也。

 

作为中国最早开启信息化大幕的行业,中国银行业使用计算的历史可以回溯到上世纪70年代,中国银行引入了第一套理光-8(RIOCH-8)型主机系统。经过40多年的发展,中国银行业从算盘到键盘、到网络,经历了从手工到自动化,从单机到联网,从分散式架构到集中式架构,从面向流程设计到面向服务设计螺旋式上长的过程。

 

这是一段浓墨重彩的历史。

 

时至今日,中国银行业的信息化水平依然在百行百业中名列翘楚。

 

这段岁月中沉淀的那些顺应大势、超越时代的眼光与勇敢,值得永远铭记,是今日中国银行业数字化转型坚定的底气。

 

但是,过去是你骄傲,也是你的束缚。

 

从第一性原理出发,银行传统的集中式IT架构解决的是企业内部资源优化的问题,即使实现了内部资源的优化,最终的结果往往是构建起一套封闭的技术体系,并在无形中支撑着业务的竖立井与壁垒。

 

何谓架构?架构是解决复杂问题、把握不确定的方法论。

 

所以对于传统商业银行,当下的数字化转型是在变中求变。

 

从表面上看,这套集中架构以及其所形成的解决之道,包括响应周期、成本、效率已经越来越难以满足客户的需求。根据《2019中国企业数字转型指数研究》显示,包括银行业在内的中国企业,数字化转型成效显著的比例仅为9%,平均成绩只有45分。其中一个显著的影响因素是,作为数据这一数字化关键生产要素的产生、加工和价值挖掘的主要承载工具,IT基础设施的生产力是否强大直接影响着数字化转型的进程。陈旧的IT架构无力支撑上层应用、或者说客户的多元需求,已经成为数字化转型最为底层瓶颈。

 

从深层次看,数字化转型的本质上是在原有的组织、流程、制度、文化框架下,生长出一个更具生机的经营范式。这个生长的过程需要根植于更具生产力的新型IT架构,始于资源禀赋与专业能力,寓于市场、客户与监管,固化为流程、机制与体制,最终沉淀为文化与价值观,在制度无法触及的地方,成为最底层的柔性生产力。

 

这一次,云计算与传统IT架构截然不同。

 

云提供的不是硬件加软件的IT解决方案,而是构建起一套以用户为中心、以服务为核心、以技术为支撑的数字化基础设施,并带来经济、敏捷、生态、创新四大关键价值:

 

 
1、经济价值

 

云计算在经济学上更加经济。作为一种大规模分布式计算模式,抽象、虚拟、可扩展和可被管理的计算能力、计算存储、计算平台和计算服务汇聚成资源池,按需交付给使用者。构建云计算之初,无论是基础设施、平台还是软件,的确需要较高的初始固定投入,但是一旦建成,就可以反复共用而极少耗损,在不断的使用扩展中边际投入将持续降低。个性化的每项增值业务,只要进行一个较低的边际投入,就可以展开广泛的服务,无须从头开发基础设施、平台和软件。换而言之云计算具备规模化所带来的经济性。

 

 
2、敏捷价值

 

万物互联的第四次科技革命已到临界点。如果说过去十年,银行的经营之道是“物理网点+在线渠道+集中式架构”,那么未来十年,“云+端+生态+场景云”才是新的生存之道。天下武功唯快不破,在这个重塑的过程中,敏捷至关重要。

 

云因为天然的基因带来三种敏捷,首先是场景敏捷,客户需要的因我而变的一人千面场景,云因为解决事务一致性问题的特性,以及未来“金融云+行业云”的布局,可以提供快速组合形成方案;其次是处理敏捷,即通过对业务功能进行拆分解耦,使业务系统更加灵活,同时每部分多实例运行,大幅提升系统可用性及处理能力,同时通过对数据的分布式存储及访问,提升大数据量表的访问能力;再次是体验敏捷,包括手机银行在内诸多面向客户的渠道上线时间将从“周”到“天”,响应客户需求的时间从秒级到毫秒级,更为重要的是上云确保与消费者永续连接,让互动更频繁、摩擦更少和充分定制化, 实质上是一种高频次随时、随地、随心的数据按需服务方式。

 

 
3、生态价值

 

《BANK4.0》中“银行无处不在,就是不在银行里”的金句,预示着场景生态在未来银行的作用。云天生具备生态基因。随着全社会、全要素数字经济的蓬勃发展,零售、制造、能源、医疗、教育、娱乐等不同行业,都将形成各类云化服务。无处不在、就是不在银行的金融服务,将伴随开放共享的金融上云的步伐,形成“金融云+行业云”的态势。银行与不同行业互为平台,互为流量,价值共享,相互赋能、协同共生。其后的技术逻辑在于基于云平台下建立起的企业间数据、技术和产品连接,极大简化系统架构和业务接口的复杂性,要远比在封闭技术体系上更加简单迅速。

 

假以时日,“金融云+行业云”将是数字中国一道靓丽的风景线。

 

 
4、创新价值

 

创新很贵,因为必然包含试错,云能够让创新“便宜”。从技术侧看,IT技术发展从非线性,需要一定的成熟度周期,其速度远超一般企业IT基础设施迭代的速度,这意味着在下一个更新周期到来之前,创新需要持续为性能、效率和可用性逐渐落后的IT基础设施付费,而竞争对手很可能在通过云上的技术红利获得更优质的IT资源和IT技术。从业务侧看,以云计算、云架构为基础,数字化转型创新可以更加聚焦业务和客户,例如如何面向全局优化,实现与供应商等合作伙伴以及客户的数据集成,构建面向全局乃至全产业链优化的开放技术体系,或是利用数字技术结合数据洞察,加速生产、提高效率或是改善成本。

 

【一个栗子:以AI领域当前炙手可热的GPU算力为例,从2018年9月到2020年5月,GPU单卡算力提升了大约7倍,在特定场景下提升了11倍,8块GPU卡的AI超算系统的峰值算力可达10 PetaOPS。如果一家企业在2019年初投入1000万用于采购GPU算力,那么现在这些算力的价格可能只是原来的几分之一。】

 

四、数字金融,大风起兮云飞扬

 

当下国内银行正处于从集中式向云分布式架构演进的关键时期。

 

预计未来几年,无论大型商业银行、还是中小银行,都会积极探索将其核心系统和分布式架构采用云技术来构建。

 

对于传统金融机构,云计算已经从增长之道转变为生存之道。

 

较为典型的有四个案例:

 

图片

 

 
1、渐进式变革的宇宙行

 

工商银行分布式云计算转型主要由两个因素驱动:一是外部因素,加大在核心系统和关键技术研发创新,研究开源技术在银行重要信息系统的应用;二是内部因素,业务创新需要具有对海量数据的处理能力、分析能力和成果转化能力。面对客户互联网化、移动化发展趋势,工商银行在大数据、电子商务、互联互通、客户体验等战术层面积极应对。

 

工商银行已建成九大企业级分布式技术体系,具体包括分布式服务、软负载均衡、分布式消息、分布式事务、分布式缓存、分布式批量、分布式对象存储、分布式文件共享存储和分布式数据。日均服务调用量和缓存日均访问量均达到数十亿级别,消息发送峰值每秒超过百万笔。目前,已基本形成主机 + 开放平台的双核心架构,经过大规模的生产考验,有相当多的应用通过服务化完成分布式转型。

 

图片

 

 
2、几分“亚马逊味”的建设银行

 

建行于2013年投产私有云,历经5年锤炼,支持了新一代核心系统运转。2018年建行引入业界成熟的公有云技术栈,有效支持了敏态自营业务和外部客户托管业务的部署投产,并逐步形成了融合私有云和公有云技术栈的“建行云”品牌。建行分布式架构经过多年的摸索和实践,已由点向面逐步推广,2014年首先在新一代核心业务系统建设中使用SOA架构,2019年分布式架构转型上升为全行业务系统的重点战略方向。云计算和分布式“灵活、弹性、敏捷、共享”等特性为支撑建行三大战略和“第二发展曲线”的落地,满足业务迅猛发展带来益处的同时,数据中心也面临了巨大的挑战,当然也迎来了转型的机遇。

 

大型商业银行中,“建行云”品牌是唯一对外输出的云服务,本质上输出的是基于公有云的SAAS场景生态服务,这种模式最为成功的典范是亚马逊。

 

图片

上图:建行云网页

 

建行并非第一个吃螃蟹者。早再2017年,招商银行旗下招银云创宣布,建设国内首个基于IBM System i的金融行业云,并开始对外输出。

 

图片

上图:招银云创网页

 

场景生态建设中,授人以鱼不如授人以渔,建行云和招银云创的云,比别的云上玩家更具外向性。

 

图片

 

图片

 

 
3、在核心重构中“云化”的邮储和民生

 

2021年4月18日,中国邮储银行新一代分布式核心系统技术平台成功投产上线并同步启动旁路验证。邮储银行新一代分布式核心系统是国内乃至全球大型商业银行中率先基于X86服务器云架构、支持海量交易处理的分布式核心银行系统,该系统上线之初预计可具备日均20亿笔的交易处理能力,未来可随业务量增长按需动态扩展。

 

该系统的亮点之一就是分布式技术平台作为全行级技术底座,自下而上划分为微服务框架、技术中台、业务中台三层,结构稳定灵活,具备多活容灾切换、单元水平在线扩容、微服务治理、故障感知转移、业务强一致性、灰度发布等能力。采用单元化微服务架构,根据业务组件把复杂系统按照业务组件进行微服务化拆分,按照服务特性划分成不同类型的单元,不同单元均可以根据业务需要实现动态延伸、弹性扩展。

 

2021年6月3日,民生银行宣布已实现分布式核心“亿级客户联机无感迁移”。按照民生“仿生金融服务(BioFaaS,即Bionic Finance as a Service)”的愿景,这次生机旨在为客户提供深度场景融合、个性化服务触达,智能化交互的金融服务,并为此实施了一系列平台建设和架构转型工作,分布式体系、云原生应用平台、AI中台建设是数字化基座建设的重中之重。

 

其中云原生的建设思路抽象为按照微服务、容器化的架构设计应用、兼顾DevOps标准,满足持续交付基本诉求,即:云原生 = 微服务 + DevOps + 持续交付 + 容器化,数据中台是民生云原生的重要实践。升级后的分布式核心系统能满足10亿级用户,5万TPS处理速度和30毫秒以内响应时间的技术要求,可有效支撑该行未来5-10年的业务增长。

 

图片

上图:民生银行云原生系统示意

 

图片

 

 
4、云上“原住民”的网商银行

 

网商银行于2015年6月25日正式开业,是银监会批准成立的中国首批民营银行之一,也是第一家将核心系统架构在金融云上、没有线下网点的科技银行。阿里系蚂蚁科技集团股份有限公司认购该行总股本30%股份。

 

基于金融云计算平台研发的银行核心系统,网商银行拥有了处理高并发金融交易、海量大数据和弹性扩容的能力,利用互联网和大数据的优势,给更多小微企业提供金融服务。网商银行有一个非常出名的310模式——三分钟申请贷款,一秒钟到账和零人工干预,全流程线上信用贷款模式,满足了小微企业“小、急、频”的碎片化贷款需求。

 

五年之前就已经率先“吃到螃蟹”的网商银行, 2019年年报数据显示,净利润为12.5亿元,不良贷款率为1.3%。截至2019年末,网商银行已累计服务小微企业和个人经营者2087万户,同比去年增长70%。

 

大风起兮云飞扬,以大数据,云计算,人工智能,5G,物联网,区块链等新一代信息技术,将构建起支持整个“数字中国”的技术底座,这就是数字基础设施,如同工业时代的高铁和高速公路,也是包括商业银行在内企业制胜未来的关键能力。

 

未来十年是数字基础设施的安装期。除了原住民的网商银行,回首传统银行上云之路的起点,都有着类似的建设数字基础设施共同目标,可以概括为 “三化”: