架构师之路--谈业务的合理架构

  奶奶从路边捡来一只小鸡。它总是喳喳的叫,但是周末我坐在那里的时候,它就会蹲在我脚上,很安详的样子。然后小鲜肉就过来说:麻麻,我好想吓唬它。小鸡被吓的到处乱串。我说了挺多话没法让小鲜肉停下来。我就叹了口气在那里看着。一个5岁的孩子本来就不具备换位思考的能力。还有一个问题,我其实根本不知道小鸡是怎样想的。只是觉得它趴在我脚上的时候很安心很安静。晚上下班我会把手伸到笼子里陪它待一会儿,因为我想它是很想自己的妈妈的。

  本文首发于静儿1986的博客,原文地址是http://www.cnblogs.com/xiexj/p/6874654.html

  先说说我们部门的业务。我们部门掌管乐视网所有的视频音频等最核心数据的信息。所有子业务都围绕着这个核心数据。最笼统的分可以分为两块:读和写。

  读数据除了直接依赖DB的内部操作之外,就是直接通过http请求的RPC调用。因为调用这个接口的业务方非常多,他们用的语言和技术非常杂,http有更好的通用性和便于运营人员等不懂技术的人排查问题,只能内网访问,也很安全。这是部门并发量最大的服务。单台机器QPS一般在2k多,低谷时在1k多,高峰时在3k多。线上11台接口服务器同时工作。但是读数据为了提高并发量,将全量的视频和专辑数据存在了memcached缓存里。所以一旦其他业务方更新了数据会直接发送MQ消息给读数据服务,读数据服务更新了缓存后要给业务方回复消息。

  读数据还有一种被叫做离线数据推送。这是由于像搜索部门这样的,需要所有视频相关的全量数据,不合适通过接口访问。之前用的是他们直接依赖我们的数据库镜像。但是这样我们这边要进行数据库改造,分库分表或者其他的表结构修改,就要通知各个依赖业务方。所以我们就改用定时全量数据推送给他们和MQ实时数据发消息的方式进行解耦。

  还有一个面向所有部门同事的服务,就是统一异常平台。部门的所有子业务的异常都会异步发送到统一的Redis中。可以在一个公共的平台统一查看。对于特定业务的,会给特定的同事发出告警邮件。

  写数据的业务方非常多,我们部门也有。其他部门也有。写数据就是创建,修改和删除。写数据QPS很低。

  创建时不仅要走我们这边,还要调用云存储,云转码等其他部门的接口。具体流程可参考之前的一篇文章:《一个请求过来都经过了什么》

  修改是走我们部门内部系统或者调用我们的API。

  删除只能走我们部门内部系统,删除接口目前不向其他业务部门开放。

  我自己目前主要做的就是读数据的部分。离线数据算是我开发的,其他人是拷贝的我的。目前正在进行RPC接口的改造。写我也做过。PGC项目是专业用户进行视频上传的,当年是我做的。这是一个平台。我做过数据接入。就是我们购买一些版权的公司将他们的视频的介质和媒体信息直接ftp放到我们服务器上,或者给我们一种调用方式我们自己去取,这种属于后台服务。我也维护过我们的视频后台系统。是我去美国做数据接入的时候,美国运营同事总是过来找我说我们系统的问题,由于时差,我只能自己动手改了。

  后台服务可以自己想怎么写怎么写。其他的,不管是读接口,PGC还是后台系统都是采用的SOA架构将业务垂直分解为前端(对于平台来说就是和界面打交道的,对于读接口来说就是业务方调用的),使用Dubbo来调用数据服务。基于这种设计,一个子业务的代码基本模块都分为API模块,WEB模块(读接口无此模块),common模块(一些公用工具或者公用POJO), client模块(dubbo服务的接口),service服务(dubbo服务的实现,即服务提供者)。

  简单介绍一下Dubbo:Dubbo是一种透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。实现了软负载均衡及容错机制,服务自动注册与发现,能够平滑添加或删除服务提供者。

  下面是今天的重点,吐槽一下我们目前读接口的架构不合理(当然不合理是很正常的,这是一个为期三年的古董),我们新方案已经设计好了。

  读接口业务简单,并发支持需求大。如果说采用Dubbo层是为了与业务分离,提高服务的复用率,提高数据的统一性。目前一个子业务就自己弄一套Dubbo。有API和WEB两个对前端业务的也将就起到作用了。读接口就是一个api调服务,有啥复用的啊。Dubbo的读接口采用默认的阻塞模式,高并发的情况下Dubbo就会成为性能瓶颈。

  业务方可以进行数据的更新,他们更新DB后还要维护我们的缓存。我们的缓存采用的乐视统一的CouchBase集群。CouchBase是Memcached的升级版。既然是走Memcached协议,那么就可以使用Moxi代理来提高性能。

  简单介绍一下Moxi:它基于memcached开发,对于并发的gets请求,做合并来减少和memcahed server的交互。对热点访问的cache会在本地缓存,减少network hops。network hops就是网络路由跳数,距离目的网络所经过的路由器数目。对于某种类型的key,可以异步set。可配置超时时间,也有错误重试机制。

  各个业务线反馈说Memcached不好用,有性能问题。好多业务线自己换成了Redis,解决了好多神奇问题。撇开这些数据不谈,给你一个用Redis而不用Memcached理由:Memcached的各种强化和代理Memcached自己都可以做,但是没有做。Redis却在不断的更新和优化。

  还有一个专门维护这个缓存数据一致性的服务。我个人觉得我们系统过分的强调了一致性,却牺牲了性能。下面是一些基本的理论:

分布式领域CAP理论:

  • Consistency(一致性),数据一致更新,所有数据变动都是同步的。
  • Availability(可用性),好的响应性能  
  • Partition tolerance(分区容错性)可靠性。

  定理:任何分布式系统只可同时满足两点,没法三者兼容。

  忠告:架构师不要将精力浪费在如何设计能满足三者的完美分布式系统,而是应该进行取舍。

 一致性模型:

  • 强一致性
  • 单调一致性
  • 会话一致性
  • 弱一致性
  • 最终一致性

BASE理论(CAP理论的延伸):

  • 基本可用(Basically Available):允许损失部分可用性,保证核心可用
  • 软状态(Soft State):分布式存储中一般一份数据至少会有三个副本,允许不同节点间副本同步的延时就是软状态的提现。mysql replication的异步赋值也是一种体现。
  • 最终一致性(Eventual Consistency):

  核心思想:即使无法做到强一致性,但是应用可以采用合适的方式达到最终一致性。

  像我们常用的分布式存储:mysql的主从读写分离,redis缓存的master-slave形式的主从复制都是基于操作记录的,都会有时延,也就是保证最终一致性而已。

  题外话:基本的理论和名词概念是很实用的。比如在之前公司做搜索引擎的时候,搜索引擎需要分词,分词的分词组件叫Tokenizer。这个不是搜索引擎特有的概念。Java的rt.jar这个最基础类库里有StringTokenizer和StreamTokenizer。如果你了解了这个,就很容易理解理解搜索引擎的分词是干什么用的。

  再说我们项目中过分强调数据一致性而损失性能和高可用的事情。完全可以不对一致性不那么精益求精。这并不是说不追求完美。追求完美可以提现在哪些方面呢?

  之前做的一个信用名片的项目,有的用户在某星手机的某些版本中上传头像,上传之后头是倒着的。经调查发现我们拍的照片在手机上可以各个角度拍摄,凭借着EXIF信息,这是一种专门为数码相机设置的格式。里面有拍摄时翻转手机的信息,可以有8种角度。很多操作系统和图片查看软件都会自动按照信息里的翻转角度,将图片翻转回来。但是某星的某些版本没有这个功能。针对这个问题,开始的时候,我用了一个国外的元数据萃取的工具包将这个EXIF信息的翻转信息提取出来。效果已经达到了。但是作为代码手艺人,觉得只是这么个小需要就添加了一个1MB多的jar包,而且实际上它的实现是解析构建DOM树的方式,意味着为了提取翻转信息,要解析构造整个文件对象。所以我自己又采用了直接读取图片二进制流的方式,取图片前面如果以0xFFD8开头的就是包含EXIF信息的,否则不予处理,读取文件结束。以0xFFD8开头的要判断是否包含旋转信息,包含旋转信息的判断是Intel标准还是Motorola标准,因为这两个标准高字节和低字节代表的含义正好相反。就这样一直到读到旋转信息或者判断出不存在旋转信息,文件关闭。所以最后读入的文件数据很少,效率大大提高。

  在之前公司用Solr搜索引擎的时候,有个需求是过滤输入的html标签。但是在Solr中对索引读入后的第一个操作就是分词,使用Solr自带的或者外部的分词器。然后再对分好的词进行更细节的过滤或者近义词之类的。但是这第一步就直接破坏了文档的结构,变成了一个个单词,而不是html文档形式。再去除,可以去除,一个个过滤符号和单词是否是html标签,判断前后都是啥。能做,第一,麻烦,最重要的是效率低。所以我当时的做法是直接修改了自己用IK分词器的源码,读入数据第一个操作先过滤标签。这就很好办了,apache有现成的工具类。这样避免了读入读出带来的性能损耗。

  说了这么多,架构到底是一个什么概念。我个人理解,在一个组织和系统内可以有很多维度的架构。

  比如业务架构是我们老大要考虑的事情。他心目中有一个自己的业务架构定位,外面提了一个需求,他有自己的规划,这个是不是应该纳入我们的业务体系。

  比如系统架构是管理者和架构师一起进行考虑的事情。业务定好了,那么用怎样的模块去划分这个业务更利于维护,更高效。

  比如技术架构是架构师的最重要责任。真正从技术角度去展示一个系统,包括硬件的,软件的,抽象的,具体的。它包括网络,服务器,第三方产品使用和调用,软件架构和数据架构。

  比如软件架构是开发人员可以接触到的软件开始的部分。比如一个web系统从nginx反向代理开始到一个SOA架构的系统:包括resin服务,resin服务上有一个mvc架构的程序,调用另一个服务的系统,系统又和缓存,数据库,消息队列,第三方调用打交道。

  比如数据架构,这个之所以单提出来是因为数据是服务的核心。比如对一个WEB应用来说,有一些数据是直接可以放到客户端的,如JS,静态页面。还有一些数据是要放到服务端的。服务端的数据又要考虑是放在缓存还是数据库还是文件等等。放在什么地方要综合考虑效率,带宽,安全,数据有效性和可靠性。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏DevOps时代的专栏

