我也要谈谈大型网站架构之系列(4)——分布式中的异步通信
我们知道在面向对象编程中,总会想着各种办法来实现代码的解耦,从而让项目中的各种人员面对自己熟悉的业务进行开发,
做到术业有专攻,比如大家非常熟悉的三层架构,MVC,MVP以及MVVM模式,让前端设计专注于html的制作,让后端开发人员
更加专注于业务逻辑的编写,可以看到,我们这么做的目的就是想最大程度的做到系统的可扩展和可维护性,那么我们的大型网站
是不是也要遵守这种模式呢?
一:分层和分割
1:分层
对于分层,我们可能非常熟知了,数据访问层,业务逻辑层,缓存层,应用层,层层专注于自己的业务,然后根据需要建立起
各自的集群,各自分离部署,而从达到系统的扩展性和维护性。
2:分割
如果说前面是横向切割,那分割就是纵向切割,我们可以把网站的整体业务切分成很多的小业务,比如博客园的导航栏,我们都
可以认为是一个独立的网站,配上各自的二级域名,建立各自的集群来实现系统的扩展性,当然这个粒度可大可小。
如果说这些子网站不存在相互调用,那么我们新增模块或者修改模块基本上都不会对其他模块造成影响,这也是我们做扩展性的终极
目标,现在既然都做到解耦了,下面的目标就是做如何通信了,通信可以分为“同步”和“异步”,这篇主要是讨论下异步操作,在分布式
系统中做到"异步操作“,当然少不了强大的消息队列。
二:消息队列
在分布式的系统中使用消息队列后,我们的生产者只管向消息队列中甩完数据后立即返回,而不管是哪个消费者来消费,可以看到
其实消息队列有如下三个优点。
1. 加快网站的相应速度
这个刚才也说了,应用层直接把消息给消息队列然后直接返回调用端,这样就避免了处理复杂的业务逻辑然后同步的插入到数据
库后再返回造成的响应延迟,在很多网站上用户提交订单就是这么处理的,应用层生成一个订单号之后,将订单丢给消息队列,然后
直接到订单成功页面,此时后端消费者对订单还没有处理完毕,因为后面会有比较多的数据操作,比如减库存,数据库同步等等,而
用户如果想要看到订单详情,需要点击“订单号”才能进入到订单详情页,这种处理也是因为消息队列的非及时性,所以需要得到网站
设计方改进和支持。
2. 提供系统的可用性
既然是异步操作,就造成了生产者不知道消费者的存在,而反过来消费者不知道生产者的存在,如果消费者挂了就不会影响到生产者,
生产者还会照常无误的向消息队列甩消息,当消费者恢复正常后就会继续消费消息队列,系统的表现可能就是email或者短信延迟收到,
不会对系统造成太大的影响。
3. 并发削峰
既然是大型网站就免不了高并发的读写操作,很典型的一个例子就是电商中的秒杀,这种高并发的写操作,如果一下子都涌入到数据库
里面去了,会导致数据库的压力非常大,从而导致客户端的访问延迟,就是不挂也容易造成数据库的死锁从而造成很多灵异事件,遇到这
种一拥而入的情况,我们就必须进行线性化操作,在代码层面上我们可以用lock机制来串行化,在分布式中我们用“消息队列”来串行化,
而且还可以通过逻辑操作来对消息队列进行动态的防洪,控洪。
在消息队列的选择上,微软有自己的MSMQ,但是在大型网站中,我们的消息队列同样需要集群,并且希望能跑在内存中,并且支持序列
化硬盘,同时在“伸缩性”和“可靠性”上要有好的作为,所以推荐大家用用开源的RabbitMQ,网址:http://www.rabbitmq.com/ 不过很
多公司都有自己开发的消息队列,比如携程的CMessage,淘宝的MetaQ。