浅谈web网站架构演变过程

来源:互联网 发布:找出出现最多的词 算法 编辑:程序博客网 时间:2024/06/06 09:44

<div><strong>转载于:</strong><a>http://blog.csdn.net/qiaqia609/article/details/50809383</a></div>

<div id="article_content" class="article_content tracking-ad" data-mod="popu_307" data-dsm="post">


<h1 style="font-size:17px; font-family:微软雅黑,宋体,Arial; background-color:rgb(109,164,125); color:rgb(255,255,255); line-height:25px; padding:5px 0px 5px 20px; margin:15px 0px!important"><a name="t0" target="_blank"></a>
前言</h1>
<div><br>
</div>
<div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">我们以<span style="background-color:rgb(255,255,153)">javaweb</span>为例,来搭建一个简单的电商系统,看看这个系统可以如何一步步演变。</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px; margin-left:30px">&nbsp;</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">  该系统具备的功能:</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">&nbsp;</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">
<ul style="list-style:none; margin:0px 0px 0px 30px; padding:0px">
<li style="list-style-type:disc">用户模块:用户注册和管理</li><li style="list-style-type:disc">商品模块:商品展示和管理</li><li style="list-style-type:disc">交易模块:创建交易和管理</li></ul>
<p style="margin:10px auto; line-height:24px">&nbsp;<span style="line-height:1.5">&nbsp;</span></p>
</div>
<h1 style="font-size:17px; font-family:微软雅黑,宋体,Arial; background-color:rgb(109,164,125); color:rgb(255,255,255); line-height:25px; padding:5px 0px 5px 20px; margin:15px 0px!important"><a name="t1" target="_blank"></a>
阶段一、单机构建网站</h1>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">  网站的初期,我们经常会在单机上跑我们所有的程序和软件。此时我们使用一个容器,如<span style="background-color:rgb(255,255,153)">tomcat</span>、<span style="background-color:rgb(255,255,153)">jetty</span>、<span style="background-color:rgb(255,255,153)">jboos</span>,然后直接使用<span style="background-color:rgb(255,255,153)">JSP/servlet</span>技术,或者使用一些开源的框架如<span style="background-color:rgb(255,255,153)">maven<span style="background-color:rgb(255,255,255)">+</span>spring<span style="background-color:rgb(255,255,255)">+</span>struct<span style="background-color:rgb(255,255,255)">+</span>hibernate</span>、<span style="background-color:rgb(255,255,153)"><span style="background-color:rgb(255,255,255)">maven+spring+</span>springmvc<span style="background-color:rgb(255,255,255)">+</span>mybatis</span>;最后再选择一个数据库管理系统来存储数据,如<span style="background-color:rgb(255,255,153)">mysql</span>、<span style="background-color:rgb(255,255,153)">sqlserver</span>、<span style="background-color:rgb(255,255,153)">oracle</span>,然后通过JDBC进行数据库的连接和操作。</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">  把以上的所有软件都装载同一台机器上,应用跑起来了,也算是一个小系统了。此时系统结果如下:</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">&nbsp;</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px"><img src="http://images2015.cnblogs.com/blog/657628/201602/657628-20160227230250549-838360069.png" alt="" style="border:0px; max-width:900px; display:block; margin-left:auto; margin-right:auto"></div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">&nbsp;</div>
<h1 style="font-size:17px; font-family:微软雅黑,宋体,Arial; background-color:rgb(109,164,125); color:rgb(255,255,255); line-height:25px; padding:5px 0px 5px 20px; margin:15px 0px!important"><a name="t2" target="_blank"></a>
阶段二、应用服务器与数据库分离</h1>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">  随着网站的上线,访问量逐步上升,服务器的负载慢慢提高,在服务器还没有超载的时候,我们应该就要做好准备,提升网站的负载能力。假如我们代码层面已难以优化,在不提高单台机器的性能的情况下,增加机器是一个不错的方式,不仅可以有效地提高系统的负载能力,而且性价比高。</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">  增加的机器用来做什么呢?此时我们可以把数据库,web服务器拆分开来,这样不仅提高了单台机器的负载能力,也提高了容灾能力。</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">  应用服务器与数据库分开后的架构如下图所示:</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px"><img src="http://images2015.cnblogs.com/blog/657628/201602/657628-20160227230551065-780123340.png" alt="" style="border:0px; max-width:900px; display:block; margin-left:auto; margin-right:auto"></div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">&nbsp;</div>
<h1 style="font-size:17px; font-family:微软雅黑,宋体,Arial; background-color:rgb(109,164,125); color:rgb(255,255,255); line-height:25px; padding:5px 0px 5px 20px; margin:15px 0px!important"><a name="t3" target="_blank"></a>
阶段三、应用服务器集群</h1>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">  随着访问量继续增加,单台应用服务器已经无法满足需求了。在假设数据库服务器没有压力的情况下,我们可以把应用服务器从一台变成了两台甚至多台,把用户的请求分散到不同的服务器中,从而提高负载能力。多台应用服务器之间没有直接的交互,他们都是依赖数据库各自对外提供服务。著名的做故障切换的软件有<span style="background-color:rgb(255,255,153)">keepalived<span style="background-color:rgb(255,255,255)">,keepalived是一个类似于layer3、4、7交换机制的软件,他不是某个具体软件故障切换的专属品,而是可以适用于各种软件的一款产品。keepalived配合上<span style="background-color:rgb(255,255,153)">ipvsadm</span>又可以做负载均衡,可谓是神器。</span></span></div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">  我们以增加了一台应用服务器为例,增加后的系统结构图如下:</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">&nbsp;</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px"><img src="http://images2015.cnblogs.com/blog/657628/201602/657628-20160227231027549-1406889699.png" alt="" style="border:0px; max-width:900px; display:block; margin-left:auto; margin-right:auto"></div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">  <strong>系统演变到这里,将会出现下面四个问题</strong>:</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">
<ol style="padding-left:40px">
<li style="list-style-type:decimal">用户的请求由谁来转发到到具体的应用服务器</li><li style="list-style-type:decimal">有什么转发的算法</li><li style="list-style-type:decimal">应用服务器如何返回用户的请求</li><li style="list-style-type:decimal">用户如果每次访问到的服务器不一样,那么如何维护session的一致性</li></ol>
<p style="margin:10px auto; line-height:24px">&nbsp;</p>
<p style="margin:10px auto; line-height:24px">  <strong>我们来看看解决问题的方案</strong>:</p>
<p style="margin:10px auto; line-height:24px">&nbsp;</p>
<p style="margin:10px auto; line-height:24px">  1、<span style="text-decoration:underline">第一个问题即是负载均衡的问题,一般有5种解决方案</span>:</p>
<p style="margin:10px auto; line-height:24px">    1、<strong>http重定向</strong>。HTTP重定向就是应用层的请求转发。用户的请求其实已经到了HTTP重定向负载均衡服务器,服务器根据<a href="http://lib.csdn.net/base/datastructure" class="replace_word" title="算法与数据结构知识库" target="_blank" style="color:#df3434; font-weight:bold;">算法</a>要求用户重定向,用户收到重定向请求后,再次请求真正的集群</p>
<p style="margin:10px auto; line-height:24px">      优点:简单。</p>
<p style="margin:10px auto; line-height:24px">      缺点:性能较差。</p>
<p style="margin:10px auto; line-height:24px">    2、<strong>DNS域名解析负载均衡</strong>。DNS域名解析负载均衡就是在用户请求<span style="background-color:rgb(255,255,153)">DNS</span>服务器,获取域名对应的IP地址时,DNS服务器直接给出负载均衡后的服务器IP。</p>
<p style="margin:10px auto; line-height:24px">      优点:交给DNS,不用我们去维护负载均衡服务器。</p>
<p style="margin:10px auto; line-height:24px">      缺点:当一个应用服务器挂了,不能及时通知DNS,而且DNS负载均衡的控制权在域名服务商那里,网站无法做更多的改善和更强大的管理。</p>
<p style="margin:10px auto; line-height:24px">    3、<strong>反向代理服务器</strong>。在用户的请求到达反向代理服务器时(已经到达网站机房),由反向代理服务器根据算法转发到具体的服务器。常用的<span style="background-color:rgb(255,255,153)">apache</span>,<span style="background-color:rgb(255,255,153)">nginx</span>都可以充当反向代理服务器。</p>
<p style="margin:10px auto; line-height:24px">      优点:部署简单。</p>
<p style="margin:10px auto; line-height:24px">      缺点:代理服务器可能成为性能的瓶颈,特别是一次上传大文件。</p>
<p style="margin:10px auto; line-height:24px">    4、<strong>IP层负载均衡</strong>。在请求到达负载均衡器后,负载均衡器通过修改请求的目的IP地址,从而实现请求的转发,做到负载均衡。</p>
<p style="margin:10px auto; line-height:24px">      优点:性能更好。</p>
<p style="margin:10px auto; line-height:24px">      缺点:负载均衡器的宽带成为瓶颈。</p>
<p style="margin:10px auto; line-height:24px">    5、<strong>数据链路层负载均衡</strong>。在请求到达负载均衡器后,负载均衡器通过修改请求的mac地址,从而做到负载均衡,与IP负载均衡不一样的是,当请求访问完服务器之后,直接返回客户。而无需再经过负载均衡器。</p>
<p style="margin:10px auto; line-height:24px">&nbsp;</p>
<p style="margin:10px auto; line-height:24px">  2、<span style="text-decoration:underline">第</span><span style="text-decoration:underline">二个问题即是集群调度算法问题,常见的调度算法有10种</span>。</p>
<p style="margin:10px auto; line-height:24px">    1、<strong>rr 轮询调度算法</strong>。顾名思义,轮询分发请求。</p>
<p style="margin:10px auto; line-height:24px">      优点:实现简单</p>
<p style="margin:10px auto; line-height:24px">      缺点:不考虑每台服务器的处理能力</p>
<p style="margin:10px auto; line-height:24px">    2、<strong>wrr 加权调度算法</strong>。我们给每个服务器设置权值weight,负载均衡调度器根据权值调度服务器,服务器被调用的次数跟权值成正比。</p>
<p style="margin:10px auto; line-height:24px">      优点:考虑了服务器处理能力的不同</p>
<p style="margin:10px auto; line-height:24px">    3、<strong>sh 原地址散列</strong>:提取用户IP,根据散列函数得出一个key,再根据静态映射表,查处对应的value,即目标服务器IP。过目标机器超负荷,则返回空。</p>
<p style="margin:10px auto; line-height:24px">    4、<strong>dh 目标地址散列</strong>:同上,只是现在提取的是目标地址的IP来做哈希。</p>
<p style="margin:10px auto; line-height:24px">      优点:以上两种算法的都能实现同一个用户访问同一个服务器。</p>
<p style="margin:10px auto; line-height:24px">    5、<strong>lc 最少连接</strong>。优先把请求转发给连接数少的服务器。</p>
<p style="margin:10px auto; line-height:24px">      优点:使得集群中各个服务器的负载更加均匀。</p>
<p style="margin:10px auto; line-height:24px">    6、<strong>wlc 加权最少连接</strong>。在lc的基础上,为每台服务器加上权值。算法为:(活动连接数*256+非活动连接数)÷权重 ,计算出来的值小的服务器优先被选择。</p>
<p style="margin:10px auto; line-height:24px">      优点:可以根据服务器的能力分配请求。</p>
<p style="margin:10px auto; line-height:24px">    7、<strong>sed 最短期望延迟</strong>。其实sed跟wlc类似,区别是不考虑非活动连接数。算法为:(活动连接数+1)*256÷权重,同样计算出来的值小的服务器优先被选择。</p>
<p style="margin:10px auto; line-height:24px">    8、<strong>nq 永不排队</strong>。改进的sed算法。我们想一下什么情况下才能“永不排队”,那就是服务器的连接数为0的时候,那么假如有服务器连接数为0,均衡器直接把请求转发给它,无需经过sed的计算。</p>
<p style="margin:10px auto; line-height:24px">    9、<strong>LBLC 基于局部性的最少连接</strong>。均衡器根据请求的目的IP地址,找出该IP地址最近被使用的服务器,把请求转发之,若该服务器超载,最采用最少连接数算法。</p>
<p style="margin:10px auto; line-height:24px">    10、<strong>LBLCR 带复制的基于局部性的最少连接</strong>。均衡器根据请求的目的IP地址,找出该IP地址最近使用的“服务器<strong>组</strong>”,注意,并不是具体某个服务器,然后采用最少连接数从该组中挑出具体的某台服务器出来,把请求转发之。若该服务器超载,那么根据最少连接数算法,在集群的<strong>非</strong>本服务器组的服务器中,找出一台服务器出来,加入本服务器组,然后把请求转发之。</p>
<p style="margin:10px auto; line-height:24px">&nbsp;</p>
<p style="margin:10px auto; line-height:24px">  3、<span style="text-decoration:underline">第三个问题是集群模式问题,一般3种解决方案</span>:</p>
<p style="margin:10px auto; line-height:24px">    1、<strong>NAT</strong>:负载均衡器接收用户的请求,转发给具体服务器,服务器处理完请求返回给均衡器,均衡器再重新返回给用户。</p>
<p style="margin:10px auto; line-height:24px">    2、<strong>DR</strong>:负载均衡器接收用户的请求,转发给具体服务器,服务器出来玩请求后直接返回给用户。需要系统支持IP Tunneling协议,难以跨平台。</p>
<p style="margin:10px auto; line-height:24px">    3、<strong>TUN</strong>:同上,但无需IP Tunneling协议,跨平台性好,大部分系统都可以支持。</p>
<p style="margin:10px auto; line-height:24px">&nbsp;</p>
<p style="margin:10px auto; line-height:24px">  4、<span style="text-decoration:underline">第四个问题是session问题,一般有4种解决方案</span>:</p>
<p style="margin:10px auto; line-height:24px">    1、<strong>Session Sticky</strong>。session sticky就是把同一个用户在某一个会话中的请求,都分配到固定的某一台服务器中,这样我们就不需要解决跨服务器的session问题了,常见的算法有ip_hash法,即上面提到的两种散列算法。</p>
<p style="margin:10px auto; line-height:24px">      优点:实现简单。</p>
<p style="margin:10px auto; line-height:24px">      缺点:应用服务器重启则session消失。</p>
<p style="margin:10px auto; line-height:24px">    2、<strong>Session Replication</strong>。session replication就是在集群中复制session,使得每个服务器都保存有全部用户的session数据。</p>
<p style="margin:10px auto; line-height:24px">      优点:减轻负载均衡服务器的压力,不需要要实现ip_hasp算法来转发请求。</p>
<p style="margin:10px auto; line-height:24px">      缺点:复制时宽带开销大,访问量大的话session占用内存大且浪费。</p>
<p style="margin:10px auto; line-height:24px">    3、<strong>Session数据集中存储</strong>:session数据集中存储就是利用<a href="http://lib.csdn.net/base/mysql" class="replace_word" title="MySQL知识库" target="_blank" style="color:#df3434; font-weight:bold;">数据库</a>来存储session数据,实现了session和应用服务器的解耦。</p>
<p style="margin:10px auto; line-height:24px">      优点:相比session replication的方案,集群间对于宽带和内存的压力减少了很多。</p>
<p style="margin:10px auto; line-height:24px">      缺点:需要维护存储session的数据库。</p>
<p style="margin:10px auto; line-height:24px">    4、<strong>Cookie Base</strong>:cookie base就是把session存在cookie中,有浏览器来告诉应用服务器我的session是什么,同样实现了session和应用服务器的解耦。</p>
<p style="margin:10px auto; line-height:24px">      优点:实现简单,基本免维护。</p>
<p style="margin:10px auto; line-height:24px">      缺点:cookie长度限制,安全性低,宽带消耗。</p>
<p style="margin:10px auto; line-height:24px">  </p>
<p style="margin:10px auto; line-height:24px">  <strong>值得一提的是</strong>:</p>
<p style="margin:10px auto; line-height:24px">  <span style="background-color:rgb(255,255,153)">nginx</span>目前支持的负载均衡算法有wrr、sh(支持一致性哈希)、fair(本人觉得可以归结为lc)。但nginx作为均衡器的话,还可以一同作为静态资源服务器。</p>
<p style="margin:10px auto; line-height:24px">  <span style="background-color:rgb(255,255,153)">keepalived<span style="background-color:rgb(255,255,255)">+</span>ipvsadm</span>比较强大,目前支持的算法有:rr、wrr、lc、wlc、lblc、sh、dh</p>
<p style="margin:10px auto; line-height:24px">  <span style="background-color:rgb(255,255,153)">keepalived</span>支持集群模式有:NAT、DR、TUN</p>
<p style="margin:10px auto; line-height:24px">  <span style="background-color:rgb(255,255,153)">nginx</span>本身并没有提供session同步的解决方案,而<span style="background-color:rgb(255,255,153)">apache</span>则提供了session共享的支持。</p>
<p style="margin:10px auto; line-height:24px">&nbsp;</p>
<p style="margin:10px auto; line-height:24px">  好了,解决了以上的问题之后,<strong>系统的结构如下</strong>:</p>
<p style="margin:10px auto; line-height:24px"><img src="http://images2015.cnblogs.com/blog/657628/201602/657628-20160227233055237-1797878801.png" alt="" style="border:0px; max-width:900px; margin:10px auto; display:block"></p>
<p style="margin:10px auto; line-height:24px">&nbsp;</p>
</div>
<h1 style="font-size:17px; font-family:微软雅黑,宋体,Arial; background-color:rgb(109,164,125); color:rgb(255,255,255); line-height:25px; padding:5px 0px 5px 20px; margin:15px 0px!important"><a name="t4" target="_blank"></a>
阶段四、数据库读写分离化</h1>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">  上面我们总是假设数据库负载正常,但随着访问量的的提高,数据库的负载也在慢慢增大。那么可能有人马上就想到跟应用服务器一样,把数据库一份为二再负载均衡即可。但对于数据库来说,并没有那么简单。假如我们简单的把数据库一分为二,然后对于数据库的请求,分别负载到A机器和B机器,那么显而易见会造成两台数据库数据不统一的问题。那么对于这种情况,我们可以先考虑使用读写分离的方式。</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">  读写分离后的数据库系统结构如下:</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px"><img src="http://images2015.cnblogs.com/blog/657628/201602/657628-20160227233231221-879714199.png" alt="" style="border:0px; max-width:900px; display:block; margin-left:auto; margin-right:auto"></div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">
<div>&nbsp;  <strong>这个结构变化后也会带来两个问题</strong>:</div>
<div>
<ol style="padding-left:40px">
<li style="list-style-type:decimal">主从数据库之间数据同步问题</li><li style="list-style-type:decimal">应用对于数据源的选择问题</li></ol>
<div><strong>  解决问题方案</strong>:</div>
<div>
<ol style="padding-left:40px">
<li style="list-style-type:decimal">我们可以使用MYSQL自带的<span style="background-color:rgb(255,255,153)">master+slave</span>的方式实现主从复制。</li><li style="list-style-type:decimal">采用第三方数据库中间件,例如mycat。<span style="background-color:rgb(255,255,153)">mycat</span>是从<span style="background-color:rgb(255,255,153)">cobar</span>发展而来的,而cobar是阿里开源的数据库中间件,后来停止开发。mycat是国内比较好的mysql开源数据库分库分表中间件。</li></ol>
<p style="margin:10px auto; line-height:24px">&nbsp;</p>
</div>
</div>
</div>
<h1 style="font-size:17px; font-family:微软雅黑,宋体,Arial; background-color:rgb(109,164,125); color:rgb(255,255,255); line-height:25px; padding:5px 0px 5px 20px; margin:15px 0px!important"><a name="t5" target="_blank"></a>
阶段五、用搜索引擎缓解读库的压力</h1>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
  数据库做读库的话,常常对模糊查找力不从心,即使做了读写分离,这个问题还未能解决。以我们所举的交易网站为例,发布的商品存储在数据库中,用户最常使用的功能就是查找商品,尤其是根据商品的标题来查找对应的商品。对于这种需求,一般我们都是通过like功能来实现的,但是这种方式的代价非常大。此时我们可以使用<a href="http://lib.csdn.net/base/searchengine" class="replace_word" title="搜索引擎知识库" target="_blank" style="color:#df3434; font-weight:bold;">搜索引擎</a>的倒排索引来完成。</p>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px"><strong>  搜索引擎具有以下优点</strong>:</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">
