集群的进化

阶段一、起步
刚开始时,网站流量比较小,所有的软件都安装在一台服务器:


阶段二、拆分
流量大了,一台电脑无法支撑,所以我们需要把每个服务单独放在一台服务器上,以提高网站的吞吐量:

阶段三、横向扩展
流量更大时,发现即使每个服务用一台电脑也是不够用的,这时我们需要 横向扩展 每种服务需要用到的服务器:

Nginx、PHP这些服务提供的服务完全是一样的,在扩展时只需要简单的添加更多的服务器即可,而 MySQL、Redis 这些保存数据的服务不能通过简单的添加服务器来扩展,还要考虑到多台服务器的数据同步问题,后面再详细介绍。
阶段四、拆分功能模块
当流量再大时,我们发现只是简单的拆分服务器已不能满足要求,这时我们需要再往细了拆分:拆分功能模块,每个功能单独放到一个集群上,这就是目前非常流行的 微服务

技术介绍

负载均衡(Load Balance)

将请求转发给任一后端服务器。

转发策略:负载均衡有多种转发策略,常用的有轮询、加权轮询等方法

健康检查:通过 心跳 机制检查后端服务器是否正常运行,如果某台服务器宕机就不再向这台服务器发送请求。

软件:实现负载均衡常用的软件有lvs、haproxy、nginx 等。

