滴滴从 KV 存储到 NewSQL 实战

Fusion-NewSQL 是由滴滴自研的在分布式 KV 存储基础上构建的 NewSQL 存储系统。Fusion-NewSQL 兼容了 MySQL 协议,支持二级索引功能,提供超大规模数据持久化存储和高性能读写。

一. 遇到的问题

滴滴的业务快速持续发展,数据量和请求量急剧增长,对存储系统等压力与日俱增。虽然分库分表在一定程度上可以解决数据量和请求增加的需求,但是由于滴滴多条业务线(快车,专车,两轮车等)的业务快速变化,数据库加字段加索引的需求非常频繁,分库分表方案对于频繁的 Schema 变更操作并不友好,会导致 DBA 任务繁重,变更周期长,并且对巨大的表操作还会对线上有一定影响。同时,分库分表方案对二级索引支持不友好或者根本不支持。

鉴于上述情况,NewSQL 数据库方案就成为我们解决业务问题的一个方向。

二. 开源产品调研

最开始,我们调研了开源的分布式 NewSQL 方案:TiDB。虽然 TiDB 是非常优秀的 NewSQL 产品,但是对于我们的业务场景来说,TiDB 并不是非常适合,原因如下:

  • 我们需要一款高吞吐,低延迟的数据库解决方案,但是 TiDB 由于要满足事务,2pc 方案天然无法满足低延迟(100ms 以内的 99rt,甚至 50ms 内的 99rt)
  • 我们的多数业务,并不真正需要分布式事务,或者说可以通过其他补偿机制,绕过分布式事务。这是由于业务场景决定的。
  • TiDB 三副本的存储空间成本相对比较高。
  • 我们内部一些离线数据导入在线系统的场景,不能直接和 TiDB 打通。

基于以上原因,我们开启了自研符合自己业务需求的 NewSQL 之路。

三. 我们的基础

我们并没有打算从 0 开发一个完备的 NewSQL 系统,而是在自研的分布式 KV 存储 Fusion 的基础上构建一个能满足我们业务场景的 NewSQL。Fusion 是采用了 Codis 架构,兼容 Redis 协议和数据结构,使用 RocksDB 作为存储引擎的 NoSQL 数据库。Fusion 在滴滴内部已经有几百个业务在使用,是滴滴主要的在线存储之一。

Fusion 的架构图如下:
滴滴从 KV 存储到 NewSQL 实战
我们采用 hash 分片的方式来做数据 sharding。从上往下看,用户通过 Redis 协议的客户端就可以访问 Fusion,用户的访问请求发到 proxy,再由 proxy 转发数据到后端 Fusion 的数据节点。proxy 到后端数据节点的转发,是根据请求的 key 计算 hash 值,然后对 slot 分片数取余,得到一个固定的 slotid,每个 slotid 会固定的映射到一个存储节点,以此解决数据路由问题。

有了一个高并发,低延迟,大容量的存储层后,我们要做的就是在之上构建 MySQL 协议以及二级索引。

需求

滴滴从 KV 存储到 NewSQL 实战

综合考虑大多数用户对需求,我们整理了我们的 NewSQL 需要提供的几个核心能力:

  • 高吞吐,低延迟,大容量
  • 兼容 MySQL 协议及下游生态
  • 支持主键查询和二级索引查询
  • Schema 变更灵活,不影响线上服务稳定性。

架构设计

Fusion-NewSQL 由下面几个部分组成:

1. 解析 MySQL 协议的 DiseServer
2. 存储数据的 Fusion 集群 -Data 集群
3. 存储索引信息的 Fusion 集群 -Index 集群
4. 负责 Schema 的管理配置中心 -ConfigServer
5. 异步构建索引程序 -Consumer 负责消费 Data 集群写到 MQ 中的 MySQL-Binlog 格式数据,根据 schema 信息,生成索引数据写入 Index 集群。
6. 外部依赖,MQ,Zookeeper

架构图如下:
滴滴从 KV 存储到 NewSQL 实战

技术挑战及方案

1.SQL 表转 Hashmap

MySQL 的表结构数据如何转成 Redis 的数据结构是我们面临的第一个问题。

如下图:
滴滴从 KV 存储到 NewSQL 实战
我们将 MySQL 表的一行记录转成 Redis 的一个 Hashmap 结构。Hashmap 的 key 由表名 + 主键值组成,满足了全局唯一的特性。下图展示了 MySQL 通过主键查询转换为 Redis 协议的方式:

滴滴从 KV 存储到 NewSQL 实战
除了数据,索引也需要存储在 Fusion-NewSQL 中,和数据存成 hashmap 不同,索引存储成 key-value 结构。根据索引类型不同,组成 key-value 的格式还有一点细微的差别 (下面的格式为了看起来直观,实际上分隔符,indexname 都是做过编码的):

1. 唯一索引:

Key: table_indexname_indexColumnsValue Value: Rowkey

2. 非唯一索引:

Key: table_indexname_indexColumnsValue_Rowkey Value:null
造成这种差异的原因就是非唯一索引在加入 Rowkey 之前的部分是有可能重复的,无法全局唯一。另外,唯一索引不将 Rowkey 编码在 key 中,是因为在查询语句是单纯的“=”查询的时候直接 get 操作就可以找到对应的 Rowkey 内容,而不需要通过 scan,这样的效率更高。

滴滴从 KV 存储到 NewSQL 实战
后面会在查询流程中重点讲述如何通过二级索引查询到数据。

2. 数据和索引一致性

因为数据和索引分别存储在不同 Fusion 集群,数据和索引的一致性保证就成了 Fusion-New 系统面临的一个关键点,在没有分布式事务的情况下,我们当前选择了保证数据索引的最终一致性。用户写入数据在数据集群中开启 RocksDB 的单机事物,同时按链接保序,这样数据流入 MQ 的时候就是有序的。异步模块从 MQ 中消费出来再批量写入到索引集群,整个流程就保证的索引数据的构建与数据集群真实的顺序一致。当然,这中间存在一个时间窗口的数据不一致,这个时间取决于 MQ 的吞吐能力。

