关于大型系统下数据库的一些思考

关于大型系统下数据库架构的一些思考

       最近在读曾宪杰大虾的《大型网站系统与Java中间件实践》这本书,感觉还是很有收获的。这本书主要讲了大型网站系统在建设过程中所面临的一些常见困难,并介绍了一些常用的解决方案。其中作者写的最多的一句话就是要根据实际场景具体分析最后选择解决方案。从书的第一页快看到结尾了(其实这已经是我第三遍看这本书了,基本每隔半年就看一遍,每次看都会有新的体会),也慢慢体会到了为什么作者要说要根据实际场景,因为确实如果系统还没发展到大型系统,就不需要一些比较重量级并且耗费比较大的解决方案,比如说数据量较小时,完全可以把数据放在一个数据库中,只需要用一台机器来作为应用服务器,业务服务器和数据库服务器,可以把数据放在一张表中。

       这本书一共分为了8章,分别是分布式系统介绍、大型网站及其架构演进过程、构建Java中间件、服务框架、数据访问层、消息中间件、软负载中心与集中配置管理、构建大型网站的其他要素。其中,我主要想写写有关数据访问的体会和思考。

       数据永远都是软件的基石和核心,如果一个软件没有数据,那这个软件就没有多大的实际用处(当然这里不排除一些只作UI展示的软件)。而数据访问包括数据的读和写,读和写就会产生很多问题,比如说数据库读写会有事务管理问题,也就是ACID。读读数据时不会产生事务问题,但是如果一边读又一边写,那么可以写的数据读不到,或者读的数据被修改了不能重复读。这些事务型的问题,大部分的关系型数据库都给了解决方案,一些数据库框架也提供了一些事务控制功能。但是一但数据量太大时,单机往往就不能承受住访问流量了。这时候就需要系统的架构演进了,通常的作法是把一台机器分成多台,把应用服务器和数据库服务器分到不同的物理机上,或者还可以加上一个业务服务器,把业务封装成一个服务,这就涉及到SOA服务化的内容了,这里主要讨论数据访问的问题。数据访问量继续增加,服务器还是抗不住,那就再加机器,这时候就形成了服务器集群,服务器集群就会产生许多问题,比如说请求路由、负载均衡、Session管理等,这些都还只是应用服务器的问题,在这里也不做过多讨论,我们还是主要讨论数据访问的问题。通常服务器扛不住都是因为数据库访问扛不住,这时候就需要在数据库架构上想办法了。在网站的架构演进过程中,可以发现其实大部分数据访问都是读多写少的,而多个数据库服务器机器其实都平摊了读与写压力,但其实扛不住的是读压力,因而,我们可以把数据库分为读库与写库,也就是所说的读写分离。读写分离有什么好处呢?好处就是可以分解读写的压力,可扩展性更强,我们可以更加关注数据库的读操作,我们通过加强数据库的读能力来提高系统的吞吐能力。比如说用一个写库,弄3个读库,这样可以充分利用物理机器资源,降低了物理成本。

       读写分离貌似是个很好的解决方案,但问题还是很严重的,读写分离后数据如何同步呢?当读写在同一个数据库上时,读与写只存在事务问题,但如果分成了读库与写库,就涉及到读库与写库的数据同步性问题了。通常有两种方法,一种就是在读数据时,把读挂起,写完成后再放行读操作,这样貌似是可以解决读写分离的数据同步性问题的。但仔细一想这样其实是违反了读写分离的初衷的。还有一种方法是热数据思想,就是把增量的数据同步到读库中去,而同步的时候增加的数据写到缓冲中,这样数据增量会慢慢收敛。同样仔细想一想,其实这种方法是不能做到数据同步的,但却是可以做到最终的同步,虽然做不到全局的同步。

      好了,读写分离后的数据库集群数据同步解决了,数据量进一步增加,就需要把数据库进行拆分了。拆分方式有两种,分别是那水平拆分和垂直拆分。垂直拆分是按业务的不同把数据库拆分成专用数据库,比如说用户模块就可以做一个用户信息数据库,而产品信息数据就可以放在产品数据库中。这样的好处也和读写分离一样,因为不同模块的访问压力是不同的,很明显在一个么电商网站中商品信息的访问压力是要远远大于用户信息数据的,因此垂直拆分可以让压力更大的模块得到更多的资源。水平拆分是因为一张表可能不能够装下所有的数据,这时就需要把一张表拆分成多张,同时这样也可以降低数据库查询的压力,比如说把不能省的用户信息数据存放在不同的表中,在数据查询时,根据不同省进行不同表的查询,可以节约一部分的检索时间。

       数据库集群后且垂直水平拆分后就会出现一些新的问题,比如自增字段和集合操作怎么办呢?在单机的时候,自增是由数据库提供的,集合操作也比较容易,比如说分页排序,直接从表中取数据就可以了,但如果分表后就复杂多了。比如说要从4个表中提取40个数据,就需要从不同的4个数据库表中分别提取40个数据,对这160个数据进行归并排序,再提取其中的40个数据,其中的120个数据其实是浪费了效率的。再者关系型数据库的Join在分库分表后会相当的麻烦。看来数据库的分库分表并不是想象中那么美好。通常的解决方案是使用数据访问中间件,也就是在业务层和数据库层之间添加一层数据库访问中间件层,通过这个数据访问中间件,可以把下层的数据库集群逻辑性地当作一个单机的数据库,数据库中间件可以自动完成集群带来的所有问题,而对上层的调用则表现得像是单机单库一样。这确实是个不错的主意,而实际上大型系统的公司确实是采用了这种方法,比如说深受IOE毒害的阿里就基于MySQL数据库构建了AliSQL系统,用TDDL框架来充当数据库集群的数据访问中间件,阿里也来了一场轰轰烈烈的去IOE革命,很明显,阿里近几年的双十一证明阿里成功了。

你可能感兴趣的:(学习,读书笔记)