风云java_JAVAWEB之后端风云(码农翻身笔记)

数据库的危机

应用程序访问数据库需要与数据库建立连接,每一个访问都需要维持一个连接,每建立一个新的连接都需要开辟一个缓冲区(内存)用来读取以及处理数据,所以数据库能够维持的连接数总是有限的。当用户量爆发增长时,数据库的性能也就出现了瓶颈,怎么处理?

解:

增加数据库服务器的内存,开辟更多的连接(治标不治本,内存的占用还是会到达瓶颈)

将保存数据的机械硬盘换成SSD,提高每个连接的处理速度(SSD的成本太高,无法大规模使用)

在应用程序与数据库之间增加一个中间层(缓存),根据局部性原理,将数据库常用的数据放在缓存中,应用程序先访问缓存查询,没有找到就再查数据库,同时也把查到的数据放在缓存中,以便加快下一次的访问速度。

上面的处理引入了新的问题:之前的应用程序与数据库是通过JDBC接口连接的,那么新增加的缓存层该怎么实现数据的访问?

解:将缓存和应用程序放在同一台主机上,缓存直接保存应用程序中的对象。

随着用户量的继续增大,应用程序这台主机也处理不过来,罢工了,怎么办?

解:拆分:web服务器独用一台主机,应用程序N台主机,缓存一台主机,数据库一台主机

813ac262bad235c5a1b278827f265f06.png

上面的所引入的新问题:缓存和应用程序不在同一台主机上,怎样保存数据到缓存?

解:Reids(高效的键值存储数据库),将java对象转成json格式通过jedis客服端保存到redis服务器

e68b5d355e9a7c6fd3843ee8efecb3d4.png

随着用户量的继续增大,缓存服务器也扛不住了,怎么办?

解:多增加几台缓存服务器(质量不够,数量来凑)

05cb9a337c24fb4719945d3555e50730.png

上面的解引入新的问题:

这么多缓存服务器,每个 Redis 存的数据都不一样,对于应用程序来说,每次向 Redis 中存放数据的时候,到底选哪个?是存到 1 号缓存服务器,还是 2 号、 3 号?

假设已经存到了 1 号Redis,等到取数据的时候,还得去 1 号 Redis 找,要不然都找不到。

数据存储也要尽可能均匀,别让 1号、 2 号缓存服务器由于存储太多而“撑死”,而 3 号缓存因为没有数据而“饿死”。

解:

余数算法:对于用户要存储的(key,value),计算key的整数Hash值,用Hash值对缓存服务器数目求余数,对在余数号服务器进行存储。要取数的时候也用同样的方式找到那台服务器进行取数。

3238253c69f34f4f5eb1197d6c73cc07.png

但是余数算法面对一个新问题时就会导致大量缓存失效:在系统运行时动态的增减缓存服务器,因为服务器的数目变了。

一致性Hash算法

假设有一个圆,在上面映射2^32-1个点;

根据服务器的IP值,用Hash函数求出一个整数值映射到圆上相应的点上;

715a0913b20f7d870bbeb47215963971.png

将要存储的(key,value)的key值,同样用Hash函数取整数,映射到圆上,再顺时针找到遇见的第一个服务器,就是其存储服务器;当然,取数的时候用同样的方式找到服务器

ab26c722b5b68b5f7ed237f37b03cf14.png

当遇到增加一台服务器时,失效的只有两台服务器之间的缓存数据;

29e3b0f4302f0ad6aca3a9132a24c279.png

但是这样会导致如果服务器分布不均匀,那么就会出现某些服务器负载过高的情况(key值的映射概率问题)。

解决措施:我们需要足够多的服务器来让服务器更均匀的分布在圆上(当服务器数量越多时,出现大的不均匀的概率越小),但实际上不可能有太多的服务器,并且服务器的数量也不定。所以我们可以抽象出许多虚拟服务器(将一台服务器映射出N台虚拟服务器),再把这些虚拟服务器映射到圆上。