3. 二级索引查询

下面是一个使用二级索引查询数据的案例:
dise-server 会根据用户查询条件和当前所有索引做匹配,找到符合的索引,然后通过 Redis 的 scan 命令,按前缀搜索 index 集群的数据,获取符合条件的主键。

如下图:
滴滴从 KV 存储到 NewSQL 实战
通过主键,可以直接到 Data 集群查到相应的数据。

根据上面索引数据的格式可以看到,scan 范围的时候,前缀必须固定,映射到 SQL 语句到时候,意味着 where 到条件中,范围查询只能有一个字段,而不能多个字段。

比如:
滴滴从 KV 存储到 NewSQL 实战
索引是 age 和 name 两个字段的联合索引。
如果查询语句如下:
select * from student where age > 20 and name >‘W’;
scan 就没有办法确定前缀,也就无法通过 index_age_name 这个索引查询到满足条件的数据,所以使用 KV 形式存储到索引只能满足 where 条件中有一个字段是范围查询。当然可以通过将联合索引分开存放,多次交互搜索取交集的方式解决,但是这就和我们减少 RPC 次数,降低延迟的设计初衷相违背了。为了解决这个问题,我们引入了 Elastic Search 搜索引擎。

架构图如下:
滴滴从 KV 存储到 NewSQL 实战
我们建议用户将需要复杂查询的字段设置为 ES 索引,consumer 消费 MQ 的时候将这些字段数据写一份到 ES 中,这样对于对查询条件简单,延迟敏感的查询,使用 Index 集群的数据;对条件复杂,延迟不敏感的查询使用 ES。这样解决了二级索引功能丰富性问题。

4. 生态构建

一个单独的存储产品解决所有问题的时代早已经过去,数据孤岛是没有办法很好服务业务的,如何与滴滴现有个各个数据系统打通数据,成了我们必须面对的问题。下面分数据流出到其他系统和从其他系统导入两个方面来阐述 Fusion-NewSQL 的数据流动方案。

4.1. Fusion-NewSQL 到其他存储系统

Fusion-NewSQL 是一个新系统,没办法短时间让各个数据系统为我们做适配。既然 Fusion-NewSQL 已经有了 Schema 信息,那么通过兼容 MySQL 的 Binlog 格式,将 Fusion-NewSQL 在数据链路中伪装成 MySQL,就可以直接使用 Mysql 的下游数据流动链路。这样的方式用最小的工作量最大程度做到了兼容。

4.2.Hive 到 Fusion-NewSQL

Fusion-NewSQL 还支持将离线的 Hive 表中的数据通过 Fusion-NewSQL 提供的 FastLoad(DTS)工具,将 Hive 表数据转入到 Fusion-NewSQL,满足离线数据到在线的数据流动。

如果用户自己完成数据流转,一般会扫描 Hive 表,然后构建 MySQL 的写入语句,一条条将数据写入到 Fusion-NewSQL,

流程如下面这样:
滴滴从 KV 存储到 NewSQL 实战
从上面的流程可以看出这种迁移方式有几个问题:

1. 每条 Hive 数据都要经过较长链路,数据导入耗时较长。

2. 离线平台的数据量大,吞吐高,数据导入直接大幅提升在线系统的 QPS,对在线系统的稳定性有较大影响。

从上面的痛点可以看出来,主要的问题是离线数据导入使用了在线系统复杂的 IO 链路。所以如何绕过在线的长 IO 链路,做批量导入就成了解决这个问题的关键。我们设计了 Fastload 数据导入平台,绕过在线 IO 路径

流程如下:
滴滴从 KV 存储到 NewSQL 实战
通过 Hadoop 并行计算,将需要导入的 Hive 数据直接构建成 Fusion-NewSQL 能识别的 sst 文件。Fusion-NewSQL 直接将 sst 文件从远端下载到本地,然后使用存储节点通过 Rocksdb 提供 ingest 功能,直接将 sst 文件加载到 Fusion-NewSQL 中,用户可以读到加载到 sst 文件中的数据。通过这样的预先构建 sst 文件,直接文件网络传输和存储引擎直接加载的步骤,就避免了数据导入走在线 IO 复杂流程,解决了稳定性问题,同时将数据导入耗时减少到原来的 1/10。

总结

通过解决上面的技术点,我们用了较小的代价,构建了一个基于 KV 存储的 NewSQL 系统,并且快速将 Fusion-NewSQL 系统接入到滴滴整体的数据链路中。虽然这不是一个完备的 NewSQL 系统,但已经可以满足大多数业务场景的需要,切实实现了 20% 工作量满足 80% 功能的需求。当前 Fusion-NewSQL 已经接入订单、预估、账单、用户中心、交易引擎等核心业务,总的数据如下图:

滴滴从 KV 存储到 NewSQL 实战

后续工作

  • 有限制的事物支持,比如让业务规划落在一个节点的数据可以支持单机跨行事务;
  • 实时索引替代异步索引,满足即写即读。目前已经有一个写穿 + 补偿机制的方案,在没有分布式事务的前提下满足正常状态的实时索引,异常情况下保证数据索引最终一致的方案;
  • 更多的 SQL 协议和功能支持。

 

KPI过时了?为什么科技公司更偏爱OKR?

KPI过时了?为什么科技公司更偏爱OKR?

阿里妹导读:除了KPI,考核员工还有什么方式?OKR是一种简单的管理方法,但是对于其误解和各种疑惑却很多。推崇者把OKR说得是无所不能,反对者认为不过是新瓶装旧酒,和KPI差不多。到底OKR和KPI,哪种方式更靠谱?技术leader该怎么选?今天,阿里资深技术专家燕标谈谈,他对OKR的思考。