<ul style="list-style:none; margin:0px 0px 0px 30px; padding:0px">
<li style="list-style-type:disc">它能够大大提高查询速度。</li></ul>
<p style="margin:10px auto; line-height:24px">&nbsp;</p>
</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px"><strong>  引入搜索引擎后也会带来以下的开销</strong>:</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">
<ul style="list-style:none; margin:0px 0px 0px 30px; padding:0px">
<li style="list-style-type:disc">带来大量的维护工作,我们需要自己实现索引的构建过程,设计全量/增加的构建方式来应对非实时与实时的查询需求。</li><li style="list-style-type:disc">需要维护搜索引擎集群</li></ul>
</div>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
&nbsp; &nbsp; &nbsp; &nbsp; 搜索引擎并不能替代数据库,他解决了某些场景下的“读”的问题,是否引入搜索引擎,需要综合考虑整个系统的需求。引入搜索引擎后的系统结构如下:</p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
<img src="http://images2015.cnblogs.com/blog/657628/201602/657628-20160227234313299-1097216621.png" alt="" style="border:0px; max-width:900px; margin:10px auto; display:block"></p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
&nbsp;</p>
<h1 style="font-size:17px; font-family:微软雅黑,宋体,Arial; background-color:rgb(109,164,125); color:rgb(255,255,255); line-height:25px; padding:5px 0px 5px 20px; margin:15px 0px!important"><a name="t6" target="_blank"></a>
阶段六、用缓存缓解读库的压力</h1>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
  1、<strong>后台应用层和数据库层的缓存</strong></p>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">  随着访问量的增加,逐渐出现了许多用户访问同一部分内容的情况,对于这些比较热门的内容,没必要每次都从数据库读取。我们可以使用缓存技术,例如可以使用google的开源缓存技术<span style="background-color:rgb(255,255,153)">guava或<span style="background-color:rgb(255,255,255)">者使用</span>memcacahe</span>作为应用层的缓存,也可以使用<span style="background-color:rgb(255,255,153)">redis</span>作为数据库层的缓存。</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">  另外,在某些场景下,关系型数据库并不是很适合,例如我想做一个“每日输入密码错误次数限制”的功能,思路大概是在用户登录时,如果登录错误,则记录下该用户的IP和错误次数,那么这个数据要放在哪里呢?假如放在内存中,那么显然会占用太大的内容;假如放在关系型数据库中,那么既要建立数据库表,还要简历对应的java bean,还要写SQL等等。而分析一下我们要存储的数据,无非就是类似{ip:errorNumber}这样的key:value数据。对于这种数据,我们可以用NOSQL数据库来代替传统的关系型数据库。</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">
