可伸缩性最佳实战

今天看了一篇关于伸缩性的文章,感觉不错,大体翻译了一下,欢迎各位道友探讨。

异步

同步调用使得组件和组件之间紧密耦合起来,这样就使得要想伸缩应用就需要伸缩所有的组件,这不仅带来使得伸缩的成本增加,而且这种高度耦合性使得伸缩变得更加困难。因此我们需要从应用角度划分出,哪些业务操作是紧密关联的,哪些是可以异步执行的,划分出那些可以异步执行的操作,然后将其进行异步化处理(比如通过JMS,事件队列,多播消息等或者线程池等),这样划分的好处就是系统可以应对更大的访问量,消弱访问峰值,比如在同步的时候A调用了B,那么用户能接受响应时间就是A处理时间+B处理的时间,而采用异步以后,当访问量增大的时候,因为A和B异步,那么A很快返回,用户体会不到延迟,而B的处理时间由原来的2秒处理完毕,变为3秒处理完毕,而B得处理都是在后台进行的,不会影响到客户响应事件,同时异步也起到了消弱峰值的作用。

其实在社会生活中也存在很多异步的场景,比如老板和秘书,假如老板没有秘书,那么势必老板在处理完事情A之前没有办法处理新的事务,而有了秘书以后,有什么次要的事情让秘书去办,同时老板可以做其它的重要的事情O(∩_∩)。
因此异步不仅利用底层框架平台的异步性,更重要的是如何做到应用本身的异步性,只有做到了这一点才算是真正的异步。

泳道设计
通过泳道(非常形象的比喻)将错误进行隔离,使得不同的错误域的错误不会相互干扰,这样也就不会因为系统某一部分的错误影响到系统的其它的部分。

缓存

在系统多个层使用缓存,比如在数据库前面的Model缓存,页面,页面片段缓存等。至于对象缓存,jdon已经讨论太对了呵呵。

监控

我们应该站在真正用户的角度去理解系统的性能,包括从外部网络测试用户体验以及内部系统的各个组件调用的次数以及每次调用的时间等等。

复制
数据库读写库分离,这样不仅可以做到一定的容灾,而且可以通过读写分离来减低写数据库的压力。

切分

没有切分就没有伸缩性,因此一个具有良好伸缩性的系统必须进行切分,而切分可以从两个地方入手,首先应用角度来说,可以将系统在垂直方向上面分层(这是一种系统架构级的粗粒度的切分),同时将系统的每个层按照功能或者资源进行水平的切分(这是一种相对细粒度的应用级的切分)。

其次对于数据的切分,比如将用户信息,交易信息,商品信息等独立存储,数据库的切分主要有读写库分离以及Sharding技术。

尽量少用关系数据库特性

系统使用关系数据库的特性越多,那么伸缩性就会变得越差,这就要求将应用逻辑从数据库真正的移动到应用中来,数据库仅仅是一种存储的技术手段,而不是应用逻辑运算的地方。

我想这一点大家应该比较清楚,如果将业务逻辑用存储过程实现,那么就会造成非常差的伸缩性,但是我想说的是及时不用关系数据库的特性,如果我们不能从应用的角度去设计系统,照样会造成很差的伸缩性。比如目前普遍采用的SSH,其实说白了这还是一种面向过程的开发,每次业务操作都是从Dao获取数据,然后Service改变一些数据,最终调用Dao保存数据,这种方式还是一种没有伸缩性的方案。

那么什么样的方式比较具有伸缩性,我个人认为通过领域建模和分布式缓存,通过对象建模形成业务对新,业务对象以聚合的方式存在缓存中(当然随着KEY-VALUE的不断流行,我们可以直接将聚合跟存放在KEY-VALUE存储系统中),每次业务操作都是存缓存中取出业务对象,调用业务对象进行业务操作,操作的过程中,业务对象会触发领域事件,然后最终领域事件监听器调用技术组件完成一些附加操作,采用这种方式,我们还可以采用异步的领域事件,这就使得系统的并发通过JAVA本身的内存锁机制实现,而不是靠原来的数据库的事务隔离性来保证并发安全性。

压力和性能测试

在系统发布前进行压力和性能测试,尽管不会发现所有隐藏的问题,但是它也是非常值得的。

容量规划以及伸缩性探讨会

我们要清楚的认识到当前系统能支持的负载,以及系统中可能存在的性能和伸缩性的瓶颈在哪里,在解决了某一个伸缩性的瓶颈以后,我们就需要关注下一个随着系统不断增加可能带来伸缩性瓶颈的问题。

回滚

任何操作都有可能失败,因此我们的系统一定要做好回滚操作,这个回滚操作室广义的回滚,具体可参考“可伸缩性和可用性反模式”。
根源分析

确保能在发生问题的时候找到问题的根源,做到治标治本。

关注系统质量