引子

每过一段时间,就会出现一波新的管理概念方法和理念。最近OKR逐渐走到聚光灯下,引起越来越多人的注视。OKR简单后面隐藏着相对复杂的一面。简单的事物运行起来往往可以非常复杂,例如围棋。
 
关于OKR的书对于如何实施OKR有详细的说明和讨论。还包括成功的实例,劝人去使用体验OKR。但是看了这些书,总是有一点隔靴搔痒的感觉。例如,几乎所有的书上都反复强调不要把OKR和KPI混淆而和绩效挂钩,但都没有给出让我信服的解释。这种情况下依样画葫芦当然也可能做一个七八分象,但是终究不能让人坦然。我的个性让我去刨根问底,希望找出OKR设计者背后的一以贯之的逻辑。本文是自认为可以自圆其说的解释。不能说是终极的答案,只是希望抛砖引玉,写出来一起讨论。
 
什么是OKR?
 
对于OKR,百度百科有如下介绍:
 

OKR(Objectives and Key Results)即目标与关键成果法,是一套明确和跟踪目标及其完成情况的管理工具和方法。OKR的主要目标是明确公司和团队的“目标”以及明确每个目标达成的可衡量的“关键结果”。OKR可以在整个组织中共享,这样团队就可以在整个组织中明确目标,帮助协调和集中精力。

百度百科

 

简单说,OKR是一种管理工具,一个思考框架,一种方法,让团队的协作更加具有成效。
 
OKR有两个基本的组成部分:
 
目标:设定一个定性的时间内目标(通常是一个季度)。目标描述应该说明:
 
  • 为什么目标很重要?

  • 它是如何同公司目标关联的,有哪些具体依赖?

  • 它所支撑或依赖的内部客户有哪些?

关键结果:是由量化指标形式呈现的,用来衡量在这段时间结束时是否达到了目标。作为关键结果,必须具体:
 
  • 有挑战性;

  • 只写关键项,而非全部罗列;

  • 说明结果,而非任务;

  • 用积极正向的语言表述。

目标为主,关键结果为从。在实施过程中,OKR可以根据情况调整或者重新定义。
 
OKR可以在不同的层级设施:公司层面、不同团队层面、个人层面。个人和团队都要支持其上级组织的目标。OKR在公司内部实现一定程度的透明,相互对齐,保证相互之间的目标的关联性。所有的OKR因此形成了一张非常复杂的网络。
 
数字化管理
 
目标是定性的,关键结果则要包含可测量的(measurable)指标。
 
目标和指标之间是密切关联的,越接近指标,应该也离目标越近。但是两者之间并不是强因果关系,而只能说有关联性。各项指标都达标,并不意味着达到了预期的目标。或者达到了预期目标,但是有些指标没有达标。正如我们觉得身体不舒服,但是各项体检指标都达标。或者,我们觉得身体很正常,但是指标可能有些不正常。下面举一些目标和指标对应的例子,体会其间微妙的区别:
 
  • 以滴滴和快的为例。如果关注目标,快的的目标应该是超越滴滴;如果关注指标,快的的指标应该是司机数量、订单数、乘客数等;
  • 以足球运动员为例。如果关注目标,我们会想到夺冠、四强、保级;如果关注指标,那我们就会想到进球数、助攻数、跑动距离、比赛场次等;
  • 以程序员为例。如果我们关注目标,我们会想接下来我应该做什么事情,是要解决产品的卡顿问题,还是可以引入大数据来做精准推荐;而如果关注指标,因为我们的工作是编程,那我们就会想哪些指标可以衡量编程工作呢?我们想到的是代码行数、bug 数、单元测试覆盖率这些; 
数字化代表了先进、精确、可控、智能等。数字给控制和决策提供了非常好的抓手,加强了管理的效率。但是如果深入数字化,立刻就体会到数字化的困境:
 
  • 数据太多,如何进行分析和聚合作为关键指标,需要一个更高级的指导原则。
  • 数据具有的片面性和误导性。如果坚持优化某一指标,往往会危及整体利益。正如有练习健美的人为了追求肌肉量和形态美,最后往往走极端,而危及生命。所以数字化管理也存在一个过犹不及的问题。数字可以用于决策和控制的手段,但是如果作为终极追求目标则需要谨慎。
指标的优点在于精确,但是不能全面反应意图。目标反应了真实的意图,但是无法精确表达,只能定性说明。模糊性是它的特点,也是它的优点。这个类似于测不准原理。OKR就是考虑到这种矛盾性,有机结合一阴一阳两个方面,以期达到一个平衡。
 
OKR框架
 
前面说过OKR的目标通常是一个季度的。所以OKR是专注短周期的执行的,通常认为OKR是一个战术性执行框架,而不是战略执行的手段。它通过聚焦目标,不断审查关键指标,来提高执行力。不过这里有一个问题,就是如何保证OKR的目标和总体战略不脱节。为此OKR的实施还需要一个OKR框架,让OKR放在公司的使命、愿景框架下去考虑。
 
下面就是OKR框架:
 

KPI过时了?为什么科技公司更偏爱OKR?

上面三层使命、愿景、战略是中长期的目标的管理,相对是规划阶段。这是管理艺术化的领域,没有规定的程序,也无法实施工具化的支持。关于这些方面的书数不胜数。这里就不再介绍了。使命、愿景和战略为OKR的执行设置了上下文,要清晰传递业务重点,所以其质量具有关键性的作用。如果没有明确的战略就制订OKR,则只是一种肤浅的形式上的模仿。
 