<div>&nbsp;</div>
<div>  2、<strong>页面缓存</strong></div>
<div>  除了数据缓存,还有页面缓存。比如使用<span style="background-color:rgb(255,255,153)">HTML5</span>的<span style="background-color:rgb(255,255,153)">localstroage</span>或者<span style="background-color:rgb(255,255,153)">cookie</span>。</div>
</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">&nbsp;</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">
<div><strong>  优点</strong>:</div>
<div>
<ul style="list-style:none; margin:0px 0px 0px 30px; padding:0px">
<li style="list-style-type:disc">减轻数据库的压力</li><li style="list-style-type:disc">大幅度提高访问速度</li></ul>
<p style="margin:10px auto; line-height:24px">&nbsp;</p>
<div><strong>  缺点</strong>:</div>
</div>
<div>
<ul style="list-style:none; margin:0px 0px 0px 30px; padding:0px">
<li style="list-style-type:disc">需要维护缓存服务器</li><li style="list-style-type:disc">提高了编码的复杂性</li></ul>
<p style="margin:10px auto; line-height:24px">&nbsp;</p>
<p style="margin:10px auto; line-height:24px">  <strong>值得一提的是</strong>:</p>
<p style="margin:10px auto; line-height:24px">  缓存集群的调度算法不同与上面提到的应用服务器和数据库。最好采用“一致性哈希算法”,这样才能提高命中率。这个就不展开讲了,有兴趣的可以查阅相关资料。</p>
<p style="margin:10px auto; line-height:24px">&nbsp;</p>
</div>
<div><span style="line-height:1.5">  加入缓存后的结构</span><span style="line-height:1.5">:</span></div>
<div><img src="http://images2015.cnblogs.com/blog/657628/201602/657628-20160227234748846-1053422543.png" alt="" style="border:0px; max-width:900px; display:block; margin-left:auto; margin-right:auto"></div>
<div>&nbsp;</div>
<div>&nbsp;</div>
</div>
<h1 style="font-size:17px; font-family:微软雅黑,宋体,Arial; background-color:rgb(109,164,125); color:rgb(255,255,255); line-height:25px; padding:5px 0px 5px 20px; margin:15px 0px!important"><a name="t7" target="_blank"></a>
阶段七、数据库水平拆分与垂直拆分</h1>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
  我们的网站演进到现在,交易、商品、用户的数据都还在同一个数据库中。尽管采取了增加缓存,读写分离的方式,但随着数据库的压力继续增加,数据库的瓶颈越来越突出,此时,我们可以有数据垂直拆分和水平拆分两种选择。</p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
  <strong>7.1、数据垂直拆分</strong></p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
  垂直拆分的意思是把数据库中不同的业务数据拆分道不同的数据库中,结合现在的例子,就是把交易、商品、用户的数据分开。</p>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px"><strong>  优点</strong>:</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">