软件测试金字塔

? “测试金字塔”是一个隐喻,它告诉我们将软件测试分成不同颗粒度的桶,也给出了我们应该在这些组中进行多少次测试的想法。尽管测试金字塔的概念已经存在了一段时间,...

3485
来自专栏程序人生

再谈 API 的撰写 - 总览

背景 去年我写过一篇文章:撰写合格的 REST API。当时 Juniper 裁掉了我们在德州的一支十多人的团队,那支团队有一半的人手在之前的半年里,主要的工作...

3797
来自专栏Coding01

「转」论微服务架构

微服务现在辣么火,业界流行的对比的却都是所谓的Monolithic单体应用,而大量的系统在十几年前都是已经是分布式系统了,那么微服务作为新的理念和原来的分布式系...

864

什么是微服务?

自2011年以来,微服务一直是软件社区的重要组成部分,但与许多其他架构和设计理念一样,自从成立以来,围绕这种架构风格的争论不断。与许多这些炒作一样,有一种倾向于...

1453
来自专栏跨界架构师

分布式系统关注点——99%的人都能看懂的「熔断」以及最佳实践

那么在这样的背景下,如果某个服务A需要发布一个新版本,往往会对正在运行的其它依赖服务A的程序产生影响。甚至,一旦服务A的启动预热过程耗时过长,问题会更严重,大量...

602
来自专栏张善友的专栏

别再设计易碎的Web API

原文作者Mathieu Fenniak在博文中大呼:不要再设计易碎的Web API 了,否则你的合作伙伴或第三方开发者会因此恨你,而离你远去的。他认为,想设计出...

1928
来自专栏媒矿工厂

定义和测量延迟

想要优化延迟,可Latency到底是多少?延迟始终是媒体内容传输的一个重要关注点,人们也在不断尝试用新的方法来优化延迟,本文参考AWS的一些新技术,介绍了延迟的...

1553
来自专栏逸鹏说道

.NET技术+25台服务器怎样支撑世界第54大网站

英文原文:StackOverflow Update: 560M Pageviews A Month, 25 Servers, And It's All Abou...

3277
来自专栏北京马哥教育

Python爬虫爬取知乎小结

最近学习了一点网络爬虫,并实现了使用Python来爬取知乎的一些功能,这里做一个小的总结。网络爬虫是指通过一定的规则自动的从网上抓取一些信息的程序或脚本。我们知...

1063
来自专栏云技术活动

由浅入深 SCF 无服务器云函数实践

近年来,互联网服务从一开始的物理服务器托管,虚拟机,容器,发展到现在的云函数,逐步无服务器化。

7555

扫码关注云+社区