下面三层目标、关键结果、任务是中短期管理,是执行阶段,是管理科学化的领域。团队的执行力是公司的核心竞争力。这个层次的关键,一是要做正确的事,一是要正确的做事。大规模团队协作是非常具有挑战的事情。协作就必须要有共同的规则,有流程和工具的支持,管理方法的创新往往集中在下面三层。
 
OKR所对应的是目标和关键结果两个层次。在同一个层次的还有比较熟悉的KPI。
在任务层的管理则是类似精益开发、Scrum等管理方法所关注的领域。这一层次关注的任务更具体。
 
在这个框架中,对于下层的工具支持比较完善。随着时间发展,管理工具自然会向上层延伸。OKR管理现在已经成为协作平台的下一个竞争点。
 
OKR分析
 
在所有的OKR介绍中,都反复强调:OKR不是考核工具,最好不要和绩效挂钩。这是最让人疑惑的地方,主要是因为OKR和KPI都包含可衡量的指标。设定了指标而又不用于考核,那是为什么呢?
 
要讨论OKR,就绕不开和KPI的对比。也只有把两者对比起来讨论,才能加深对OKR的认识。我们先有必要简单介绍一个KPI。
 
KPI简介
 
KPI系统是一个纵向的指标体系:先确定公司层面关注的KPI,再确定部门乃至个人要承担的KPI,由于KPI体系是经过层层分解,这样,就在指标体系上把战略落到“人”了。而要把战略具体落实,需要“显性化”,要对每个层面的KPI进行赋值,形成一个相对应的纵向的目标体系。所以,在落实战略时有“两条线”:一条是指标体系,是工具;另一条是目标体系,利用指标工具得到。
 
KPI制订需要遵循的SMART原则:
 
  • S代表具体(Specific),指绩效考核要切中特定的工作指标,不能笼统;
  • M代表可度量(Measurable),指绩效指标是数量化或者行为化的,验证这些绩效指标的数据或者信息是可以获得的;
  • A代表可实现(Attainable),指绩效指标在付出努力的情况下可以实现,避免设立过高或过低的目标;
  • R代表有关联性(Relevant),指绩效指标是与上级目标具明确的关联性,最终与公司目标相结合;
  • T代表有时限(Time-bound),注重完成绩效指标的特定期限。
总体来说,KPI是对重点经营活动的衡量,而不是对操作过程的反映。它要求精确,注重目标,而不对过程有太多关注。
 
KPI由上级与员工共同参与完成,双方达成一致意见后,作为最后员工考核的要素和依据。从表面看,KPI的优点明显:目标明确,员工和公司目标一致,有利于公司的战略实现。在一定程度上可以激励员工。但是在实施过程中,KPI的弊病也是明显的:
 
  • 因为KPI直接影响到最后的考核结果,所以员工一般都偏于保守,争取对于自己有利的指标,这样会从根本上抑制团队的创造力的积极性,让团队追求稳定和平庸。
  • 如果机械的按照KPI考核,个人和团队都可以为了某一个时段的指标达标,而损害长期的目标,从而妨碍战略的优化执行。局部的优化和全局优化间的矛盾在这种意义上是无法避免的。
  • KPI重结果,轻过程,做得极端的企业基本上是只看结果的。从而KPI对于赋能团队和个人是有限的。
让过程精彩,为结果买单
 
阿里有句土话:为过程喝彩,为结果买单。这作为一个公司的考核原则是可以的。但是从团队管理的角度讲,则不能仅仅是站在旁边为团队的同学喝彩,更重要的是要保证团队的过程精彩。OKR针对上面KPI的一些缺点,不和考核挂钩,就是为了让过程精彩。这便是OKR和KPI本质定位的不同。
 
如果我们把OKR和Scrum来对比,可能可以更加容易理解为何OKR不要和绩效挂钩。Scrum在实施过程中,也会要定义一些关键指标来分析团队实施的效率。但是我们清楚,一个团队Scrum实施得流畅,并不能保证最终产品就一定好,一定会给最终客户带来价值。
 
从这种意义上讲,OKR实际上和Scrum更类似,而不是和KPI更类似。只是OKR管理的是季度目标,而Scrum管理的是月度目标。两者实际可以相互补充。
 
归纳起来,OKR的KPI之间有如下区别:KPI主要是一个考核工具,OKR是一个对团队和个人的赋能工具。OKR的关注点是结果和过程并重的,特别是探索性的工作可能会更偏重于过程。
 
70分万岁
 
OKR的另一个核心理念是70分万岁,就是鼓励团队定一个足够高的目标,团队在非常努力之后也只能达到70%。不过由于创新等不确定性,团队不会因为只拿了30分而被惩罚,这个只是表明指标太高了,或者目标不正确,需要调整。同时OKR也不鼓励设置能拿到100分的指标,因为那只是表明指标设置得缺乏挑战性。70分是一个满意的分数,较好平衡了挑战和现实。
 
取法于上,仅得为中,取法于中,故为其下。设置70分的目标,就要求团队能够打破常规思维,要求行动有一定的创新,有一定的“杠杆率”,要求“行必果”,就是所用的行动都一定要有结果的。所以OKR的实施重点在于激励创新,发现业务的杠杆点,最大可能撬动业务发展。
 
70分原则是为了让团队放下一时的得失之心,更好发挥团队的潜力。这个原则集中实际上体现了OKR的理念:激发每个人的自我驱动力。
 
对比OKR的冒险精神,Scrum比较保守,要求百分百完成目标。这也是因为两者的目的不一样。基本来说,越是低层的管理工作,越需要可预测性,需要考虑各种条件限制。越往上,则越需要跳出现实的限制,通过战略来拉动执行力。
 
管理之道
 