<ul style="list-style:none; margin:0px 0px 0px 30px; padding:0px">
<li style="list-style-type:disc">解决了原来把所有业务放在一个数据库中的压力问题。</li><li style="list-style-type:disc">可以根据业务的特点进行更多的优化</li></ul>
<p style="margin:10px auto; line-height:24px">&nbsp;</p>
<div><strong>  缺点</strong>:</div>
<div>
<ul style="list-style:none; margin:0px 0px 0px 30px; padding:0px">
<li style="list-style-type:disc">需要维护多个数据库</li></ul>
<p style="margin:10px auto; line-height:24px">&nbsp;</p>
<div><strong>  问题</strong>:</div>
<ol style="padding-left:40px">
<li style="list-style-type:decimal">需要考虑原来跨业务的事务</li><li style="list-style-type:decimal">跨数据库的join</li></ol>
<div><strong>  解决问题方案</strong>:</div>
<div>
<ol style="padding-left:40px">
<li style="list-style-type:decimal">我们应该在应用层尽量避免跨数据库的事物,如果非要跨数据库,尽量在代码中控制。</li><li style="list-style-type:decimal">我们可以通过第三方应用来解决,如上面提到的<span style="background-color:rgb(255,255,153)">mycat</span>,mycat提供了丰富的跨库join方案,详情可参考mycat官方文档。</li></ol>
<p style="margin:10px auto; line-height:24px">  <strong>垂直拆分后的结构如下</strong>:</p>
<p style="margin:10px auto; line-height:24px"><img src="http://images2015.cnblogs.com/blog/657628/201602/657628-20160227235245346-1978991654.png" alt="" style="border:0px; max-width:900px; margin:10px auto; display:block"></p>
<p style="margin:10px auto; line-height:24px">  <strong>7.2、数据水平拆分</strong></p>
<p style="margin:10px auto; line-height:24px">  数据水平拆分就是把同一个表中的数据拆分到两个甚至多个数据库中。产生数据水平拆分的原因是某个业务的数据量或者更新量到达了单个数据库的瓶颈,这时就可以把这个表拆分到两个或更多个数据库中。</p>
<div>
<div><strong>  优点</strong>:</div>
<div>
<ul style="list-style:none; margin:0px 0px 0px 30px; padding:0px">
<li style="list-style-type:disc">如果我们能客服以上问题,那么我们将能够很好地对数据量及写入量增长的情况。</li></ul>
<p style="margin:10px auto; line-height:24px">&nbsp;</p>
</div>
</div>
<div><span style="line-height:1.5">  问题</span><span style="line-height:1.5">:</span></div>
<div>
<ol style="padding-left:40px">
<li style="list-style-type:decimal">访问用户信息的应用系统需要解决SQL路由的问题,因为现在用户信息分在了两个数据库中,需要在进行数据操作时了解需要操作的数据在哪里。</li><li style="list-style-type:decimal">主键的处理也变得不同,例如原来自增字段,现在不能简单地继续使用了。</li><li style="list-style-type:decimal">如果需要分页,就麻烦了。</li></ol>
<div><span style="line-height:1.5">  解决问题方案</span><span style="line-height:1.5">:</span></div>
<div>
<ol style="padding-left:40px">
<li style="list-style-type:decimal">我们还是可以通过可以解决第三方中间件,如<span style="background-color:rgb(255,255,153)">mycat</span>。mycat可以通过SQL解析模块对我们的SQL进行解析,再根据我们的配置,把请求转发到具体的某个数据库。</li><li style="list-style-type:decimal">我们可以通过<span style="background-color:rgb(255,255,153)">UUID</span>保证唯一或自定义ID方案来解决。</li><li style="list-style-type:decimal">mycat也提供了丰富的分页查询方案,比如先从每个数据库做分页查询,再合并数据做一次分页查询等等。</li></ol>
<p style="margin:10px auto; line-height:24px">  <strong>数据水平拆分后的结构</strong>:</p>
<p style="margin:10px auto; line-height:24px"><img src="http://images2015.cnblogs.com/blog/657628/201602/657628-20160227235433268-409249903.png" alt="" style="border:0px; max-width:900px; margin:10px auto; display:block"></p>
<p style="margin:10px auto; line-height:24px">&nbsp;</p>
</div>
</div>
</div>
</div>
</div>
<h1 style="font-size:17px; font-family:微软雅黑,宋体,Arial; background-color:rgb(109,164,125); color:rgb(255,255,255); line-height:25px; padding:5px 0px 5px 20px; margin:15px 0px!important"><a name="t8" target="_blank"></a>
阶段八、应用的拆分</h1>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
  <strong>8.1、拆分应用</strong></p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
  随着业务的发展,业务越来越多,应用越来越大。我们需要考虑如何避免让应用越来越臃肿。这就需要把应用拆开,从一个应用变为俩个甚至更多。还是以我们上面的例子,我们可以把用户、商品、交易拆分开。变成“用户、商品”和“用户,交易”两个子系统。  </p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
  拆分后的结构:</p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
