版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/tjgamejx2/article/details/51013428

1、定义

从实用主义角度描述分布式系统,即系统对外有统一的入口,系统内的业务层进程可以有无限多个,即可水平扩展,可根据计算量增减机器。存储层支持水平扩展,可根据计算量增减机器。使系统在计算和存储上,理论上可以达到无限制。对于这个定义,大家看看就好,我并没有过多的进行抽象,我希望更实用更易懂一些。强调一下,这只是一篇导论,概要描述一些分布式系统中的核心技术。

一般互联网系统常见的分布式系统部署为:外网负载均衡层—web层—业务逻辑负载均衡层—业务逻辑层—持久化层。回头给大家补张拓扑图。

负载均衡层的实现,从大类别上一般分为两种:proxy方式与客户端路由。

web层可以概括为外网业务层,并不一定使用的HTTP协议实现,一般用于处理外部协议解析,包装业务层原子功能以对外提供各种业务。

业务逻辑层,将系统划分为各个原子性功能,对更为复杂的业务层提供支持。原子性功能独立出来,可以组合出更多的业务,满足业务扩展,另外可根据不同的子功能增减机器。另外将核心业务层从web层剥离,也有安全性考虑。

2、负载均衡

客户端路由:即服务端有多个入口,客户端依赖一些策略选择访问具体某个入口。比如智能DNS,其实就是客户端路由的一种实现。

proxy实现:客户端全部访问统一的proxy作为访问入口,由proxy将请求进行分发,策略在proxy中实现,客户端无需关注。如:ngnix与Apache反向代理是典型的proxy,F5、lvs也算是一种,只是对于输出流并不走proxy过。也许这样定义proxy并不一定完全正确,但是我想不到一个更好的词了。

3、应用层分布式

要使应用层,即web层和业务逻辑层能够实现水平扩展,是相对容易的,总结一句话概括:保证应用层无状态,可实现水平扩展。然而在绝大多数应用场景中,业务都是有状态的,我们要做到的只是使应用层进程本身是无状态的,将进程内的内存缓存全部剥离出来,一般分为两大类,一、session,存储用户认证信息及某些业务的上下文信息;二、业务缓存数据。尽量不要使用进程内的内存锁,除非你确定他不影响进程多开。

目前主流做法均是将session和业务缓存信息抽离出来存入到redis或者memcache这些程序中,也有一些简单的做法,依赖负载均衡层,根据不同的sessionid或者业务id,将请求分发至对应的业务服务器上,比如在sessionid和业务id上加上服务器id,不过这种做法,在业务服务器宕机后,其他服务器并不能有效接管其客户端请求,并不推荐如此实现。

4、数据库层分布式

核心在于数据库水平拆分的实现,一般具体实现是根据要分表的字段做哈希,如对订单表的订单号对100取余,可将分为100份,得到一个订单号维度的100份表。这样拆分后,查询方必须知道订单号才可以进行操作。实际中往往要进行其他维度的查询,比如用户维度,那么在存储的时候,也需要存储一份用户维度的表。可以让应用层写的时候写两个维度,也可以使用触发器双写(多写),也可以根据数据库增量日志做异步拆分。

数据库水平拆分是一种以空间换时间的方法,大部分系统使用主从读写分离可以解决的问题,并不一定非要做水平拆分。

5、数据一致性与事物完整性

一个比较大型且业务复杂的系统,往往一个业务在处理时,链路是比较长的,即需要经过比较多进程或者系统处理才可以完成,当跨进程跨系统时,要保证数据一致性并不是那么容易,如果不注重数据一致性,那你们的客服估计要忙的晕头转向,技术与运维也会在查日志处理问题业务中无法自拔。

什么是数据一致性,系统被划分为子模块后,各个子模块对于同一笔订单,他们的数据应该是一致的,跨系统同理。举个最简单的例子,用户去银行支付,支付成功了,但是在系统中仍旧是未支付,这就是一个最常见的数据一致性问题。

什么是事物完整性,一笔业务在系统中流转顺序为,A-B-C-D-E,五个步骤,若ABC成功,到D就已经失败,那么这个事物不完整。这个与数据库中的事物处理又一定的区别,因为每个事物都作为不同的子事物在单独进程中执行,系统需要维护这样的事物完整,就必须增加额外的工作了,比如使用异步补调或者分布式事物管理器管理事物。

6、日志与监控

对于一个分布式系统,日志与监控是无法省略的,一个业务做完,往往链路比较长,这就需要比较完善的日志系统来跟踪业务。对于分布式系统来说,其系统中的进程非常多,业务也比较复杂,如果没有监控,那人就跟瞎子一样,哪些业务可能会出问题,哪些可能扛不住了需要加机器,都无从得知。

一般来说分布式系统,也应该有一套分布式日志跟踪系统,日志收集器将日志汇总到日志系统中,由日志系统对日志进行整理。每个业务请求进入系统应分配一个traceid跟踪号,使日志系统能够抽取其业务报文数据,耗时等。

请求次数、请求耗时、峰值、平均值、错误数、错误报文、线程并发数、请求被block的线程数、数据库请求消耗、并发数、峰值等等,太多的业务数据都需要被监控到,并且当各个指标与平均值偏离到指定值时应能及时告警。

7、系统可用性

假如每台机器一天中出问题的概率为0.1%,那么若系统有100台服务器,在1天中有一台及以上出问题的概率为1-0.999^100=9.52%,若是1000台服务器,这个概率是63.2%,基本上3天就有一台机器完蛋了,由此可见从技术上提高系统可用性的重要,如果在这样一个大型系统中你解决不了这个问题,基本上可能天天都有事故,还谈什么用户体验与自己的KPI呢?

我们需要考虑容灾了,不管是应用层还是数据库层,我们要提高系统可用性。heartbeat、keepalive对proxy等单点的容灾,MHA对MySQL的容灾等都可以帮助我们来提升系统可用性。

————————————————
版权声明:本文为CSDN博主「司马晨风」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/tjgamejx2/article/details/51013428