第一部分是团队的情况和后端技术的架构。近一年我们的开发团队从50人增长到了现在两百人,公司总人数扩张到600左右,技术人员占的比例跟国内大多互联网创业公司的比例差不多,1/3左右的样子,昨天大会上王天提到Twitter的工程师44%左右在硅谷差不多是平均水平,国内公司比例要低一些。 我们是一家典型的业务驱动公司,并不是技术驱动的,业务驱动的一个特点是需要快速尝试各种可能性,需要技术人员能尽快跟上,好的程序员并不是那么好招的,某些阶段在一定程度上先靠人数来堆。所以挖财技术团队中少部分人是有一定经验的,核心的一些架构师主要是从阿里出来的,大部分的程序员相对普通。 而后端技术用的主要是比较大众的东西,Web容器用Tomcat,框架主要是Spring MVC,也有少量的Play,中间服务层是Dubbo,微容器用Spring Boot,服务注册这一块是用ZooKeeper,核心业务开发方式还是围绕着Spring和Mybatis等;数据的存储这块是MySQL和Hbase,分布存储这块是用阿里巴巴之前开源的一个中间件Cobar。 消息和实时计算这块主要是Kafka, Storm,日志以及监控系统则是用典型的ELK和Zabbix。另外我们将要放弃MongoDB和Memcached,并不是这些产品自身的问题,而是人的因素,最早的架构师对MongoDB很熟,后来因为他离开,这块的一些问题缺乏强有力的人把控,就放弃了。其他人对MySQL和Hbase更熟悉,并且这两种组合基本满足我们的需求了。Memcached则是被Redis替代。 总的来说,我们裁剪掉了一些之前使用的相似产品,减少为一种,主要是基于自身运维能力考虑的,不在于这些技术是否足够好或者是否符合团队的特性和遇到的问题,而是你能不能把它维护的好,或者说风险控制好。 业务上面我们大概也是比较典型的。基础设施是一块,然后中间是服务,上面是日常的应用。基础设施就包括典型的存储、消息、框架,还有发布、运维、监控等等。中间就是现在典型的SOA服务,用户的资产、服务、流水、交易等等,所有的服务采用Spring Boot打包部署,主要便于运维上的统一和方便做一些切面层的事情。最上面是应用,包括社区、记帐、钱管家、理财。而安全和风控会切入在每一个环节。 其实作为一个互联网的金融公司,很多时候我们对金融会有一点点陌生,在我们看来做一个理财产品或者一个理财业务其实和电商业务有很大的相似之处。主要就是理财产品,他也是一个商品,这个商品可能有高的回报,最初形成这个商品的时候背后有一套综合系统或者说有一套逻辑。并且购买这个商品之后,这个商品是有历史的,他的收益是在变化的,所以简化之后,我们发现跟电商系统是相似的。 这就是典型的架构,前面是Web或Gateway,中间是Service,中间层协议是Dubbo默认方式或者是HTTP。 数据存储这一块主要是MySQL和Hbase,当前还有小部分数据使用的Mongo,ORMapping这块我们用了MyBatis。数据的水平扩展主要是基于刚才提到的Cobar,它是阿里比较成功的开源产品之一。Cobar支持数据的二维扩展,能满足我们的场景,比如说几千万用户的流水记录可以按用户加时间的维度来划分。如果单纯按时间的维度分区,在查询用户的流水时要散落到各个分区上,对各个分区的压力都较大。而按用户的维度则可能导致这个分区在一定时间后达到我们预设的容量上线,因为一天有几百万甚至上千万的流水进入。 二维的方式可以解决这些问题。尽管我们后来发现用户的数据大多在最近一段时间内较热,时间比较早的数据相对较冷,只用了Cobar的一维扩展方式,将冷数据归档到Hbase集群来解决。在数据的在线处理这块,有很多用Akka框架的程序,比如计息系统主要是运算的,所以Akka很适合干这个事情。 自动记帐这块主要是钱管家这款产品,他会根据银行的帐单把这些数据汇总到这个产品里面,主要是从其他系统汇聚出原始的数据,根据这些数据我们会进行分类,进行加工和抽取,最后汇总到database,这个过程的思路就是command pipeline下面这套组合,只不过是分布式命令和管道,分布式里面命令是Akka所承担的角色。 数据分析这块,Canal会把binlog数据丢到Kafka然后同步到其他系统。在线分析主要通过Storm进行,数据分析过程中缓存用了豌豆荚的Codis。离线分析目前用Hadoop/Spark的方式,数据分析之后,一部分存到Hbase,另一部分在通过Cober存储到MySQL里面。 前面介绍了挖财的架构,第二部分说说我们选择Scala的原因。首先Scala的语言还是有点争议的,不管是大师级的人物还是编程语言爱好者,对编程语言的争议从来没停止过的。但不管别人说Scala怎么样,从工程师的角度,从实用的角度来说,我是比较认可这个语言的。 我觉得松本行弘批判保罗格雷厄姆的话非常代表我的观点,他说的语言会朝着“小而干净”的方向进化,他自己也创造过一个Lisp的方言叫ARC,他崇尚保持简洁和纯粹的设计思路,但这门语言并不算成功。从总体或者说未来的趋势来看,语言已经不可能保持那么小而精的状态。能够真正做到解放生产力这么一个目标才是演化的方向,所以从解放生产力这个角度来看的话,Scala实际上是达到了这个效果的。不管怎么骂,Scala确实为我们解决了很多实际问题,加速了我们的效率。 我们为什么会选择Scala?可以说有一些巧合,在挖财快速发展的过程中,几个核心的架构师对这种语言都是比较喜爱的,并且之前有些经验。如果是一个人,或者说你的公司想做这个事情,但是没有人能够支持你去做这件事情的话,那其实是相当麻烦的。因为你至少要有好几个能力相当不错的人能够一起来做这个事情,才可能在公司把这个事情推广,才能够影响更多的人。这样形成核心的小的影响之后,会吸引来更多的爱好者的加入,这样才能够使这个语言被大家所接受。 所以这就必须是一个团队,既使个人能力再强也没用,团队的意愿非常重要,假如他不愿意用这个语言,或者他不接受这个语言,那么用主流的Java也是OK的,培养而不是强迫,如果用这个语言当然更好,如果不使用的话也没有关系。但是我们可能在口味上会偏好这些人,因为我发现相对来讲这些人他会更愿意去思考,或者说在处理一些问题的时候会比普通的程序员想的更多。在这个过程中还有个非常重要的事,就是慎重的选择开发栈。 就拿选择Scala来讲,Scala有他自己的生态系统,跟Java还不太一样。比如说Java在Web层有Struts/Spring MVC框架,Scala有Play/Lift,构建工具Java里面是Maven,Scala则以sbt为主。Scala有一套自己的玩法或者说技术栈,你是不是选择整套技术栈是需要非常慎重的。 挖财处于一个中等创业公司的规模,对我们来说,Java还是更大众化的。在业务发展过程中,人员加入还是比较快的。而且很多人还是以Java为主,所以我们的做法是不改变这些人员的习惯,还是以Java生态为主,没有强制的用Scala的开发栈。而且Scala的技术栈里有不错的产品,也有维护的很差的产品。你选择一个产品时,先看它的邮件列表,如果邮件列表里都没有什么来往邮件,这个产品的维护性和持续性肯定不够。 Scala的优点体现在,原来Java里的设计模式,现在在Scala的语言层面就提供了。比如说Java里的单例,Scala直接对应的就是object;访问者模式我们可以用更优雅直观的模式去匹配;还有构造器模式;依赖注入在Scala里面有蛋糕模式。 不可变的模式主要是在并发编程里面的,并发编程我们主要面临的就是状态,怎么同步或维护这个状态,保证这个状态不被污染掉。如果这个状态本身就是不可变的,那么就不存在竞争性。Scala本身推崇不可变的思路,当你想要去改变这个状态时,实际是new一个新的状态,原来的数据对象并不会改变本身,但Scala也并不是说完全像一些纯粹的函数式语言偏执于只用一种纯粹的不可变对象,所以Scala也提供了一种像Java的可变的数据变量(用var声明)。 还有就是Java里面我们用来在不同的领域(尤其是在网络)之间传输的都是值对象,值对象的描述跟一般的对象一样,表达上略微有点嗦。而Scala里使用的case class在表达上则简洁一些,并且这些case class配合模式匹配非常好用。这些都是表达方式的简洁化,或者提升生产力的一种体现。 其他的优点比如动态类型以静态类型的方式去实现动态的效果,我们称之为duck typing,他看起来像duck听起来也像duck那么它就是duck。Scala里面以隐式参数或者隐式转换的方式实现动态语言的等价效果,只不过这种方式在编译器能够更好的检测,所以在安全里更有保障。 还有利用函数式特性去自定义流控,比如说C#里的using是一个很好的特性,我们在using的括号里面定义一个resource,不管是一个文件流或者是一个disposable资源,程序处理完会把这个资源自动释放,我们可以在Scala里面通过柯里化和函数特性也可以灵活的定义类似的流控,实现等价效果。另外还有它强大的集合操作,就举两个例子,我们想要从同一组流中进行下图的两个查找,同样的效果的写Java很麻烦,而Scala通过高效的运算以很简洁的方式实现出来。 当然他有不好的地方就是门槛相对高一点,这个门槛就是函数式背景,举一个例子,比如说eta规约,比如说我这个函数里面的参数是接收另外一个函数,简单的说就是高级函数,这个高级函数里面传给他的参数比如说是 arg = |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|