<img src="http://images2015.cnblogs.com/blog/657628/201602/657628-20160227235716455-1083812456.png" alt="" style="border:0px; max-width:900px; margin:10px auto; display:block"></p>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px"><strong>  问题</strong>:</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">
<ol style="padding-left:40px">
<li style="list-style-type:decimal">这样拆分后,可能会有一些相同的代码,如用户相关的代码,商品和交易都需要用户信息,所以在两个系统中都保留差不多的操作用户信息的代码。如何保证这些代码可以复用是一个需要解决的问题。</li></ol>
<div>&nbsp;  <span style="line-height:1.5">解决问题</span><span style="line-height:1.5">:</span></div>
<div>
<ol style="padding-left:40px">
<li style="list-style-type:decimal">通过走服务化的路线来解决</li></ol>
<p style="margin:10px auto; line-height:24px">&nbsp;</p>
<p style="margin:10px auto; line-height:24px">  <strong>8.2、走服务化的道路</strong></p>
<p style="margin:10px auto; line-height:24px">  为了解决上面拆分应用后所出现的问题,我们把公共的服务拆分出来,形成一种服务化的模式,简称<span style="background-color:rgb(255,255,153)">SOA</span>。</p>
<p style="margin:10px auto; line-height:24px">  采用服务化之后的系统结构:</p>
<p style="margin:10px auto; line-height:24px; text-align:center"><img src="http://images2015.cnblogs.com/blog/657628/201602/657628-20160229163138345-658950671.png" alt="" style="border:0px; max-width:900px; margin:10px"></p>
<div>
<div><strong>  优点</strong>:</div>
<div>
<ul style="list-style:none; margin:0px 0px 0px 30px; padding:0px">
<li style="list-style-type:disc">相同的代码不会散落在不同的应用中了,这些实现放在了各个服务中心,使代码得到更好的维护。</li><li style="list-style-type:disc">我们把对数据库的交互放在了各个服务中心,让”前端“的web应用更注重与浏览器交互的工作。</li></ul>
<p style="margin:10px auto; line-height:24px">&nbsp;</p>
</div>
</div>
<div><span style="line-height:1.5">  &nbsp;问题</span><span style="line-height:1.5">:</span></div>
<div>
<ol style="padding-left:40px">
<li style="list-style-type:decimal">如何进行远程的服务调用</li></ol>
<div><span style="line-height:1.5">  &nbsp;</span><span style="line-height:1.5">解决方法</span><span style="line-height:1.5">:</span></div>
<div>
<ol style="padding-left:40px">
<li style="list-style-type:decimal">我们可以通过下面的引入消息中间件来解决</li></ol>
<p style="margin:10px auto; line-height:24px">&nbsp;</p>
</div>
</div>
</div>
</div>
<h1 style="font-size:17px; font-family:微软雅黑,宋体,Arial; background-color:rgb(109,164,125); color:rgb(255,255,255); line-height:25px; padding:5px 0px 5px 20px; margin:15px 0px!important"><a name="t9" target="_blank"></a>
阶段九、引入消息中间件</h1>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">  随着网站的继续发展,我们的系统中可能出现不同语言开发的子模块和部署在不同平台的子系统。此时我们需要一个平台来传递可靠的,与平台和语言无关的数据,并且能够把负载均衡透明化,能在调用过程中收集调用数据并分析之,推测出网站的访问增长率等等一系列需求,对于网站应该如何成长做出预测。开源消息中间件有阿里的<span style="background-color:rgb(255,255,153)">dubbo</span>,可以搭配Google开源的分布式程序协调服务<span style="background-color:rgb(255,255,153)">zookeeper</span>实现服务器的注册与发现。</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">  引入消息中间件后的结构:</div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">  <img src="http://images2015.cnblogs.com/blog/657628/201602/657628-20160228000043534-1504308364.png" alt="" style="border:0px; max-width:900px; display:block; margin-left:auto; margin-right:auto"></div>
<div style="font-family:微软雅黑,宋体,Arial; font-size:15px">&nbsp;</div>
<h1 style="font-size:17px; font-family:微软雅黑,宋体,Arial; background-color:rgb(109,164,125); color:rgb(255,255,255); line-height:25px; padding:5px 0px 5px 20px; margin:15px 0px!important"><a name="t10" target="_blank"></a>
十、总结</h1>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
  以上的演变过程只是一个例子,并不适合所有的网站,实际中网站演进过程与自身业务和不同遇到的问题有密切的关系,没有固定的模式。只有认真的分析和不断地探究,才能发现适合自己网站的<a href="http://lib.csdn.net/base/architecture" class="replace_word" title="大型网站架构知识库" target="_blank" style="color:#df3434; font-weight:bold;">架构</a>。</p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
  </p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
  下一篇,我将根据小型项目的实际情况,设计出11套具体的方案,分别对应拥有1~12机器时,如何利用这些稀少的资源搭建小型的高可用,高扩展的结构出来。</p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
  下下篇,才轮到实战,我将结合<span style="background-color:rgb(255,255,153)"><a href="http://lib.csdn.net/base/docker" class="replace_word" title="Docker知识库" target="_blank" style="color:#df3434; font-weight:bold;">Docker</a></span>虚拟技术,实现快速的集群搭建。</p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
  敬请期待~</p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