应该在系统开始的时候就关注系统质量,而不是在测试阶段出现问题的时候才考虑如何伸缩,那个时候就晚了。


原文:http://akfpartners.com/techblog/2009/08/11/scalability-best-practices/
[该贴被xmuzyu于2009-12-06 19:48修改过]

切分 异步 这些境界其实只有面向对象OO修行到一定份上才会有,面向对象设计模式培养程序员对设计细分的敏感性。深厚OO思维可以培养人的异步思维。

当然,也有人说,切分异步不一定来自OO,其实他们都来自于自然,我们日常处理事情的基本逻辑,只不过我们可能没有发现它的眼睛。

而如果拥有这颗能辨别业务细腻度眼睛以及细分一套方法,那么,无疑你已经是一名合格的架构师。


呵呵,我觉得切分,异步,BASE是一种新的架构风格,只有切分了才能更好的实现异步,只有异步了才可以更好的实现BASE策略,只有真正实现了BASE,系统才会有一个很好的伸缩性和可用性,否则如果没有切分,什么地方都同步,所有炫都绷得紧紧的肯定会断。因此切分,异步,BASE应该同属于一个体系。

2009年12月06日 20:41 "xmuzyu"的内容
什么地方都同步,所有炫都绷得紧紧的肯定会断。因此切分,异步,BASE应该同属于一个体系

是的,同步就是刚,刚则易断,而异步是水,以柔克刚。

BASE确实是一个好的可伸缩模式,不但指出实践中存在这样一个需求,而且指出如何在CAP定律下进行妥协协调。蕴含艺术技巧其中。

下面有点扯开,权当灌水:
昨天看了一部机器人片子,智能机器人之父认为由代码组成的机器人后面开始有灵魂,灵魂是什么?就是创造性和情感艺术。

电影的主人公和一个小女孩同时掉入水中,机器人可以根据概率立即算出主人公存活率是45%。而女孩是11%,所以救了主人公,但是主人公说:如果是人类,就会救只有11%的女孩。

我举这个例子,主要说明数学量化思维和艺术哲学思维的不同,不能以数学替代哲学,软件架构有很多是讲究艺术性的,比如BASE理论是一种在一致性和可用性之间的平衡,至于怎么平衡,没有公式。

而关系数据库 数据结构则是一种完全数学化的量化方案,充分发挥了计算机精确计算的功能,通过关系数据库的Join语法可以精确将很多数据集合在一起计算,结果是非常好,但是数据量一大,访问量一大,它自己就很累,就无法获得更好地性能。

这时候就要站在关系数据库 数据结构之上更高层次来看到问题,从业务源头进行重新探索,进行切分异步化,减少必须使用关系数据库的场景,这是一种非常正常的逻辑思维。

系统使用关系数据库的特性越多,那么伸缩性就会变得越差,这就要求将应用逻辑从数据库真正的移动到应用中来,数据库仅仅是一种存储的技术手段,而不是应用逻辑运算的地方。
------------------------------------
xmuzyu 你好,上述这句不甚理解,假设在项目中使用存储过程,各种约束,等等,那么在分层的时候,会受到很多影响?

2010年02月05日 09:37 "mouqj"的内容
系统使用关系数据库的特性越多,那么伸缩性就会变得越差,这就要求将应用逻辑从数据库真正的移动到应用中来,数据库仅仅是一种存储的技术手段,而不是应用逻辑运算的地方。
------------------------------------
xmuzyu 你好,上述这句不甚理解,假设在项目中使用存储过程,各种约束,等等,那么在分层的时候,会受到很多影响?

你好,是否使用RDBMS,是否使用存储过程对于分层没什么影响的,DB只是存储的地方,一般通过Respository封装,而业务逻辑的运算要放到你的业务层,也就是通过你的对象Modle来进行。这样依赖RDBMS越少,你的系统在scale out方面就好一点,当然了还要看你的业务层本身的设计,到底有没有切分,模块之间的通信方式适当(比如同步,异步等)。

2010年02月06日 11:31 "xmuzyu"的内容
而业务逻辑的运算要放到你的业务层,也就是通过你的对象Modle来进行。这样依赖RDBMS越少

也就是说还是个类似“解耦”的概念,使用模型层与数据库打交道,而业务逻辑,则构筑在这层之上?

从业务过程开始分析:
DB: 专职于数据存储。数据的来源、含义、使用都不属于这一层的范畴
业务逻辑:专职于数据的应用,用来解决我们遇到的问题。数据的读写方式不属于这一层的范畴。

简单的理解是解耦合,深入一点则是划分核心业务过程。划分的足够清楚了才能够在存储不足的时候很方便的添加一个DB服务器,在处理速度不足的时候很方便的添加一个运算服务器。

我想请教个问题,这个异步如何能更好的支持并发呢,返回时间肯定快了,但是我就没想明白怎么缓解访问高峰了,能给简单解释一下吗,谢谢