一、认识Redis
Redis是开源的,用于存储数据的,在内存中存储数据。Redis被用作数据库,缓存,消息队列等一些作用。
在数据库的学习中,我们学习了MySQL,但是MySQL有一些大问题:其访问速度比较慢。在互联网产品中,对于性能要求是很高的。因为Redis是存储在内存中,其速度比较快,也是可以作为数据库来进行使用的,但是其最大的劣势是:存储空间是有限的!
因此,为了达到即快又大的要求,我们需要将Redis和MySQL结合使用。Redis可以作为缓存,存储一些热点数据,可以满足大部分的访问需求。“二八原则”:20%的热点数据能满足80%的访问需求。系统的复杂程序大大提升了,而且,如果数据发生修改,还涉及到Redis和MySQL之间的数据同步问题。
Redis的初心就是用来作为一个“消息中间”的消息队列,但是在分布式系统下的生产者消费者模型,当前很少会直接使用Redis作为消息中间件。
Redis是在分布式系统中,才能发挥威力的~如果只是单机程序,直接通过变量存储数据的方式是比使用Redis更优的选择。 (进程之间具有隔离性,进程间通信==>网络,Redis就是基于网络,可以把自己的内存中的变量给别的进程,甚至别的主机进程进行使用)
二、分布式架构演进的一些概念
2.1 常见的概念
在正式引入架构演进之前,为了避免读者对架构中的概念完全不了解导致低效沟通,优先对其中一些比较重要的概念做前置介绍:
2.1.1 基本概念
应用(Application)/系统(System)
为了完成一整套服务的一个程序或者一组相互配合的程序群。
模块(Module)/组件(Component)
当应用比较复杂时,为了分离职责,将其中具有清晰职责的,内聚性强的部分,抽象出概念,便于理解。
分布式(Distributed)
系统中的多个模块被部署于不同的服务器上,即可以将该系统成为分布式系统。比如:Web服务器与数据库分别工作在不同的服务器上,或者多台Web服务器被分别部署在不同的服务器上。
集群(Cluster)
被部署于多台服务器上的,为了实现特定目标的一个/组特定的组件,整个整体被称为集群。比如:多个MySQL工作在不同的服务器上,共同提供数据库服务目标,可以被称为一组数据库集群。
分布式 VS 集群
通常不用太严格区分两者的细微概念,分布式强调的是物理形态,即工作在不同服务器上并且通过网络通信配合完成任务;而集群更在意逻辑形态,即是否为了完成特定服务目标。
主(Master)/从(Slave)
集群中,通常有一个程序需要承担更多的职责,被称为主;其他承担附属职责的被称为从。比如:MySQL集群中,只有其中一台服务器上数据库允许进行数据的写入(增/删/改),其他数据库的数据修改全部要从这台数据库同步而来,则把那台数据库称为主库,其他数据库称为从库。
中间件(Middleware)
一类提供不同应用程序用于相互通信的软件,即处于不同技术,工具和数据库之间的桥梁。
2.1.2 评价指标
可用性(Avaliability)
考察单位时间段内,系统可以正常提供服务的概率/期望。
响应时长(Response Time RT)
指用户完成输入到系统给出用户反应的时长。通常我们需要衡量的是最长响应时长,平均响应时长和中位数响应时长。这个指标原则上是越小越好,但是很多情况下由于实现的限制,需要根据实际情况具体判断。
吞吐(Throughput)vs 并发(Concurrent)
吞吐考察单位时间段内,系统可以成功处理的请求的数量。并发指系统中同一时刻支持的请求最高量。
三、分布式架构演进
3.1 单机架构
单机架构,只有一台服务器,这个服务器负责所有的工作。在前期中,我们快速将业务系统投入时市场进行校验,并且可以迅速响应变化要求。但好在前期用户访问量很少,没有对我们的性能。安全等提出很高的要求,而且系统架构简单,无需专业的运维团队,所以选择单机架构是合适的。
现在计算机硬件,发展速度非常快,哪怕只有一台主机,这一台主机的性能也是很高的,可以支持非常高的并发,非常大的数据存储。
如果业务进一步增长,用户量和数据量都水涨船高,一台主机难以应付的时候,就需要引入更多的主机,引入更多的硬件资源。一台主机的硬件资源是有上限的,包括不限于(CPU,内存,硬盘,网络)服务器每次收到一个请求,都是需要消耗上述的一些资源的。如果同一时刻,处理的请求多了,此时就可能会导致某一个硬件资源不够用了,无论是哪一个方面不够用了,都可能会导致服务器处理请求的事件变长,甚至处理出错。
如果我们真的遇到了这样的服务器不够用的场景,怎么进行处理呢??
- 开源:简单粗暴,增加更多的硬件资源(一个主机上能增加的硬件资源也是有限的,取决于主板的扩展能力,一台主机扩展到极限了,但是还是不够,只能引入多台主机了,一旦引入多台主机,系统就可以称为分布式系统)
- 节流:软件上进行优化(需要通过性能测试,找到是哪一个环节出现了瓶颈,再去对症下药)
3.2 应用数据分离架构
随着系统的上线,我们不出意外地获取了成功。市场上出现了一批忠实于我们的用户,使得系统的访问量逐步上升,逐渐逼近了硬件资源的极限。将应用和数据分离的做法,可以以最小的代价提升系统的承载能力。
和之前的架构的主要区别在于:将数据库服务独立部署在同一个数据中心的其他服务器上,应用服务通过网络访问数据。
3.3 应用服务集群架构
现在我们的系统出现了爆款,单台应用服务器已经无法满足需求了。我们的单机应用服务器首先出现了瓶颈,摆在我们技术团队面前的由两种方案:
- 垂直扩展/纵向扩展:通过购买性能更优、价格更高的应用服务器来应对更多的流量。
- 水平扩展/横向扩展:通过调整软件架构,增加应用层硬件,将用户流量分担到不同的应用层服务器上,来提升系统的承载能力。
负载均衡:为了解决用户流量向哪一台应用服务器分发的问题,需要一个专门的系统组件做流量分发。实际中负载均衡不仅仅指的是工作在应用层的,甚至可能是在其他的网络层之中。同时流量调度算法也有很多种,这里简单介绍几种较为常见的:
- Round-Robin轮询算法:即非常公平地将请求依次分给不同的应用服务器
- Weight-Round-Robin轮询算法:为了不同的服务器(比如性能不同)赋予不同的权重(weight),能者多劳
- 一致性哈希散列算法:通过计算用户的特征值(比如IP地址)得到哈希值,根据哈希结构做分发,优点是确保来自相同用户的请求总是被分给指定的服务器,也就是我们平时遇到的专项客户经理服务。
负载均衡器遇到瓶颈怎么办??
3.4 读写分离/主从分离架构
现在的架构中,无论扩展多少台服务器,这些请求最终都会从数据库读写数据,到了一定程度之后,数据的压力称为系统承载能力的瓶颈点。数据库服务有其特殊性:如果将数据分散到各台服务器之后,数据的一致性将无法得到保障。所谓数据的一致性,此处是指:针对同一系统,无论何时何地,我们都应该看到一个始终维持统一的数据。
我们采用的解决方法是这样的,保留一个主要的数据库写入数据库,其他的数据库作为从属数据库。从库的所有数据全部来自主库的数据,经过同步,从库可以维护与主库一致的数据。然后为了分担数据库的压力,我们可以将写数据请求全部交给主库处理但是读请求分散到各个从库中。
3.5 引入缓存——冷热分离架构
随着访问量继续增加,发现业务中一些数据的读取频率远大于其他数据的读取频率。我们把这部分数据称为热点数据,与之对应的是冷数据。针对热数据,为了提升其读取的响应时间,可以增加本地缓存,并在外部增加分布式缓存,通过缓存大大降低数据库压力。
3.6 垂直分库
随着业务的数据量增大,大量的数据存储在同一个库中已经显得有些力不从心了,所以可以按照业务将数据分别存储。比如:针对评论数据,可以按照商品ID进行hash,路由到对应的表中存储;针对支付记录,可按照小时创建表,每一个小时表继续拆分为小表,使用用户ID或者记录编号来路由数据。只要实时操作的表数据量足够小,请求能够足够均匀的分发到多态服务器上的小表,那数据库就能通过水平扩展的方式来提高性能。
3.7 业务拆分——微服务
随着人员增加,业务发展,我们将业务分给不同的开发团队去维护,每一个团队独立实现自己的微服务,然后互相之间对数据的直接访问进行隔离,可以利用Gateway、消息总线等技术,实现相互之间的调用关联。甚至可以把一些类似于用于管理,安全管理,数据采集等业务提成公共服务。
引入微服务,解决了人的问题,付出的代价??
- 系统的性能下降~~(想要保证性能不下降太多,只能引入更多的机器,更多的硬件资源)
- 拆出来更多的服务,多个功能之间要更依赖于网络通信,网络通信的速度比硬盘还慢,幸运的是硬件技术的发展,网卡现在有万兆网卡,读写速度已经超过了硬盘读写。
- 系统复杂程度提高,可用性收到影响~~
- 服务器更多了,出现问题的概率就更大了,这就需要一系列的手段来保证系统的可用性(丰富的监控报警,以及配套的运维人员)。
微服务的优势:
- 解决了人的问题
- 使用微服务,可以更方便于功能的复用
- 可以给不同的服务进行不同的部署