管理在汉语中我们现在都当做一个词语,但是实际上包括两个方面:管和理。
 
  • 管原意为细长而中空之物,其四周被堵塞,中央可通达。使之闭塞为堵;使之通行为疏。管,就表示有堵有疏、疏堵结合。所以,管既包含疏通、引导之意,又包含限制、约束之意。总之是通过制度规章等约束条件引导事物向期望的方向发展。
  • 理者,治玉也,就是把一块璞玉粗糙的表层清理掉,露出下面美玉细腻的花纹来。引申的意义,理就是要发现、开发人物中善和美的一面。
 
管是止恶,理是扬善。管理,一阴一阳结合,才是管理的比较全面的意义。如果说KPI偏向管。那么OKR更倾向于理。两者是可以有机结合的。
 
任何一种新的理论和方法的提出,都具有它的背景。工业时代主要靠提高机器的效率来提高劳动生产率,人和机器是同等对待的。现代企业,人才是最重要的资源。员工提高执行力和创造力是企业的核心竞争力。效能的关键的是要提高组织的活力和创造力。一个具有自驱力的员工和一个被动的员工间的效率可以有一个数量级的差别。但是这种组织的能力不是天生的,而是需要培养和建设的。OKR就是组织能力建设工具,通过一个OKR团队来帮助其他个人和团队成长,这也是OKR在各大高科技公司广受欢迎的根本原因。
 
总体来说,实施OKR是希望得到如下收益:
 
  1. 聚焦在最重要的事情上。
  2. 提升敏捷性和快速应对的能力。
  3. 通过公开透明促进跨部门的一致性。
  4. 促进前瞻性思考,鼓励创新。
OKR的实施
 
实施OKR,需要转换心态,把OKR不是当做考核工具,而是来帮助团队更好成长的助手。人都是怕繁琐的,对于新的管理流程都会不自觉有抗拒的心理。让每个人对于OKR的心态变化,认识到其是帮助个人成长的工具,对于其成功落地是非常关键的。当然这对实施过程中的推动的团队要求非常之高。OKR和KPI在具体流程上类似,而其根本的不同在于这一点用心处。这一点不同在实施过程中容易被忽略掉,但却至关重要。
 
OKR只是一个工具,实施其过程是容易的,真正的难点在于:制订高质量的目标和准确衡量目标效果的关键成果指标,以及持之以恒的执行。这需要结合业务进行深入的分析和思考。
 
OKR和KPI解决不同的问题,所以两者可以并存。另外,OKR的实施可以从局部实施起,例如从某个团队、项目,或者管理的中高层开始,在积累经验后确定如何推广。
 
[1]中总结的OKR十大关键注意事项:
 
制订OKR前
 
  1. 帮助大家理解为什么要实施OKR。
  2. 得到高管的赞助。
  3. 提供OKR培训。
  4. 确保存在一个清晰的战略。
制订OKR时
 
  1. 目标应定性而非定量。
  2. 避免所有OKR都是自上而下制定的。
  3. 解决KR上出现的一系列问题,例如条数过多、质量差等。
  4. 使用一致的评分系统。
制定OKR后
 
  1. 避免制定后就束之高阁。要有周例会和中期审核计划。
  2. 链接OKR确保同上层组织对其一致。
 
总结
 
OKR当然不是一种包治百病的银弹。但是其鼓励创新和冒险,支持自下到上的挑战,激发团队和个人主动性的精神,在当前的行业快速发展的条件下,还是很具有意义的。
 
《晏子春秋》说:橘生淮南则为橘,生于淮北则为枳,叶徒相似,其实味不同。所以然者何?水土异也。实施OKR,需要团队文化的支持,需要一个良好的文化氛围才可能发挥其威力,否则终将蜕化为类似KPI的考核手段。这需要中坚的团队,能够深刻理解OKR的设计理念,才不会在实施过程中走样。OKR学其形易,而学其神难。在实施过程中一定要因地制宜,变通实施,坚持之后才能取得预期的效果。
 
参考资料:
1.OKR:源于因特尔和谷歌的目标管理利器 机械工业出版社
2.https://baike.baidu.com/item/关键绩效指标法 
3.http://www.woshipm.com/zhichang/765124.html
4.https://worktile.com/blog/okr/1b53bcdb66cba7
5.https://www.zhihu.com/question/22478049/answer/23833548 
6.https://www.atiim.com/blog/how-okrs-complement-scrum/
7.https://baijiahao.baidu.com/s?id=1623530400696261877&wfr=spider&for=pc OKR与KPI的三个本质

淘宝千万级并发分布式架构的14次演进

一、概述

本文以淘宝作为例子,介绍从一百个并发到千万级并发情况下服务端的架构的演进过程,同时列举出每个演进阶段会遇到的相关技术,让大家对架构的演进有一个整体的认知,文章最后汇总了一些架构设计的原则。

二、基本概念

在介绍架构之前,为了避免部分读者对架构设计中的一些概念不了解,下面对几个最基础的概念进行介绍:

1)分布式

系统中的多个模块在不同服务器上部署,即可称为分布式系统,如Tomcat和数据库分别部署在不同的服务器上,或两个相同功能的Tomcat分别部署在不同服务器上。

2)高可用

系统中部分节点失效时,其他节点能够接替它继续提供服务,则可认为系统具有高可用性。

3)集群

一个特定领域的软件部署在多台服务器上并作为一个整体提供一类服务,这个整体称为集群。如Zookeeper中的Master和Slave分别部署在多台服务器上,共同组成一个整体提供集中配置服务。

在常见的集群中,客户端往往能够连接任意一个节点获得服务,并且当集群中一个节点掉线时,其他节点往往能够自动的接替它继续提供服务,这时候说明集群具有高可用性。

4)负载均衡

请求发送到系统时,通过某些方式把请求均匀分发到多个节点上,使系统中每个节点能够均匀的处理请求负载,则可认为系统是负载均衡的。

