• Feeds

  • 技术方案评审

    新年开始,大部分公司都在启动大量新功能的规划及设计、技术人员同时在设计对应实现方案、架构师或者技术主管则需要一天内穿梭在多个技术讨论中,评审并达成成熟稳定的设计方案。从架构师的角度来考虑,如何衡量一个技术方案的优劣呢?

    一、评审点

    从总体上讲,技术方案是衡量一个团队的开发成熟度重要一方面。技术设计是否围绕核心需求key features?模块依赖关系、兼容性是否得到充分清晰的描述及共识;设计上不同的方案是否得到了充分考虑比较?是否有正反的激烈的碰撞还是行政上的领导说了算?另外代码实现是否正确执行设计,还是代码实现边走边看,与设计方案基本脱节?

    从细节上来看,在软件企业内经常有不同形式的方案review,架构师在做review时候需要要考察哪些环节?从互联网系统设计的角度,总结到以下几点。

    简洁及可维护性
    从工程角度来看,避免难懂的方案。技术方案尽量象PPT那样,越傻瓜的方案越有生命力。当然简洁的同时也要满足后续条件。

    性能、健壮性及可扩展性
    互联网项目唯快不破,性能是立根之本。我们需要为健壮及性能留有一定扩展余地。

    避免过度设计
    Donald Knuth说过“过早优化是万恶之源(premature optimization is the root of all evil)”,不少架构师也牢记于心。但是在实际操作上,这一点和上一点所说扩展性直接冲突,比如
    保守派:质疑在一些环节增加可扩展性,需要多花很多精力(比如30%),但增加的扩展能力未必能用上。
    激进派:质疑如果不增加一定扩展能力,当需求稍微发生变化,方案需要全盘推翻。
    可扩展性及过度设计的矛盾是否如薛定谔的猫那样,需要打开盒子那一刻才知道结果?还是架构师可以根据经验及环境去取舍,从我的观点来看,“make appropriate design tradeoff”是衡量架构师能力的首要指标。

    Case Study
    拿年前比较热门的12306系统来举例,如需做一个方案实现其中的余票查询模块,假设设计如下

    12306查询模块设计方案

    需求
    1、能够承载峰值查询为10万次/秒的请求
    2、余票信息能容忍一定程度和实际系统不一致,但是滞后不能超过5秒
    附加需求:为了此虚拟项目更具有可比性及易于理解,设计方案必须全采用开源技术实现,不修改相关服务器源码,并采用普通廉价服务器部署。

    技术难点
    1、峰值处理能力,需要用最小的成本解决
    2、数据需要5秒内动态更新的问题,需要采用合适的方案

    技术选型
    采用nginx, MySQL, varnish, memcached来实现
    假设nginx+远程cache处理能力是2万次/秒;varnish在大部分本地cache命中情况下处理能力是3万次/秒;

    方案一
    采用cache直接查询的方式

    方案二
    采用七层反向代理增加cache的方式

    数据更新的方案设计
    需要将订票系统中的实时变化反映到查询系统中
    方案一:PULL

    方案二:PUSH

    使用上面的方案评审方法来看,方案有什么问题呢?

    二、方案文档

    另外再说下技术方案的文档要求。一个团队如果没有形成技术方案的规范,交付的方案通常是五花八门的,有word、visio、邮件,mm图、ppt、PDF、纯文本…… 怎样才算一份好的设计文档?

    核心需求及技术难点
    很多技术方案第一段就直奔主题,比如展示模块图或者存储结构,这会让阅读者一头雾水,先告诉阅读对象“我们究竟要解决什么技术问题”。


    一张A4纸上密密麻麻写满同一字号文字的方案令人生畏,“一图胜千言”,用txt、一封邮件、或者纯文字的word通常情况下较难得到理解

    文字、关键字
    方便本地或者文档服务器全文检索,文档支持版本管理。
    一个团队运作一年以上之后,文档数可能成百上千,需要通过关键字来快速查询,需要支持版本管理的文档服务器及仓库。而仅靠设计方发一封邮件来提供给大家技术方案很难形成技术积累。

    便于修改
    技术方案及设计文档需要方便团队每一个成员更新,技术方案在代码实现时会有设计的改进及微调,这些需要能随时方便的更新到设计文档上,大部分团队存在设计文档与代码实现脱节的情况。而用一个图片或者pdf的来提供技术方案的更是让执行人员更新方案无处下手。

    三、扩展作业

    在文章结束之前,顺便再出一个今天随便想到的facebook中的like功能作为扩展训练题

    需求

    • 可以对一个对象(一条feed、文章、或者url)进行like操作
    • 需要看到一个对象的like总数
    • 可以看到一个对象的like用户列表,优先显示我的好友列表(social list)。
    • 数据量:每天新增的like对象数为1千万,每秒like计数器查询量及social user list均为30万次/秒。

    假设现有系统的存储结构(MySQL)为
    friends表, from_uid + to_uid 为联合主键
    (from_uid bigint,
    to_uid bigint,
    ctime timestamp)
    feed表, feed_id + like_uid 为联合主键
    (feed_id bigint,
    like_uid bigint,
    ctime timestamp);

    假设以上存储是单表结构,请问如何设计like技术方案?如何评判你的like方案的优劣?

    广告:新年开始,新浪微博技术团队也正在招兵买马,对以上内容感兴趣的技术人才欢迎投递简历,层次不限,从架构师到有一定基础的Java及PHP工程师都可,联系方式见blog右方。

    如想及时阅读Tim Yang的文章,可通过页面右上方扫码订阅最新更新。

    « | »

    14 Comments  »

    1. 杨老师,看到了你,我发现我才看到了人生的规划,才有了目标!
      大型分布式应用一直是我所向往和追求的!至少我对其相当感兴趣!看到了您今天的招聘信息,甚是遗憾,因为北京离我家太远了 Y_Y

    2. 呜呜

      C++招不。

    3. 哎呀

      浙江开个分店吧,杨老师

    4. coolzyt

      扩展作业:
      其他需求应该不是很难实现,就是一个缓存队列更新+计数的问题,使用多台web服务器+redis集群可以实现
      可以看到一个对象的like用户列表,优先显示我的好友列表(social list)。这个稍微麻烦一点,个人觉得可以通过uid+feedid组成key来缓存一个关系,这样查询时可以快速遍历我的好友有没有like这个feed。

    5. 楼拴柱

      GOOD!

    6. beiqirun

      简历投了,
      作业:
      Redis集群–更新队列+计数,like对象的like用户列表使用sorted set(好友关系 score为1),like对象计数器使用hash,防止有别的扩展。
      定时清理过大的like用户列表,最多保持1000。

    7. silentime

      “互联网项目唯快不破,性能是立根之本。”

      这个快说的是项目完成的速度,不是用户访问的速度,跟性能没有关系吧……
      真别扭……

    8. Mike

      请教杨师傅:方案文档这部分,一般采用什么载体(软件)?或者说您可否建议一下,用什么软件好呢?我一直纠结于这个,邮件方式让我一直觉得无法积累,后期更难于打理。觉得非常不方便啊。

    9. 好想去新浪做微博啊,等忙完了,投个简历试试

    10. xum

      对于12306查询模块这类系统,有点太过纠结于性能了,我用它订过票,那种传统的交互设计,让我为了一张票,就不停地查呀查呀查呀,鬼知道什么时候放票或有退票可买,估计所有人都跟我一样,凭空增添了系统的压力。其实,根据我的需求或者第一次查询操作,完全可以形成一个明确的查询条件,系统记下来,排队循环查呗,一发现车票多了,就立刻通知我,这多好啊,即控制了峰值,又节省了带宽,还省了我的事。真不明白,非得搞成这么一个全民抢票系统,然后让我们搞技术的都去勇攀高峰。。。。。。等冲上去以后,却发现。。。峰中还有更高峰。。。。。。

    11. 鱼翅

      varnish,没有使用过。个人感觉增加varnish之后:
      缺点是:前端请求距离原始DB数据的距离为2,系统复杂度提高,增加了运营维护成本,分析、解决问题可能有些繁琐;

      优点是:1)有效的减轻Ngnix和Memcache的请求负担;
      2)有效避免Memcache集群出现问题时,请求击穿数据库,引发系统崩溃;

      数据更新方案:
      poll方案,存在请求击穿数据库DB的请求;
      pull方案,增加了系统实现和维护复杂度,但可以保证系统的可靠性。

      欢迎批评、指导。

    Leave a Comment