初识Redis
Redis的初心,最初是用来作为一个"消息中间件"的(消息队列------分布式系统下的生产者消费者模型),但是当前很少会直接使用Redis作为消息中间件使用(业界有更多更专业的消息中间件使用,如:RabbitMQ)。
现在的Redis主要被用作为数据库使用,通过之前的学习,我们已经知道有MySQL数据库了,那为什么还要有Redis数据库呢?
MySQL最大的问题在于:数据存储在硬盘中,访问速度慢。很多互联网产品对于性能的要求是很高的。而Redis是一个非关系型数据库(使用key-value的形式对数据进行存储),它是将数据存储在内存中的,而CPU访问内存的速度是比硬盘快很多的(大约3~4个数量级)。
那我们定义变量,不就是在内存中存储数据吗?
Redis是在分布式系统中才发挥自己的威力的~~如果只是单机程序,直接通过变量存储数据的方式是比Redis更优的选择。我们都知道进程具有隔离性,而进程与进程之间的通信时通过网络完成的。Redis也是如此,Redis就是基于网络可以把自己内存中的变量给别的进程甚至别的主机的进程进行使用。
那Redis有没有它的劣势呢?
与MySQL相比,Redis最大的劣势在于:存储空间是有限的。
那有没有什么办法可以把数据库搞得又大又快呢?
典型的方案:可以把Redis和MySQL结合起来使用~~
互联网中有一个"二八原则"------20%的热点数据就能满足80%的访问需求。我们可以把那20%的数据放到Redis中,再把全量的数据存储到MySQL中。这样当用户访问的是热点数据时,就能直接从Rediis中拿到数据,访问冷数据也能从MySQL中进行获取。
但是这么做就会使系统的复杂程度大大提升,而且如果数据发生修改,还涉及到Redis和MySQL之间的数据同步问题!
分布式架构的演进
单机架构
单机架构,就是只有一台服务器,这个服务器负责所有的工作。
此处以电商网站为例:
初期,我们需要利用精干的技术团队,快速将业务系统投入市场进行检验,并且可以迅速响应变化要求。但好在前期用户访问量很少,没有对我们的性能、安全等提出很高的要求,而且系统结构简单,无需专业的运维团队,所以选择单机架构是合适的。
那单机程序中,能不能把数据库服务器也去掉,光一个应用服务器即负责业务,又负责数据存储呢?
也不是不可以,但是会比较麻烦。
绝大部分公司的产品,都是这样的单机架构,现在计算机硬件的发展速度非常之快。哪怕只有一台主机,这一台主机的性能也是很高的。可以支持非常高的并发&非常大的数据存储。
但是如果业务进一步增长,一台主机难以应付的时候,就需要引入更多的主机,引入更多的硬件资源~~
一台主机的硬件资源是有上限的!这些硬件包括:CPU、内存、硬盘、网络......服务器每次收到一个请求,都需要消耗上述的资源。如果同一时刻,处理的请求多了,此时就可能会导致某个硬件资源不够用了。无论是哪个方面不够用了,都可能会导致服务器处理请求的时间变长甚,至于处理出错。
那如果我们真的遇到了这样服务器不够用的场景,怎么处理呢?
1、开源
简单粗暴,增加更多的硬件资源。一个主机上面能增加的硬件资源也是有限的,取决于主板的扩展能力。一台主机扩展到极限了,但是还不够,就只能引入多台主机了。但并不是说新的机器买来就可以直接解决问题了,也需要在软件上做出对应的调整和适配。一旦引入多台主机了,咱们的系统就可以称为"分布式系统"。
2、节流
软件上优化,这件事比较难!对程序员的水平要求比较高,需要通过性能测试,找到是哪个环节出现了瓶颈再去对症下药(比如:通过更换数据结构,加快增删改查的速率)
应用服务和数据库服务分离
还是以刚才的电商网站为例:
随着系统的上线,我们不出意外地获得了成功。市场上出现了一批忠实于我们地用户,使得系统地访问量逐步上升,逐渐逼近了硬件资源的极限,同时团队也在此期间积累了对业务流程地一批经验。面对当前地性能压力,我们需要未雨绸缪去进行系统重构、架构挑战,以提升系统的承载能力。但由于预算仍然很紧张,我们选择了将应用和数据分离的做法,可以最小代价的提升系统的承载能力。
和单机架构相比,主要的区别在于将数据库服务独立部署在同一个数据中心的其他服务器上,应用服务通过网络访问数据。
应用服务集群架构
继续以刚才的电商网站为例:
我们的系统受到了用户的欢迎,并且出现了爆款,单台应用服务器已经无法满足需求了,我们的单机应用服务器首先遇到了瓶颈,摆在我们技术团队面前的有两种方案,大家针对方案的优劣展示了热烈的讨论:
1、垂直扩展/纵向扩展。通过购买性能更优、价格更高的应用服务器。这种方案的优势在于完全不需要对系统软件做任何的调整;但是劣势也很明显:硬件性能和价格的增长关系是非线性的,意味着选择性能2倍的硬件肯能要花费4倍的价格,其次硬件性能的提升是有上限的。
2、水平扩展/横向扩展。通过调整软件架构,增加应用层硬件,将用户流量分担到不同的应用层服务器上,来提升系统的承载能力。这种方案的优势在于成本相对较低,并且提升的上限空间也很大。但劣势是带给系统更多的复杂性,需要技术团队有更丰富的经验。
经过团队的学习、调研和讨论,最终选择了水平扩展的方案来解决该问题,但这需要引入一个新的组件------负载均衡:为了解决用户流量向哪台应用服务器分发的问题,需要一个专门的系统组件做流量分发。实际中负载均衡不仅仅指的是工作在应用层的,甚至可能是在其他的网络层之中。同时,流量调度算法也有很多中的,这里简单介绍几种较为常见的:
- Round-Robin轮询算法。即非常公平地将请求依次分给不同地应用服务器。
- Weight-Round-Robin 轮询算法。为不同的服务器(比如性能不同)赋予不同的权重(weight),能者多劳。
- 一致哈希散列算法。通过计算用户的特征只(比如IP地址)得到哈希值,根据哈希结果进行分发,优点是确保来自相同用户的请求总是被分给指定的服务器。也就是我们平时遇到的专项客户经理服务。