5)正向代理和反向代理

  • 系统内部要访问外部网络时,统一通过一个代理服务器把请求转发出去,在外部网络看来就是代理服务器发起的访问,此时代理服务器实现的是正向代理;

  • 当外部请求进入系统时,代理服务器把该请求转发到系统中的某台服务器上,对外部请求来说,与之交互的只有代理服务器,此时代理服务器实现的是反向代理。

简单来说,正向代理是代理服务器代替系统内部来访问外部网络的过程,反向代理是外部请求访问系统时通过代理服务器转发到内部服务器的过程。

三、架构演进

单机架构

淘宝千万级并发分布式架构的14次演进

以淘宝作为例子。在网站最初时,应用数量与用户数都较少,可以把Tomcat和数据库部署在同一台服务器上。浏览器往www.taobao.com发起请求时,首先经过DNS服务器(域名系统)把域名转换为实际IP地址10.102.4.1,浏览器转而访问该IP对应的Tomcat。

随着用户数的增长,Tomcat和数据库之间竞争资源,单机性能不足以支撑业务。

第一次演进:Tomcat与数据库分开部署

淘宝千万级并发分布式架构的14次演进

Tomcat和数据库分别独占服务器资源,显著提高两者各自性能。

随着用户数的增长,并发读写数据库成为瓶颈。

第二次演进:引入本地缓存和分布式缓存

淘宝千万级并发分布式架构的14次演进

在Tomcat同服务器上或同JVM中增加本地缓存,并在外部增加分布式缓存,缓存热门商品信息或热门商品的html页面等。通过缓存能把绝大多数请求在读写数据库前拦截掉,大大降低数据库压力。

其中涉及的技术包括:使用memcached作为本地缓存,使用Redis作为分布式缓存,还会涉及缓存一致性、缓存穿透/击穿、缓存雪崩、热点数据集中失效等问题。

缓存抗住了大部分的访问请求,随着用户数的增长,并发压力主要落在单机的Tomcat上,响应逐渐变慢。

第三次演进:引入反向代理实现负载均衡

淘宝千万级并发分布式架构的14次演进

在多台服务器上分别部署Tomcat,使用反向代理软件(Nginx)把请求均匀分发到每个Tomcat中。

此处假设Tomcat最多支持100个并发,Nginx最多支持50000个并发,那么理论上Nginx把请求分发到500个Tomcat上,就能抗住50000个并发。

其中涉及的技术包括:Nginx、HAProxy,两者都是工作在网络第七层的反向代理软件,主要支持http协议,还会涉及session共享、文件上传下载的问题。

反向代理使应用服务器可支持的并发量大大增加,但并发量的增长也意味着更多请求穿透到数据库,单机的数据库最终成为瓶颈。

第四次演进:数据库读写分离

淘宝千万级并发分布式架构的14次演进

把数据库划分为读库和写库,读库可以有多个,通过同步机制把写库的数据同步到读库,对于需要查询最新写入数据场景,可通过在缓存中多写一份,通过缓存获得最新数据。

其中涉及的技术包括:Mycat,它是数据库中间件,可通过它来组织数据库的分离读写和分库分表,客户端通过它来访问下层数据库,还会涉及数据同步,数据一致性的问题。

业务逐渐变多,不同业务之间的访问量差距较大,不同业务直接竞争数据库,相互影响性能。

第五次演进:数据库按业务分库

淘宝千万级并发分布式架构的14次演进

把不同业务的数据保存到不同的数据库中,使业务之间的资源竞争降低,对于访问量大的业务,可以部署更多的服务器来支撑。

这样同时导致跨业务的表无法直接做关联分析,需要通过其他途径来解决,但这不是本文讨论的重点,有兴趣的可以自行搜索解决方案。

随着用户数的增长,单机的写库会逐渐会达到性能瓶颈。

第六次演进:把大表拆分为小表

淘宝千万级并发分布式架构的14次演进

比如针对评论数据,可按照商品ID进行hash,路由到对应的表中存储;针对支付记录,可按照小时创建表,每个小时表继续拆分为小表,使用用户ID或记录编号来路由数据。

只要实时操作的表数据量足够小,请求能够足够均匀的分发到多台服务器上的小表,那数据库就能通过水平扩展的方式来提高性能。其中前面提到的Mycat也支持在大表拆分为小表情况下的访问控制。

这种做法显著的增加了数据库运维的难度,对DBA的要求较高。数据库设计到这种结构时,已经可以称为分布式数据库,但是这只是一个逻辑的数据库整体,数据库里不同的组成部分是由不同的组件单独来实现的。

如分库分表的管理和请求分发,由Mycat实现,SQL的解析由单机的数据库实现,读写分离可能由网关和消息队列来实现,查询结果的汇总可能由数据库接口层来实现等等,这种架构其实是MPP(大规模并行处理)架构的一类实现。

目前开源和商用都已经有不少MPP数据库,开源中比较流行的有Greenplum、TiDB、Postgresql XC、HAWQ等,商用的如南大通用的GBase、睿帆科技的雪球DB、华为的LibrA等等。

不同的MPP数据库的侧重点也不一样,如TiDB更侧重于分布式OLTP场景,Greenplum更侧重于分布式OLAP场景。

这些MPP数据库基本都提供了类似Postgresql、Oracle、MySQL那样的SQL标准支持能力,能把一个查询解析为分布式的执行计划分发到每台机器上并行执行,最终由数据库本身汇总数据进行返回。

也提供了诸如权限管理、分库分表、事务、数据副本等能力,并且大多能够支持100个节点以上的集群,大大降低了数据库运维的成本,并且使数据库也能够实现水平扩展。

数据库和Tomcat都能够水平扩展,可支撑的并发大幅提高,随着用户数的增长,最终单机的Nginx会成为瓶颈。

第七次演进:使用LVS或F5来使多个Nginx负载均衡

淘宝千万级并发分布式架构的14次演进

