• Feeds

  • 团队的技术形象

    当一个app不好用时候,用户会说团队的产品不行;当系统可用性有问题时(比如访问慢或频繁宕机),用户会说这个团队技术不行。

    发生频繁宕机并不常见,宕机通常会由程序bug或者访问压力过大引起。bug最终会被修复;在不过分在意成本的情况下,访问压力最终可以用硬件来扛住。另外系统升级及功能变更也会带来可用性与稳定性的问题,但大多数系统会最终相对稳定下来,大的变更会越来越少,系统也会趋于稳定。

    技术成本的控制通常不是一个很紧迫的问题,一方面公司的业务模式也不是靠省服务器做出来的,其次技术团队可以通过投入时间去优化改善来降低成本(但大部分团队更愿意将研发资源投入到新功能开发上去)。因而通常只要达到基本可用,则成本合理性问题不会得到充分关注。另外成本也很难直接对比,一个公司比另外一个公司服务器少些,但是各自功能场景有差异,没有直接可比性。因此较难从技术成本合理性角度衡量某个团队技术好不好。讽刺的大部分现实是,只要系统基本可用,则会被视为一支有战斗力的团队;如果能达到一定体量(虽然不是技术团队直接带来的),那则会被视为超强的技术团队。

    软件质量在大部分公司走不出测试或者“质量保证”部门,很少有团队会认为步子不够快是由于软件质量问题造成。开发效率同样没有直接可比性,“努力”有时候会掩盖一切,朋友圈时常会看到这样的总结,“虽然走了一些弯路,但兄弟们加班加点将进度追了回来,感动……”。比软件质量问题更糟糕的是业务方向的不确定性,方向不确定带来的消耗比软件质量的问题更大,走错方向导致一两个月努力泡汤的事情也很常见,因此不是最短板的软件质量的重视通常就无从提起了。

    隔洋对岸则有一些技术主导的公司,Mark Zuckerberg曾说过,Facebook在早期时,非技术岗位如HR及市场也招聘有技术背景的人担任。这些公司尽量招聘最顶级的技术人才,这些人能够在公司中享受技术的乐趣。但这也只有平台级的公司才有可能。这些公司商业模式的门槛足够高,从而有持续的利润来支持这一愿景。而剩下绝大多数公司,需要首先去考虑生存的问题,这也很正常,头部的公司如果失去垄断地位,也马上没有机会去维持纯技术形象。

    技术行不行是一个很无力的目标,技术很强的团队未必能改变世界,不强的团队很多时候也生存得很好。业界很多业务模式短板并不在技术上,更混乱的是,出现技术问题有时反而被当做PR事件及段子去炒作。当然,在技术较差的团队,软件质量及技术创新无从谈起。处在风口的猪,也会遇到前文所说的重复踩进同一个坑的无力感。

    为什么超长列表数据的翻页技术实现复杂(二)

    上文为什么超长列表数据的翻页技术实现复杂提到了超长列表翻页技术设计上一些问题,今天讨论下部分解决思路。

    前新浪同事 @pi1ot 最近在程序员杂志发表的一篇文章《门户级UGC系统的技术进化路线》也是超长列表的一个经典案例,在正式展开思路之前,我们也不妨了解一下此文所说新浪评论系统的演进思路。

    从文中看到几个版本的列表翻页实现方案

    3.0版

    3.0系统的缓存模块设计的比较巧妙,以显示页面为单位缓存数据,因为评论页面是依照提交时间降序排列,每新增一条新评论,所有帖子都需要向下移动一位,所以缓存格式设计为每两页数据一个文件,前后相邻的两个文件有一页的数据重复,最新的缓存文件通常情况下不满两页数据。

    此方案由于每页的条数是定长的,因此主要采用缓存所有列表的方案。但为了数据更新的便利,缓存结构比较复杂。从今天多年之后的眼光来看,这种设计不利于理解、扩展及维护。因此目前大多不倾向使用这种方案。

    4.0版

    解决方案是在MySQL数据库和页面缓存模块之间,新建一个带索引的数据文件层,每条新闻的所有评论都单独保存在一个索引文件和一个数据文件中,期望通过把对数据库单一表文件的读写操作,分解为文件系统上互不干涉可并发执行的读写操作,来提高系统并发处理能力。在新的索引数据模块中,查询评论总数、追加评论、更新评论状态都是针对性优化过的高效率操作。从这时候起,MySQL数据库就降到了只提供归档备份和内部管理查询的角色,不再直接承载任何用户更新和查询请求了。

    使用自定义索引的方式,由于未与相关人员交流细节,推断应该是类似数组的结构。

    从上述案例看到,评论系统是一种典型的超长列表数据结构,如果再MySQL的基础上来做,需要设计额外的索引结构来实现高效的翻页功能

    由于超长列表的翻页实现成本高主要是由于列表索引的B-TREE结构方面原因,B-TREE结构能快速查找到某个key,但不是为叶子节点的Range访问而设计,因此主要解决思路也是围绕B-TREE的range访问而进行优化。

    首先、从原理来看,可以在B-TREE增加以下2个二级索引字段:

    • Count index 记录每个非叶子节点下的条目数,这样可以帮助快速定位到任意的offset;
    • Offset index 记录部分叶子节点的offset,比如每隔1000个id记录一个offset如下,并保存在另外一个列表中,当需要查找某个offset的时候,则可以利用附近已经记录offset的id来定位目的地位置。比如当翻页到1010时,如果offset index记录了[1000: id10345],则可以从id10345往后10个元素找到10010。
    [
    {"1000":10345},
    {"2000":13456},
    {"3000":22345},
    {"4000":56789},
    {"5000":66788}
    ]
    

    这2个字段可以同时使用,也可以只用其中一个。如图
    btree-index

    再看如何将上述方法应用到具体的实现中。由于本文主要讨论MySQL环境,MySQL要在B-TREE上额外保存一些信息需要修改MySQL源代码,修改门槛较高,因此更简单方法是将上述二级索引通过应用层保存在另外的表中。

    一种非严格意义的count index实现如下:

    CREATE TABLE IF NOT EXISTS `second_index` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `uid` int(11) NOT NULL,
      `yymm` int(11) NOT NULL,
      `index_count` int(11) NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
    
    
    INSERT INTO `second_index` (`id`, `uid`, `yymm`, `index_count`) VALUES
    (1, 1, 1409, 123),
    (2, 1, 1410, 2342),
    (3, 1, 1411, 534),
    (4, 1, 1412, 784),
    (5, 1, 1501, 845);
    

    一种offset index实现如下:
    在第一次用户翻页到某个offset位置时,在redis直接保存offset, id。当有其他请求来查找offset之后数据时,可以从offset的位置往后扫描。如果列表的数据发生了变化,需要及时将Redis保存的offset index删除。

    以上2种方法已经在生产环境使用。

    @icycrystal4对此文所提方法亦有贡献。

    我为什么用DigitalOcean来测试docker容器

    最近不少工程师都在尝试docker,通常会在本机创建虚拟机或者通过一些公共的测试服务器来进行,我为什么选择付费用DigitalOcean来测试docker容器?

    先说一个案例,一个月前某工程师说,“看了你写的kubernetes文章后,我也打算试下”。最近再碰到他时,他很惭愧的说,“试了好多次,还没跑通”。在国内确实存在访问国外云服务的问题,一方面速度慢,另外也存在不少资源莫名其妙就被墙了,类似的云服务更推荐大家使用国外的云主机来进行日常的学习及测试。因此给大家介绍Tim日常使用DigitalOcean(简称DO)的一些便利之处。

    1. 虽然大家所在公司也都有公共测试服务器,但是使用这些资源通常面临多人共同使用的冲突;独占的服务器通常需要领导审批,也存在随时被业务征用走的情况。而在自己工作电脑创建虚拟机则由于占用资源较大,影响本身工作环境效率。使用云主机创建帐号开通一个虚拟机只需要几秒钟,不会出现启动的服务被人停掉的困扰。
    2. DigitalOcean是经过Tim比较后一种性价比非常高的VPS,它的特点是全SSD存储,费用低,比同类型的云服务便宜不少。按小时计费,基本款每天开24小时只需要1.04元人民币。如果只开1小时,则只收费1小时,不到1毛钱。服务也比较稳定,Tim的博客从Linode迁移到DigitalOcean已经有半年以上,目前运行稳定。
    3. DigitalOcean支持CoreOS,CoreOS是一种天生为容器而设计的Linux发行版,由于CoreOS没有包管理工具,无法直接安装各种应用,所有的功能推荐用容器来实现,因此可以帮助大家在测试Docker环境时更好理解容器化理念、更好的分清宿主机与容器的边界、更好的理解分布式的容器及服务。DigitalOcean自带了较新版本的CoreOS,利用CoreOS自带的docker,创建虚拟机后1分钟内就可以完成下载镜像及启动容器的工作。
    4. DO的网速很快,可极大提升工作效率,在DigitalOcean美国机房访问github等资源基本上一回车就下载完了,从docker registry拉一个200M的unbutu镜像只要数秒。而国内访问大部分技术资源速度比较慢,比如CoreOS默认是在线安装方式,在国内装CoreOS要2小时以上;从Docker registry下载一个ubuntu image也需要20分钟左右。
    5. 建议使用以下推荐链接 https://www.digitalocean.com/?refcode=b5d7cd2d0410 来注册用户,当你使用及付费后,Tim可以获得一杯咖啡左右的推荐费的好处,你可以获得$10的费用,相当免费使用2个月。

    PS:给那些申请成功的同学:

    1、CoreOS默认的用户名不是你的 ssh-key 指定的用户或 root,而是 core,因此使用以下命令登录。
    ssh -i ssh-key-file core@ip
    2、Droplet在服务器不启动时可能也会收费,如果是测试用途,长时间不用前建议将Droplet删除,以免产生额外费用。

    3、DO美国机房从国内SSH访问会有丢包的情况,可以尝试MOSH来代替SSH,也可以选择新加坡机房。

    4、DO的文档也非常丰富,英文熟练的同学可以参看 tutorials

    123...Last