高可用(High Availiablity

高可用:系统能够一直提供稳定的服务,即使服务器出现宕机的情况。

很多公司的高可用目标是4个9,也就是99.99%,这就意味着,系统的年停机时间为8.76个小时。

服务器宕机是不可避免的情况,那么我们如何才能保存系统在有机器宕机时依然能够提供服务呢?

实现高可用的原理非常简单:提供一个备份服务器,当工作服务器宕机时,备份服务器马上替代上

比如上面负载均衡图框架中的负载均衡服务器就存在 单点故障 问题,就是说如果负载均衡服务器宕机了,那么整个系统就无法访问了,所以为了解决单点故障我们需要为负载均衡服务器添加一个备份服务器:

常用实现高可用的软件有:keepalivedheartbeat 等。

SESSION 共享

由于 SESSION 的原理是在服务器上保存数据,这就会导致在集群环境下出现 SESSION 丢失 的问题,这是因为在有负载均衡的集群环境中,每次请求的后端服务器可能是不同的,我们在保存 SESSION 时可能保存到了 a 服务器上,而在负载均衡轮询到其它服务器时无法读取到 SESSION 数据。

由于 SESSION 是保存在第三台服务器上的,所以当负载均衡把请求转发给另外两台服务器时就会出现获取不到 SESSION 的情况。

解决 SESSION 丢失有两种办法:

1、 SESSION 共享

将 SESSION 保存到 Redis 或者数据库中以实现共享,由于 SESSION 的使用比较频繁所以还是放在 Redis 中最好:

2、IP HASH

另一个方法是修改负载均衡的转发策略,不要使用轮询的方式,而是使用IP HASH的方式,这种方式会根据用户的IP进行HASH运算然后计算出对应的后端服务器,以后这个IP发送的所有请求都转发同这台服务器上,这样同一个用户每次访问的是同一个后台服务器,这样就可以正常使用 SESSION 了。

反向代理

反向代理服务器相当于是一个缓存服务器。

用户首先访问反向代理服务器,如果在服务器有要访问的数据的缓存数据并且没有过期就直接返回给用户,如果没有缓存数据就替用户到后端去取数据,取到数据之后缓存到本地,然后返回给用户,下次再有人访问同样的数据时直接返回缓存数据。

这种服务器常用来缓存网站中静态页面,比如:新闻详情、小说详情等不经常更新的页面。

常用软件:varnish(推荐)、squid。

CDN

CDN:内容分发网络,和反向代理类似,只不过,CDN是把数据缓存在世界各地的服务器节点上,当用户访问数据时会从离他最近的服务器节点上去找,比较适用于静态资源的地域优化。比如:图片、新闻、视频、直播、音乐等。

数据库集群

数据库的集群不能通过简单的扩展服务器来实现,因为数据库在集群时要考虑数据的同步、事务一致性等问题。常用的数据库集群方案有:
1、主、从复制
2、分库、分表
3、PXC 集群

主、从复制

MySQL 自带主从复制。

一主多从

适用于:读操作比较多,写操作比较少。

一个集群中只能有一个主服务器,可以有多个从服务器,对主服务器上的所有写操作都会自动同步到从服务器上:

工作原理
主服务器会将所有写操作记录到 binlog(二进制日志) 中,然后从服务器会从主服务器读取这个 binlog,然后在从服务器上把 binlog 中的内容重放一遍以实现数据的同步。

读写分离
在主从复制这种架构的基础上,我们的程序就可以实现 读写分离 来提供网站的性能。

读写分离:指所有的定操作都到主服务器上去执行,所有的读操作都到从服务器上去执行,这样可以在不同的服务器上执行不同的操作,以分担单台服务器的压力(注意这里主服务器存在单点故障问题,如果要解决这个问题,我们就需要实现 MySQL 主服务器的双机热备)。

多主多从

当网站写压力比较大时,我们就需要多台主服务器来分担负载,然后让它们互为主从这样就可以同步数据了,这时我们可以搭建以下结构的 MySQL 集群:

跨地址同步数据存在的问题:数据延迟
由于主从复制是异步执行的,复制数据时根据系统负载、网络等多方面原因会出现从服务器复制数据的延迟问题,这就会导致新插入的数据无法马上读取的情况,这对于一些对数据一致性要求比较高的系统是无法接受的。比如,我刚刚下了一个订单并且支付成功了,可系统却一直显示未支付,此时用户一定会心慌慌担心自己的钱被骗了。

解决办法:
1、使用 PXC 集群:PXC是一种 强一致性 的集群,在向一个节点插入数据时,PXC会先将这个数据同时插入到所有其它节点上去,在其它节点没有插入成功时就一直阻塞等待,直至所有其它节点都写入成功了,才会显示插入成功,否则显示插入失败。这种集群对于一些和钱相关的系统来说是很有用的。当然有利就有弊,PXC的集群的缺点就是速度慢,对强一致性要求高的场景,主要跟钱相关。

2、使用缓存服务器来减少延迟:为了即保存一致性又能保证性能,我们可以使用缓存服务器(比如 Redis )来暂时存储数据以减少延迟。

写数据时:同时向数据库和 Redis 中写入

读数据时:先到数据库中读,如果数据库中没有再到 Redis 中读,如果 Redis 中也没有就是真的没有

3、淘宝出的 canal

分库、分表

分库:将一个数据库分成多个数据库。

分表:将一张表分成多张表。

分库

当网站的访问量非常大时,我们为了提高数据的性能,我们需要将数据库根据业务逻辑拆分成多个库,然后就可以放到不同的集群上:

在分库之后要尽量避免跨库操作,所以我们在分库时,应该把需要连表操作的表放到一个库中,比如订单表和订单商品表。如果实在需要跨库联表操作时,我们就得使用程序拆分 SQL 语句分别查询。

分表

我们在项目中应该避免出现 大表

当一个表非常大的时,对这个表进行的操作都将消耗大量的时间,操作这样的表简直就是恶梦!

什么样的表算大表呢?

一般的标准是:

1、表中的记录数超过 2千万

2、数据文件超过 10 G

这个没有统一的标准,不同的表结构,不同的硬件对大表的定义都不同,所以要灵活定义。

为了避免出现大表的情况,我们可以使用 分表 的技术。

分表:把一张表中的数据分拆到多张表中。

分表分为横向分表纵向分表 两种:

  • 横向分表:当表中数据量比较大时,将数据保存到多个表中。

  • 纵向分表:当表中字段比较多时,就可以将常用的字段,和不常用的字段分到多个表中。

原则:常用的字段一个表(热数据),不常用的另一个表(冷数据)

中间件

在分库、分表的架构中,对于数据的操作比较复杂,比如,在添加数据时,我们要计算数据应该插入到哪个库的哪个表中,要查询数据时还要考虑跨库、跨表的查询、排序、合并等问题。如果这些工作都由我们自己编码来实现,那么难度是非常大的。这时我们可以使用一些中间件来帮助我们简化开发。

常用的中间件有:

1、MyCat

2、OneProxy

3、ProxySQL

4、Atlas

[mark] (参考自我的上课讲义) 未完待续!

 评论



本站使用 Material X 作为主题 , 总访问量为 次 。
隐藏