a54c98b592b8cb67d22855bd4cbfe27b.png

Hash槽算法

假设设定16384个槽,每个服务器均匀分管部分数目的槽;

a2a0954bb566c01e2ac371cac5a6368e.png

将key值用CRC16算法(跟Hash函数原理一样的)产生一个整数映射到槽上,进行存储。

acc9e03abacaf16bcd57bc9bc26e069f.png

当新增一个服务器时,将其它服务器所管理的槽各自分出一些交给新的服务器管理,以保证均匀性。

当根据一个key值查找数据时,可以向任一服务器发出请求,如果没有就重定向到其它的服务器,直到查到为止(这一块涉及到redis之间的通信,也叫redis集群)

集群中的故障转移问题

当涉及到集群时,就能够对一个老问题(数据安全问题)有了比较好的解决方案。原理就是当一台服务器挂掉之后,选一台备份服务器顶上。示例如下:将16384个Hash槽由两组服务器管理(当然也可以是多组服务器),每组服务器由一个master节点N个salve节点组成,其中master节点负责处理查询请求,salve节点负责同步数据进行备份。每一个节点都是一台独立的主机,甚至主从节点如果有条件的话应该分布在不同的机房,以应对有可能整个机房全部挂掉的风险(一般是电力风险),当master节点挂掉之后,在备份组里面选一台salve节点顶上。当然这一块实现起来就涉及到Redis集群的通信问题,服务器在运行时的动态增减问题,数据的备份与故障转移等问题。

2a2c92ae61b407f14927b1676c4e378b.png

Nginx高可用

Nginx是负责处理http请求的web服务器,当访问量达到一定程度时,服务器挂掉怎么办?(也叫单点故障)

解:用两台服务器,一主一从,对外只提供一个IP,当主服务器挂掉后从服务器顶上,具体的实现可以用Keepalived等类似的软件。

d869b2a4f9ce95e956c9cae8c5ce26b9.png

tomcat高可用

tomcat是负责逻辑处理的应用服务器,当处理量达到一定程度时,服务器挂掉怎么办?

解:用多台服务器协同处理,为了保证负载均衡,Nginx需要将请求均匀的转发到tomcat服务器上;

引入的新问题:tomcat是需要保存服务状态的,如果一台服务器在处理用户的过程中挂掉了,那么请求就会转移到其它服务器,但是其它服务器又没有该用户的状态信息,这又该如何处理?

解:

各台应用服务器之间进行通信交流,以保证session在各台服务器时刻保持一致(通信成本太高,效率低)

把session集中保存在数据库中,每台应用服务器都能访问查询(数据库的处理速度太慢)

把session集中保存在Redis缓存中

e9fc2dcea36ccf9d84e1a63a9399781c.png

数据库高可用

数据库服务器是最重要的,所有用户的数据都能够永久性的在数据库中固化下来,但是在在一个分布式的环境中,保持数据的强一致性是非常难的,稍有不慎就会乱套,特别是金融数据。怎么处理这个问题?

解:数据库有个特点就是统计出来的结果,读数据的次数远远高于写数据的次数。所以可以设计一主多从的架构,一台master数据库主要负责写数据(当然也可以读数据),多台从机负责读数据;

f851a16a10654c1241ff570c59340e47.png

优点:

能够极大的缓解程序对X锁与S锁的争用(这块后面再深挖)

能够平衡多数据库的负责均衡,提高可用性

在主机挂掉之后,从机成为主机顶上

缺点:

程序对数据库的访问就变得有些麻烦,怎样分离读写操作去访问不同的服务器?

a3f3288ff8d4096f7e91ee38bcb73ccf.png

对该缺点的解决措施:再抽象出一个中间层来处理双方产生的矛盾,如mysql proxy(这块后面深挖)

705fd929836ade748c97547c9a1f37f7.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值