由于瓶颈在Nginx,因此无法通过两层的Nginx来实现多个Nginx的负载均衡。

图中的LVS和F5是工作在网络第四层的负载均衡解决方案,其中LVS是软件,运行在操作系统内核态,可对TCP请求或更高层级的网络协议进行转发,因此支持的协议更丰富,并且性能也远高于Nginx,可假设单机的LVS可支持几十万个并发的请求转发;F5是一种负载均衡硬件,与LVS提供的能力类似,性能比LVS更高,但价格昂贵。

由于LVS是单机版的软件,若LVS所在服务器宕机则会导致整个后端系统都无法访问,因此需要有备用节点。可使用keepalived软件模拟出虚拟IP,然后把虚拟IP绑定到多台LVS服务器上,浏览器访问虚拟IP时,会被路由器重定向到真实的LVS服务器,当主LVS服务器宕机时,keepalived软件会自动更新路由器中的路由表,把虚拟IP重定向到另外一台正常的LVS服务器,从而达到LVS服务器高可用的效果。

此处需要注意的是,上图中从Nginx层到Tomcat层这样画并不代表全部Nginx都转发请求到全部的Tomcat。

在实际使用时,可能会是几个Nginx下面接一部分的Tomcat,这些Nginx之间通过keepalived实现高可用,其他的Nginx接另外的Tomcat,这样可接入的Tomcat数量就能成倍的增加。

由于LVS也是单机的,随着并发数增长到几十万时,LVS服务器最终会达到瓶颈,此时用户数达到千万甚至上亿级别,用户分布在不同的地区,与服务器机房距离不同,导致了访问的延迟会明显不同。

第八次演进:通过DNS轮询实现机房间的负载均衡

淘宝千万级并发分布式架构的14次演进

在DNS服务器中可配置一个域名对应多个IP地址,每个IP地址对应到不同的机房里的虚拟IP。

当用户访问www.taobao.com时,DNS服务器会使用轮询策略或其他策略,来选择某个IP供用户访问。此方式能实现机房间的负载均衡,至此,系统可做到机房级别的水平扩展,千万级到亿级的并发量都可通过增加机房来解决,系统入口处的请求并发量不再是问题。

随着数据的丰富程度和业务的发展,检索、分析等需求越来越丰富,单单依靠数据库无法解决如此丰富的需求。

第九次演进:引入NoSQL数据库和搜索引擎等技术

淘宝千万级并发分布式架构的14次演进

当数据库中的数据多到一定规模时,数据库就不适用于复杂的查询了,往往只能满足普通查询的场景。

对于统计报表场景,在数据量大时不一定能跑出结果,而且在跑复杂查询时会导致其他查询变慢,对于全文检索、可变数据结构等场景,数据库天生不适用。

因此需要针对特定的场景,引入合适的解决方案。如对于海量文件存储,可通过分布式文件系统HDFS解决,对于key value类型的数据,可通过HBase和Redis等方案解决,对于全文检索场景,可通过搜索引擎如ElasticSearch解决,对于多维分析场景,可通过Kylin或Druid等方案解决。

当然,引入更多组件同时会提高系统的复杂度,不同的组件保存的数据需要同步,需要考虑一致性的问题,需要有更多的运维手段来管理这些组件等。

引入更多组件解决了丰富的需求,业务维度能够极大扩充,随之而来的是一个应用中包含了太多的业务代码,业务的升级迭代变得困难。

第十次演进:大应用拆分为小应用

淘宝千万级并发分布式架构的14次演进

按照业务板块来划分应用代码,使单个应用的职责更清晰,相互之间可以做到独立升级迭代。这时候应用之间可能会涉及到一些公共配置,可以通过分布式配置中心Zookeeper来解决。

不同应用之间存在共用的模块,由应用单独管理会导致相同代码存在多份,导致公共功能升级时全部应用代码都要跟着升级。

第十一次演进:复用的功能抽离成微服务

淘宝千万级并发分布式架构的14次演进

如用户管理、订单、支付、鉴权等功能在多个应用中都存在,那么可以把这些功能的代码单独抽取出来形成一个单独的服务来管理,这样的服务就是所谓的微服务。

应用和服务之间通过HTTP、TCP或RPC请求等多种方式来访问公共服务,每个单独的服务都可以由单独的团队来管理。此外,可以通过Dubbo、SpringCloud等框架实现服务治理、限流、熔断、降级等功能,提高服务的稳定性和可用性。

不同服务的接口访问方式不同,应用代码需要适配多种访问方式才能使用服务,此外,应用访问服务,服务之间也可能相互访问,调用链将会变得非常复杂,逻辑变得混乱。

第十二次演进:引入企业服务总线ESB屏蔽服务接口的访问差异

淘宝千万级并发分布式架构的14次演进

通过ESB统一进行访问协议转换,应用统一通过ESB来访问后端服务,服务与服务之间也通过ESB来相互调用,以此降低系统的耦合程度。这种单个应用拆分为多个应用,公共服务单独抽取出来来管理,并使用企业消息总线来解除服务之间耦合问题的架构,就是所谓的SOA(面向服务)架构,这种架构与微服务架构容易混淆,因为表现形式十分相似。

个人理解,微服务架构更多是指把系统里的公共服务抽取出来单独运维管理的思想,而SOA架构则是指一种拆分服务并使服务接口访问变得统一的架构思想,SOA架构中包含了微服务的思想。

业务不断发展,应用和服务都会不断变多,应用和服务的部署变得复杂,同一台服务器上部署多个服务还要解决运行环境冲突的问题,此外,对于如大促这类需要动态扩缩容的场景,需要水平扩展服务的性能,就需要在新增的服务上准备运行环境,部署服务等,运维将变得十分困难。

第十三次演进:引入容器化技术实现运行环境隔离与动态服务管理

淘宝千万级并发分布式架构的14次演进

