网站建设-数据库横向扩展
数据库横向扩展
在网站建设的过程中,一个高扩展性的架构设计可以保证当网站业务量和访问量达到零界点时我们能够以较低的成本对现有系统进行扩展。而网站系统最难扩展的部分通常是数据库或者持久化存储。当今最流行的RDBMS数据库,如Oracle,Sql Server等,都是关系型数据库。大多数数据库都有依赖基于ACID属性的外键,如下表,
属性 |
说明 |
原子性(Atomicity) |
要么完成事务中的所有操作,要么一个都不执行 |
一致性(Consistency) |
事务开始和结束时,数据库的所有数据都要保持状态一致 |
隔离性(Isolation) |
事务的表现就像它是对数据库执行的唯一操作 |
持久性(Duration) |
事务完成时,操作将不能更改 |
不管是使用哪种类型的外键,原则是只要写和读操作在同一时间发生就会出现两种情况,
- 读出来的数据与真实数据存在差异,因为数据在读出来的同时已经发生改变了;
- 必须保证读和写操作不能同时发生,操作必须等待另外一项操作完成后才能进行;
基于这个原则,当网站访问量达到一定数量时,根据使用的ACID外键属性的不同,就会出现数据存在较大差异或者操作等待时间过长的问题,因此我们就必须对数据库进行扩展来解决这一的问题。
在90%以上的网站建设项目中,数据库的读操作远远大于写操作,特别是企业的网站制作,99%都是读操作,只有管理员对网站信息进行增删改查时才会对数据库有写操作。对于这种高读/写比例的网站应用,创建只读数据库副本就可以轻松地扩展这类系统。这种通过创建数据库副本来横向扩展数据库的技术叫做“读写分离”。
时间敏感度
根据数据的时间敏感度,有两种方法可以分布数据的只读副本。什么叫时间敏感度?我们为什么要在乎它?时间敏感度指的是相对于数据库的写副本来说,只读副本有多新,还是完全同步的。因为对于读写分离的数据库来说,理论上可以做到读写副本完全同步,但是成本非常高,对于利益相关者来说这往往不是他们想要的性价比。因此,我们在这里讨论实际上是你到底能容忍多大的读写数据差异。
查询缓存
这种方法是在数据或应用层建立缓存层,每次查询可以先检查缓存中是否已存在对象,而不是每次都去读取数据库。当进行写操作后必须将数据标示为过期,下次读取时才需要查询事务数据库获取数据,更新缓存。现在有那么多优秀的键值存储系统可以作为缓存系统,如memcache,redis,couchbase等,所以先强烈推荐这种方法。
缓存机制
复制数据库
除了建立缓存层外,还可以通过复制数据库来拆分数据,大多数关系数据库都有某种类型的复制功能。Sql Server是通过主-从数据库的概念来实现复制功能的。所谓的主数据库就是只进行写操作的数据库,从数据库是主数据库的只读副本。主数据库会把更新,插入,删除等操作记录在二进制日志中,每个从数据库则是从主数据库中请求这些日志,在自身重现这些操作。如下图,
数据库读写分离
还记得我们上面提到的,在90%以上的网站建设项目中,数据库的读操作远远大于写操作,这意味着我们可以通过这样的数据库扩展,将很少量的写操作在一台主数据库中完成,而大量的读操作由多台从数据库承担,这样可以很好的将用户读取操作分摊到多台从数据库上,大大减轻了单台数据库的负担,理论上还可以通过无限扩展从数据库的数量来适应无限增加的网站用户访问量。
大多数的网站建设项目都可以通过这两种方法来增强网站扩展性,不仅仅是数据库,web服务器通常也能通过类似的原理轻松扩展,这样就能够把事务平均分配到多个服务器上进行横向扩展。但是遗憾的是,几乎没有一款现有的建站系统或建站软件原生支持这样的横向扩展,程序员必须对代码和数据库进行二次开发后才能实现。
但是对于某些必须保证实时同步的数据而言,这种方法就不适用了。在内存中缓存客户的专有数据或者不同功能的特有数据可能会造成扩展服务瓶颈,很难在不影响客户响应时间的前提下扩展这些服务。要解决这种内存限制,就需要我们对系统进行纵深扩展了。