这时候就又有问题了,负载均衡器,看起来不是承担了所有请求吗?这个东西能顶住吗?
负载均衡器,对于请求量的承担能力,要远超过应用服务器的。负载均衡前期是领导,负责分配工作;应用服务器是组员,执行任务。当然,如果请求量太大,负载均衡器也是有可能扛不住的,这时就要引入更多的负载均衡器了(引入多个机房)。
如上面讨论,增加应用服务器,确实能够处理更高的请求量,但是随之存储服务器(也就是上图的数据库服务器),要承担的请求量也就更多了!!
如何解决呢?
开源(引入更多的机器)+节流(门槛高,更复杂)。
读写分离
上面,我们把用户的请求通过负载均衡之后,可以并行处理了,并且可以随着业务的增长,可以动态扩张服务器的数量来缓解压力。但是现在的架构里,无法扩展多少台服务器,这些请求最终都会从数据库读写数据,到一定程度之后,数据的压力会成为系统承载能力的瓶颈点。我们可以想扩展应用服务器一样扩展数据库服务器吗?答案是否定的,因为数据库服务有其特殊性:如果将数据分散到各台服务器之后,数据的一致性将无法得到保障。所谓数据的一致性, 此处是指:针对同⼀个系统,无论何时何地,我们都应该看到⼀个始终维持统⼀的数据。想象⼀下, 银行管理的账户金额,如果收到⼀笔转账之后,⼀份数据库的数据修改了,但另外的数据库没有修改,则用户得到的存款金额将是错误的。
我们的解决办法是这样的,保留一个主要的数据库作为写入数据库,其他数据库作为从属数据库,从库的所有数据全部来自主库的数据,经过同步后,从库可以维护着于主库一致的数据,然后为了分担数据库的压力,我们可以将写数据请求全部交给主库处理,但读请求分散到各个库中。由于大部分的系统中,读写请求都是不成比例的,例如100次读1次写,所以只要将读请求由各个从库分担之后,数据库的压力就没有那么大了。当然这个过程不说无代价的,主库到从库的数据同步其实是有成本的,这个问题我们暂时不做进一步讨论。
ps:在多个从存储服务器之前也可以加入负载均衡,如果主存储服务器也有多个,那么也可以添加负载均衡。
引入缓存 ------ 冷热分离架构
随着访问量继续增加,发现业务中的一些数据的读取频率远大于其他数据的读取频率。我们把这部分数据称为热点数据,与之相对应的是冷数据。而数据库有个天然的问题:响应速度非常慢。针对热数据,为了提升其读取的响应时间,可以增加本地缓存,并在外部增加分布式缓存,缓存热门商品信息或热门商品的html页面等。通过缓存能把绝大多数请求在读写数据库前拦截掉,大大降低数据库压力。其中涉及的技术包括:使用memcached作为本地缓存,使用Redis作为分布式缓存,还会涉及缓存一致性、缓存穿透/击穿、缓存雪崩、热点数据集中失效等问题。
那么引入缓存服务器有没有什么代价呢?
缓存服务器的空间比较小,无法存储全量数据。
分库分表
随着业务的数据量增大,大量的数据存储在同一个库中已经有些力不从心了,所以可以按照业务,将数据分别存储。比如针对评论数据,可按照商品ID进行hash,路由到对应的表中存储;针对支付记录,可以按照小时创建表,每个小时继续拆分为小表,使用用户ID或记录编号来路由数据。只要实时操作的数据量足够小,请求能够足够均匀地分发到多台服务器上的小标,那数据库就能通过水平扩展的方式来提高性能。但是这种做法显著增加了数据库运维的难度,对DBA的要求较高。数据库设计到这种结构时,已经可以称为分布式数据库,但是这只是一个逻辑数据库整体,数据库里不同的组成部分是由不同的组件单独实现的。
微服务架构
之前的应用服务器,一个服务器程序里面做了很多的业务,这就可能会导致这一个服务器的代码变得越来越复杂~~
为了更方便代码的维护,就可以把这样的一个复杂的服务器,拆分成更多的,功能更单一,但是更小的服务器(微服务)。
注意:**微服务本质上是在解决"人"的问题~~**当应用服务器复杂了,势必就需要更多的人来维护了。当人多了,就需要配套地管理,把这些人组织好~~划分组织结构,分成多个组,每个组分配领导进行管理~~按照功能,拆分成多组微服务,就可以有利于上述人员的组织结构分配了~~
那啥时候会涉及到"人"的问题呢?=》 大厂
如果是小公司,就两三个开发~~此时搞微服务就没有太大必要了。
那引入微服务,解决了人的问题,付出的代价又是什么呢?
1、系统性能的下降~~(要想保证性能不下降太多,只能引入更多的机器,更多的硬件资源)。
拆出来更多的服务,多个功能之间更依赖网络通信。网络通信的速度很可能是比硬盘还慢的!!!
2、系统的复杂程度提高,可用性受到影响~~
服务器更多了,出现问题的概率就更大了。这就需要一系列的手段,来保证系统的可用性~~(更丰富的监控报警,以及配套的运维人员)
微服务的优势:
1、解决了人的问题
2、使用微服务,可以更方便功能的复用
3、可以给不同的服务进行不同的部署