目前最流行的容器化技术是Docker,最流行的容器管理服务是Kubernetes(K8S),应用/服务可以打包为Docker镜像,通过K8S来动态分发和部署镜像。

Docker镜像可理解为一个能运行你的应用/服务的最小的操作系统,里面放着应用/服务的运行代码,运行环境根据实际的需要设置好。把整个“操作系统”打包为一个镜像后,就可以分发到需要部署相关服务的机器上,直接启动Docker镜像就可以把服务起起来,使服务的部署和运维变得简单。

在大促的之前,可以在现有的机器集群上划分出服务器来启动Docker镜像,增强服务的性能,大促过后就可以关闭镜像,对机器上的其他服务不造成影响(在3.14节之前,服务运行在新增机器上需要修改系统配置来适配服务,这会导致机器上其他服务需要的运行环境被破坏)。

使用容器化技术后服务动态扩缩容问题得以解决,但是机器还是需要公司自身来管理,在非大促的时候,还是需要闲置着大量的机器资源来应对大促,机器自身成本和运维成本都极高,资源利用率低。

第十四次演进:以云平台承载系统

淘宝千万级并发分布式架构的14次演进

系统可部署到公有云上,利用公有云的海量机器资源,解决动态硬件资源的问题,在大促的时间段里,在云平台中临时申请更多的资源,结合Docker和K8S来快速部署服务,在大促结束后释放资源,真正做到按需付费,资源利用率大大提高,同时大大降低了运维成本。

所谓的云平台,就是把海量机器资源,通过统一的资源管理,抽象为一个资源整体。在之上可按需动态申请硬件资源(如CPU、内存、网络等),并且之上提供通用的操作系统,提供常用的技术组件(如Hadoop技术栈,MPP数据库等)供用户使用,甚至提供开发好的应用。用户不需要关系应用内部使用了什么技术,就能够解决需求(如音视频转码服务、邮件服务、个人博客等)。在云平台中会涉及如下几个概念:

  • IaaS:基础设施即服务。对应于上面所说的机器资源统一为资源整体,可动态申请硬件资源的层面;

  • PaaS:平台即服务。对应于上面所说的提供常用的技术组件方便系统的开发和维护;

  • SaaS:软件即服务。对应于上面所说的提供开发好的应用或服务,按功能或性能要求付费。

至此,以上所提到的从高并发访问问题,到服务的架构和系统实施的层面都有了各自的解决方案,但同时也应该意识到,在上面的介绍中,其实是有意忽略了诸如跨机房数据同步、分布式事务实现等等的实际问题,这些问题以后有机会再拿出来单独讨论。

四、 架构设计总结

架构的调整是否必须按照上述演变路径进行?

不是的,以上所说的架构演变顺序只是针对某个侧面进行单独的改进,在实际场景中,可能同一时间会有几个问题需要解决,或者可能先达到瓶颈的是另外的方面,这时候就应该按照实际问题实际解决。

如在政府类的并发量可能不大,但业务可能很丰富的场景,高并发就不是重点解决的问题,此时优先需要的可能会是丰富需求的解决方案。

对于将要实施的系统,架构应该设计到什么程度?

对于单次实施并且性能指标明确的系统,架构设计到能够支持系统的性能指标要求就足够了,但要留有扩展架构的接口以便不备之需。对于不断发展的系统,如电商平台,应设计到能满足下一阶段用户量和性能指标要求的程度,并根据业务的增长不断的迭代升级架构,以支持更高的并发和更丰富的业务。

服务端架构和大数据架构有什么区别?

所谓的“大数据”其实是海量数据采集清洗转换、数据存储、数据分析、数据服务等场景解决方案的一个统称。

在每一个场景都包含了多种可选的技术,如数据采集有Flume、Sqoop、Kettle等,数据存储有分布式文件系统HDFS、FastDFS,NoSQL数据库HBase、MongoDB等,数据分析有Spark技术栈、机器学习算法等。

总的来说大数据架构就是根据业务的需求,整合各种大数据组件组合而成的架构,一般会提供分布式存储、分布式计算、多维分析、数据仓库、机器学习算法等能力。而服务端架构更多指的是应用组织层面的架构,底层能力往往是由大数据架构来提供。

有没有一些架构设计的原则?

1)N+1设计

系统中的每个组件都应做到没有单点故障。

2)回滚设计

确保系统可以向前兼容,在系统升级时应能有办法回滚版本。

3)禁用设计

应该提供控制具体功能是否可用的配置,在系统出现故障时能够快速下线功能。

4)监控设计

在设计阶段就要考虑监控的手段。

5)多活数据中心设计

若系统需要极高的高可用,应考虑在多地实施数据中心进行多活,至少在一个机房断电的情况下系统依然可用

6)采用成熟的技术

刚开发的或开源的技术往往存在很多隐藏的bug,出了问题没有商业支持可能会是一个灾难。

7)资源隔离设计

应避免单一业务占用全部资源。

8)架构应能水平扩展

系统只有做到能水平扩展,才能有效避免瓶颈问题

9)非核心则购买

非核心功能若需要占用大量的研发资源才能解决,则考虑购买成熟的产品。

10)使用商用硬件

商用硬件能有效降低硬件故障的机率。

11)快速迭代

系统应该快速开发小功能模块,尽快上线进行验证,早日发现问题大大降低系统交付的风险。

12)无状态设计

服务接口应该做成无状态的,当前接口的访问不依赖于接口上次访问的状态。

来源:https://segmentfault.com/a/1190000018626163

 IT大咖说  |  关于版权 

由“IT大咖说(ID:itdakashuo)”原创的文章,转载时请注明作者、出处及微信公众号。投稿、约稿、转载请加微信:ITDKS10(备注:投稿),茉莉小姐姐会及时与您联系!

感谢您对IT大咖说的热心支持!