从实用主义角度描述分布式系统,即系统对外有统一的入口,系统内的业务层进程能够有无限多个,便可水平扩展,可根据计算量增减机器。存储层支持水平扩展,可根据计算量增减机器。使系统在计算和存储上,理论上能够达到无限制。对于这个定义,你们看看就好,我并无过多的进行抽象,我但愿更实用更易懂一些。强调一下,这只是一篇导论,概要描述一些分布式系统中的核心技术。mysql
通常互联网系统常见的分布式系统部署为:外网负载均衡层--web层--业务逻辑负载均衡层--业务逻辑层--持久化层。回头给你们补张拓扑图。web
负载均衡层的实现,从大类别上通常分为两种:proxy方式与客户端路由。redis
web层能够归纳为外网业务层,并不必定使用的HTTP协议实现,通常用于处理外部协议解析,包装业务层原子功能以对外提供各类业务。sql
业务逻辑层,将系统划分为各个原子性功能,对更为复杂的业务层提供支持。原子性功能独立出来,能够组合出更多的业务,知足业务扩展,另外可根据不一样的子功能增减机器。另外将核心业务层从web层剥离,也有安全性考虑。数据库
客户端路由:即服务端有多个入口,客户端依赖一些策略选择访问具体某个入口。好比智能DNS,其实就是客户端路由的一种实现。缓存
proxy实现:客户端所有访问统一的proxy做为访问入口,由proxy将请求进行分发,策略在proxy中实现,客户端无需关注。如:ngnix与Apache反向代理是典型的proxy,F五、lvs也算是一种,只是对于输出流并不走proxy过。也许这样定义proxy并不必定彻底正确,可是我想不到一个更好的词了。安全
要使应用层,即web层和业务逻辑层可以实现水平扩展,是相对容易的,总结一句话归纳:保证应用层无状态,可实现水平扩展。然而在绝大多数应用场景中,业务都是有状态的,咱们要作到的只是使应用层进程自己是无状态的,将进程内的内存缓存所有剥离出来,通常分为两大类,1、session,存储用户认证信息及某些业务的上下文信息;2、业务缓存数据。尽可能不要使用进程内的内存锁,除非你肯定他不影响进程多开。服务器
目前主流作法均是将session和业务缓存信息抽离出来存入到Redis或者memcache这些程序中,也有一些简单的作法,依赖负载均衡层,根据不一样的sessionid或者业务id,将请求分发至对应的业务服务器上,好比在sessionid和业务id上加上服务器id,不过这种作法,在业务服务器宕机后,其余服务器并不能有效接管其客户端请求,并不推荐如此实现。session
核心在于数据库水平拆分的实现,通常具体实现是根据要分表的字段作哈希,如对订单表的订单号对100取余,可将分为100份,获得一个订单号维度的100份表。这样拆分后,查询方必须知道订单号才能够进行操做。实际中每每要进行其余维度的查询,好比用户维度,那么在存储的时候,也须要存储一份用户维度的表。可让应用层写的时候写两个维度,也可使用触发器双写(多写),也能够根据数据库增量日志作异步拆分。并发
数据库水平拆分是一种以空间换时间的方法,大部分系统使用主从读写分离能够解决的问题,并不必定非要作水平拆分。
一个比较大型且业务复杂的系统,每每一个业务在处理时,链路是比较长的,即须要通过比较多进程或者系统处理才能够完成,当跨进程跨系统时,要保证数据一致性并非那么容易,若是不注重数据一致性,那大家的客服估计要忙的晕头转向,技术与运维也会在查日志处理问题业务中没法自拔。
什么是数据一致性,系统被划分为子模块后,各个子模块对于同一笔订单,他们的数据应该是一致的,跨系统同理。举个最简单的例子,用户去银行支付,支付成功了,可是在系统中仍旧是未支付,这就是一个最多见的数据一致性问题。
什么是事物完整性,一笔业务在系统中流转顺序为,A-B-C-D-E,五个步骤,若ABC成功,到D就已经失败,那么这个事物不完整。这个与数据库中的事物处理又必定的区别,由于每一个事物都做为不一样的子事物在单独进程中执行,系统须要维护这样的事物完整,就必须增长额外的工做了,好比使用异步补调或者分布式事物管理器管理事物。
对于一个分布式系统,日志与监控是没法省略的,一个业务作完,每每链路比较长,这就须要比较完善的日志系统来跟踪业务。对于分布式系统来讲,其系统中的进程很是多,业务也比较复杂,若是没有监控,那人就跟瞎子同样,哪些业务可能会出问题,哪些可能扛不住了须要加机器,都无从得知。
通常来讲分布式系统,也应该有一套分布式日志跟踪系统,日志收集器将日志汇总到日志系统中,由日志系统对日志进行整理。每一个业务请求进入系统应分配一个traceid跟踪号,使日志系统可以抽取其业务报文数据,耗时等。
请求次数、请求耗时、峰值、平均值、错误数、错误报文、线程并发数、请求被block的线程数、数据库请求消耗、并发数、峰值等等,太多的业务数据都须要被监控到,而且当各个指标与平均值偏离到指定值时应能及时告警。
假如每台机器一天中出问题的几率为0.1%,那么若系统有100台服务器,在1天中有一台及以上出问题的几率为1-0.999^100=9.52%,如果1000台服务器,这个几率是63.2%,基本上3天就有一台机器完蛋了,因而可知从技术上提升系统可用性的重要,若是在这样一个大型系统中你解决不了这个问题,基本上可能每天都有事故,还谈什么用户体验与本身的KPI呢?
咱们须要考虑容灾了,不论是应用层仍是数据库层,咱们要提升系统可用性。heartbeat、keepalive对proxy等单点的容灾,MHA对MySQL的容灾等均可以帮助咱们来提高系统可用性。
来源:http://blog.csdn.net/tjgamejx2/article/details/51013428