&nbsp;</p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
  本文有什么说错的地方,希望大家指出,让我好改正过来,多谢。</p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
&nbsp;</p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
参考:</p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
《大型网站技术架构:核心原理与案例分析》——李智慧 著</p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
《大型网站系统与<a href="http://lib.csdn.net/base/java" class="replace_word" title="Java 知识库" target="_blank" style="color:#df3434; font-weight:bold;">Java</a>中间件实践》——曾宪杰 著</p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
《<a href="http://lib.csdn.net/base/mysql" class="replace_word" title="MySQL知识库" target="_blank" style="color:#df3434; font-weight:bold;">MySQL</a>性能调优与架构设计》——简朝阳 著</p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
《keepalived权威指南》</p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
《mycat权威指南》</p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
《dubbo用户指南》</p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
《<a href="http://lib.csdn.net/base/computernetworks" class="replace_word" title="计算机网络知识库" target="_blank" style="color:#df3434; font-weight:bold;">计算机网络</a>》</p>
<p style="margin:10px auto; line-height:24px; font-family:微软雅黑,宋体,Arial; font-size:15px">
《<a href="http://lib.csdn.net/base/operatingsystem" class="replace_word" title="操作系统知识库" target="_blank" style="color:#df3434; font-weight:bold;">操作系统</a>》</p>
<br>
</div>
   
</div>
原创粉丝点击