高可用性、负载均衡的mysql集群解决方案
一、mysql的市场占有率
二、mysql为什么受到如此的欢迎
三、mysql数据库系统的优缺点
四、网络服务器的需求
五、什么是mysql的集群
六、什么是负载均衡
七、mysql集群部署和实现方法
八、负载均衡的配置和测试
九、Mysql集群系统的测试(测试方案+测试脚本+测试结果分析)
l mysql的市场占有率
MySQL是世界上最流行的开源数据库,已有1100多万的击活安装,每天超过五万的下
载。MySQL为全球开发者、DBA和IT管理者在可靠性、性能、易用性方面提供了选
择。
第三方市场调查机构Evans Data Corporation调查显示,过去两年内在开发者使用
的所有数据库中,MySQL已经拥有了25%的市场占有率。开源已经成为当今IT结构中
不可或缺的重要部分,而且开源的市场占有率将继续增加。如下图所示:
l mysql为什么受到如此的欢迎
Sun公司今天1月份花了10亿美元将mysql收购,准备进军开源和数据库。
数据库系统 |
Oracle |
SQL Server |
MySQL |
DB2 |
是否免费 |
收费 |
收费 |
免费 |
收费 |
存储过程 |
支持 |
支持 |
支持 |
支持 |
视图 |
支持 |
支持 |
支持 |
支持 |
快照 |
支持 |
支持 |
不支持 |
支持 |
触发器 |
支持 |
支持 |
支持 |
支持 |
安全 |
强 |
中 |
中 |
强 |
复杂查询 |
强 |
中 |
弱 |
中 |
索引 |
丰富 |
一般 |
弱 |
中 |
数据类型 |
多 |
多 |
多 |
多 |
事务处理 |
强 |
强 |
弱 |
中 |
l mysql数据库系统的优缺点
每个系统都有自身的不足和发展历程,mysql也一样。
优点 |
缺点 |
1. 源码公开,免费 2. 跨平台 3. 为多种开发语言和包提供了API 4. 支持多线程 5. 小巧、灵活、速度较快 6. 支持各种字符集 7. 提供各种连接、优化的工具包 |
1. 不完善,很多数据库特性不支持 2. 只适合中小型应用,对于大型应用,可以跟其他数据库互补; 3. 数据库系统数据量只能达到千万级别; |
l 网络服务的需求
随着Internet的飞速发展和对我们生活的深入影响,越来越多的个人在互联网上购物、娱
乐、休闲、与人沟通、获取信息;越来越多的企业把他们与顾客和业务伙伴之间的联络
搬到互联网上,通过网络来完成交易,建立与客户之间的联系。互联网的用户数和网络
流量正以几何级数增长,这对网络服务的可伸缩性提出很高的要求。例如,比较热门的Web
站点会因为被访问次数急剧增长而不能及时处理用户的请求,导致用户进行长时间的等待
,大大降低了服务质量。另外,随着电子商务等关键性应用在网上运行,任何例外的服务
中断都将造成不可估量的损失,服务的高可用性也越来越重要。所以,对用硬件和软件方
法实现高可伸缩、高可用网络服务的需求不断增长,这种需求可以归结以下几点:
1) 可伸缩性(Scalability),当服务的负载增长时,系统能被扩展来满足需求,且不降
低服务质量。
2) 高可用性(Availability),尽管部分硬件和软件会发生故障,整个系统的服务必须是
每天24小时每星期7天可用的。
3) 可管理性(Manageability),整个系统可能在物理上很大,但应该容易管理。
4) 价格有效性(Cost-effectiveness),整个系统实现是经济的、易支付的。
单服务器显然不能处理不断增长的负载。这种服务器升级方法有下列不足:一是升级过
程繁琐,机器切换会使服务暂时中断,并造成原有计算资源的浪费;二是越往高端的服务
器,所花费的代价越大;三是一旦该服务器或应用软件失效,会导致整个服务的中断。
通过高性能网络或局域网互联的服务器集群正成为实现高可伸缩的、高可用网络服务的有
效结构。这种松耦合结构比紧耦合的多处理器系统具有更好的伸缩性和性能价格比,组成
集群的PC服务器或RISC服务器和标准网络设备因为大规模生产,价格低,具有很高的性能
价格比。但是,这里有很多挑战性的工作,如何在集群系统实现并行网络服务,它对外是
透明的,它具有良好的可伸缩性和可用性。
针对上述需求,我们给出了基于IP层和基于内容请求分发的负载平衡调度解决方法,并在
Linux内核中实现了这些方法,将一组服务器构成一个实现可伸缩的、高可用网络服务的服
务器集群,我们称之为Linux虚拟服务器(Linux Virtual Server)。在LVS集群中,使得
服务器集群的结构对客户是透明的,客户访问集群提供的网络服务就像访问一台高性能、
高可用的服务器一样。客户程序不受服务器集群的影响不需作任何修改。系统的伸缩性通
过在服务机群中透明地加入和删除一个节点来达到,通过检测节点或服务进程故障和正
确地重置系统达到高可用性。
l 什么是mysql集群
分为同步集群和异步集群。
同步集群(mysql cluster)
结构:(data + sql + mgm节点)
特点:
1) 内存级别的,对硬件要求较低,但是对内存要求较大。换算比例为:1:1.1;
2) 数据同时放在几台服务器上,冗余较好;
3) 速度一般;
4) 建表需要声明为engine=ndbcluster
5) 扩展性强;
6) 可以实现高可用性和负载均衡,实现对大型应用的支持;
7) 必须是特定的mysql版本,如:已经编译好的max版本;
8) 配置和管理方便,不会丢失数据;
异步集群(mysql replication)
结构:(master + slave)
特点:
1) 主从数据库异步数据;
2) 数据放在几台服务器上,冗余一般;
3) 速度较快;
4) 扩展性差;
5) 无法实现高可用性和负载均衡(只能在程序级别实现读写分离,减轻对主数据库的压力);
6) 配置和管理较差,可能会丢失数据;
l 什么是负载均衡
通过director,将用户的请求分发到real server服务器上,然后返回给用户。
负载均衡部署灵活、能够满足各种需求。
实现方式:
硬件:BIG/IP、Cisco、IBM(昂贵)
软件:LVS(免费)
LVS系统将用户的请求的数据包在数据层和网络层进行了封装和转发,由三种方式满足各种需求。
1) DR:直接路由
2) Tuning:tcp/ip隧道
3) NAT:网络地址转换
需求:
免费的软件包
1) 2台低端的director(active和standby)
2) 心跳线:连接2台director,检测活动情况
3) 2台以上的real servers
通用结构:
有兴趣的可以分别研究上面的三种LVS结构。
l mysql集群部署和实现方法
1) 假设现在有4台服务器(mysql官方推荐的最小配置)
服务器 |
开启的服务 |
角色 |
192.168.131.164 Ndb1 |
Mysqld |
Mysql API |
Ndb_mgmd |
管理节点(master) |
|
Heartbeat |
Director(master) |
|
192.168.131.26 Ndb2 |
Mysqld |
Mysql API |
Ndb_mgmd |
管理节点(backup) |
|
Heartbeat |
Director(standby) |
|
192.168.131.77 Sql1 |
Mysqld |
Mysql API(realserver) |
Ndbd |
存储节点 |
|
Arptables |
访问路由 |
|
192.168.131.101 Sql2 |
Mysqld |
Mysql API(realserver) |
Ndbd |
存储节点 |
|
Arptables |
访问路由 |
2)服务器安装配置和网络连接
(以下为所有服务器各操作一遍,共4遍)
安装:
将4台服务器安装CentOS 5.2,选择下面的包:
Clustering
Storage Clustering
mysql不需要安装,但perl-mysql-xxx的所有包需要安装
开发工具包和类库
sshd服务
SElinux ==>disable
语言支持包不安装,默认美国英语
设定主机名:
Vi /etc/sysconfig/network
Hostname=xxx
:wq
检查主机名:
Uname -a
必须和上表中的一一对应。否则有问题。
Vi /etc/hosts
Ndb1 192.168.131.164
Ndb2 192.168.131.26
Sql1 192.168.131.77
Sql2 192.168.131.101
更新:
#rpm --import http://dries.ulyssis.org/rpm/RPM-GPG-KEY.dries.txt
#yum update -y && yum -y install lynx libawt xorg-x11-deprecated-libs nx freenx arptables_jf httpd-devel
下载:
Mysql cluster版本(我下载的5.0.67社区版本):
[root@ndb1 RHEL5]# ls -lh MySQL* | awk '{print $9}'
MySQL-client-community-5.0.67-0.rhel5.i386.rpm
MySQL-clusterextra-community-5.0.67-0.rhel5.i386.rpm
MySQL-clustermanagement-community-5.0.67-0.rhel5.i386.rpm
MySQL-clusterstorage-community-5.0.67-0.rhel5.i386.rpm
MySQL-clustertools-community-5.0.67-0.rhel5.i386.rpm
MySQL-devel-community-5.0.67-0.rhel5.i386.rpm
MySQL-server-community-5.0.67-0.rhel5.i386.rpm
MySQL-shared-community-5.0.67-0.rhel5.i386.rpm
MySQL-shared-compat-5.0.67-0.rhel4.i386.rpm
MySQL-shared-compat-5.0.67-0.rhel5.i386.rpm
MySQL-test-community-5.0.67-0.rhel5.i386.rpm
perl-HTML-Template-2.9-1.el5.rf.noarch.rpm
[root@ndb1 RHEL5]#
在服务器上安装以上包,在安装的过程中如果缺少包或者库,采用:
yum install xxxx自行安装。
建立目录:
#mkdir /var/lib/mysql-cluster -p
以下分别操作:
安装cluster组件:
#Rpm -Uvh MySQL-xx-xx.rpm,根据不同,可以少安装部分组件。根据你需要而定。
163、26上,我安装了:
[root@ndb1 RHEL5]# rpm -aq | grep MySQL
MySQL-clusterstorage-community-5.0.67-0.rhel5
MySQL-clustertools-community-5.0.67-0.rhel5
MySQL-clustermanagement-community-5.0.67-0.rhel5
MySQL-shared-community-5.0.67-0.rhel5
perl-DBD-MySQL-3.0007-1.fc6
MySQL-server-community-5.0.67-0.rhel5
[root@ndb1 RHEL5]#
101、77上,我安装了:
[root@sql1 ~]# rpm -aq | grep MySQL
MySQL-clusterstorage-community-5.0.67-0.rhel4
MySQL-devel-community-5.0.67-0.rhel4
MySQL-server-community-5.0.67-0.rhel4
MySQL-client-community-5.0.67-0.rhel4
MySQL-shared-community-5.0.67-0.rhel4
[root@sql1 ~]#
以下在ndb1(164)和ndb2(26)上操作
[root@ndb1 ~]# vi /var/lib/mysql-cluster/config.ini
[NDBD DEFAULT]
NoOfReplicas=2
DataMemory=800M
IndexMemory=400M
[MYSQLD DEFAULT]
[NDB_MGMD DEFAULT]
[TCP DEFAULT]
# Section for the cluster management node
[NDB_MGMD]
# IP address of the management node (this system)
ID=1
HostName=192.168.131.164
[NDB_MGMD]
# IP address of the management node (this system)
ID=2
HostName=192.168.131.26
# Section for the storage nodes
[NDBD]
# IP address of the first storage node
HostName=192.168.131.77
DataDir= /var/lib/mysql-cluster
[NDBD]
# IP address of the second storage node
HostName=192.168.131.101
DataDir=/var/lib/mysql-cluster
# one [MYSQLD] per storage node
[MYSQLD]
[MYSQLD]
[MYSQLD]
[MYSQLD]
[MYSQLD]
[MYSQLD]
[MYSQLD]
:wq
以下在mysql API上操作(这里,我设定了7个API,以后可以随时加入)
Mysqld API的配置文件:
Vi /etc/my.cnf
[root@ndb1 ~]# cat /etc/my.cnf
[mysqld]
ndbcluster
ndb-connectstring = "host=192.168.131.164,host=192.168.131.26"
[ndb_mgm]
connect-string = "host=192.168.131.164,host=192.168.131.26"
[ndbd]
connect-string = "host=192.168.131.164,host=192.168.131.26"
:wq
分别启动ndb_mgmd/ndbd/mysqld
164/26:
ndb_mgmd -f /var/lib/mysql-cluster/config.ini
77/101:
Ndbd --initial
164/26/77/101:
/etc/rc.d/init.d/mysql start
在管理节点ndb1(164)和ndb2(26)上查看各节点的情况:
[root@ndb1 ~]# ndb_mgm
-- NDB Cluster -- Management Client --
ndb_mgm> show
Connected to Management Server at: 192.168.131.164:1186
Cluster Configuration
---------------------
[ndbd(NDB)] 2 node(s)
id=3 @192.168.131.77 (Version: 5.0.67, Nodegroup: 0, Master)
id=4 @192.168.131.101 (Version: 5.0.67, Nodegroup: 0)
[ndb_mgmd(MGM)] 2 node(s)
id=1 @192.168.131.164 (Version: 5.0.67)
id=2 @192.168.131.26 (Version: 5.0.67)
[mysqld(API)] 7 node(s)
id=5 @192.168.131.101 (Version: 5.0.67)
id=6 @192.168.131.26 (Version: 5.0.67)
id=7 @192.168.131.164 (Version: 5.0.67)
id=8 @192.168.131.77 (Version: 5.0.67)
id=9 (not connected, accepting connect from any host)
id=10 (not connected, accepting connect from any host)
id=11 (not connected, accepting connect from any host)
ndb_mgm>
以上说明一切正常。
将服务增加到开机启动服务项中:
164/26:
echo 'ndb_mgmd -f /var/lib/mysql-cluster/config.ini' > /etc/rc.d/init.d/ndb_mgmd
chmod 755 /etc/rc.d/init.d/ndb_mgmd
77/101:
Echo 'ndbd' > /etc/rc.d/init.d/ndbd
Chmod 755 /etc/rc.d/init.d/ndbd
Chkconfig --level 2345 ndbd on
OK,到此mysql cluster 配置完成。
强调:
1)由于数据放在内存中,需要在ndb节点上加大内存的数量。按照1:1.1的比例,如果数据量达到3.6GB,需要4GB的内存。
2)由于NDB和mysqld(API)都很耗费内存,所以建议将NDB放在164和26上。可能启动的时候会有警告,但是没关系的。
查看数据和内存情况:
77:
[root@sql2 ~]# top
top - 16:39:36 up 1:59, 1 user, load average: 1.37, 0.76, 0.60
Tasks: 80 total, 2 running, 78 sleeping, 0 stopped, 0 zombie
Cpu(s): 4.0%us, 4.0%sy, 0.0%ni, 87.3%id, 2.9%wa, 0.2%hi, 1.5%si, 0.0%st
Mem: 2075600k total, 2005868k used, 69732k free, 68256k buffers
Swap: 2031608k total, 0k used, 2031608k free, 1400812k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 2306 mysql 25 0 119m 15m 3952 S 22 0.8 10:20.94 mysqld
23791 root 15 0 1587m 484m 31m R 20 23.9 9:34.97 ndbd
由于77只有2GB的内存,而在config.ini中,把1.2GB的内存分配给了NDB,所以,加上mysqld用掉的,2GB的内存似乎已经所剩无几了。
查看77上的数据大小:
[root@sql2 ~]# cd /var/lib/mysql-cluster/ndb_4_fs/
[root@sql2 ndb_4_fs]# du -lh
1.3GB
连接API创建数据库:
由于上面4台都做为mysqld 的API,所以创建数据库的时候,都需要创建一遍。
以下操作在4台API上都需要操作:
# Mysql -uroot -pxxxxxxxxxxxx -A
Mysql> create database testdatabase;
Mysql> grant all on *.testdatabase to root@'192.168.131.%' identified by 'xxxxxxxxxxxxxxx';
Mysql> flush privileges;
Mysql> create table test(int (1));
Mysql> insert into test(1);
Mysql> quit;
以上做完以后,可以通过任意一台API上创建表,并写数据到表中,其他数据库都会同步写入。
分别连接每台服务器进行检查:
# Mysql -uroot -pxxxxxxxxxxxx -A
Mysql> use testdatabase;
Mysql> select * from test;
如果输出结果完全相同,表明mysql cluster已经可以正常工作了。
在2台API上设置LVS
Mysql cluster做好以后,数据库分别建立同名的数据库以后,权限分配好,然后只要在一台上写入数据,其他的NDB就存储了相同的数据。
用
程序连接任意一台API写数据,如果程序中未设置API的选择和判断,只使用了其中一个API,一旦API当机,则无法写入数据,必须修改程序。即便做了
API的判断和选择,因为没有实现负载均衡,服务器的性能没有充分利用。高可用性也没有达到目标。所以,我们现在在2台API之间做LVS。
LVS采用 ultramonkey(http://www.ultramonkey.org)
首先在NDB1(164)和NDB2(26)上下载heartbeat的软件包:
下载所有的rpm包:
Cd /usr/local/src
Mkdir heartbeat
Cd heartbeat
#Wget xxx.xxx.rpm
我下载了如下的软件包:
[root@ndb1 heartbeat]# ls -lh *.rpm | awk '{print $9}';
arptables-noarp-addr-0.99.2-1.rh.el.um.1.noarch.rpm
heartbeat-1.2.3.cvs.20050927-1.rh.el.um.4.i386.rpm
heartbeat-ldirectord-1.2.3.cvs.20050927-1.rh.el.um.4.i386.rpm
heartbeat-pils-1.2.3.cvs.20050927-1.rh.el.um.4.i386.rpm
heartbeat-stonith-1.2.3.cvs.20050927-1.rh.el.um.4.i386.rpm
ipvsadm-1.21-1.rh.el.1.um.1.i386.rpm
libnet-1.1.2.1-1.rh.el.um.1.i386.rpm
perl-Authen-SASL-2.08-1.rh.el.um.1.noarch.rpm
perl-Convert-ASN1-0.18-1.rh.el.um.1.noarch.rpm
perl-IO-Socket-SSL-0.96-1.rh.el.um.1.noarch.rpm
perl-ldap-0.3202-1.rh.el.um.1.noarch.rpm
perl-Mail-IMAPClient-2.2.9-1.rh.el.um.1.noarch.rpm
perl-Net-SSLeay-1.25-1.rh.el.um.1.i386.rpm
perl-Parse-RecDescent-1.94-1.el5.rf.noarch.rpm
perl-Parse-RecDescent-1.94-1.rh.el.um.1.noarch.rpm
perl-XML-NamespaceSupport-1.08-1.rh.el.um.1.noarch.rpm
perl-XML-SAX-0.12-1.rh.el.um.1.noarch.rpm
[root@ndb1 heartbeat]#
Heartbeat中包含以下几部分:
1) Master Director(分发器)-- MD
2) Backup Director(备份分发器)-- BD
3) Real server (真实服务器,可以有2个以上)--RS
IP设置并确认:
MD:
Eth0:192.168.131.164/24/GW:192.168.131.1
Eth1:10.9.30.1/24
MD:
Eth0:192.168.131.26/24/GW:192.168.131.1
Eth1:10.9.30.2
VIP:192.168.131.105/24/GW:192.168.131.1 -- 用户访问的统一虚拟IP
RS1:192.168.131.101/24/GW:192.168.131.1
RS2:192.168.131.77/24/GW:192.168.131.1
。。。
等等
以下操作在所有服务器上执行:
主机名确认:
分别执行:
#uname -a
主机名对应表中所列。
在MD和BD修改IP转发:
#vi modprobe.sh
modprobe ip_vs_dh
modprobe ip_vs_ftp
modprobe ip_vs
modprobe ip_vs_lblc
modprobe ip_vs_lblcr
modprobe ip_vs_lc
modprobe ip_vs_nq
modprobe ip_vs_rr
modprobe ip_vs_sed
modprobe ip_vs_sh
modprobe ip_vs_wlc
modprobe ip_vs_wrr
:wq
高可用性、负载均衡的mysql集群解决方案的更多相关文章
- 「mysql优化专题」高可用性、负载均衡的mysql集群解决方案(12)
一.为什么需要mysql集群? 一个庞大的分布式系统的性能瓶颈中,最脆弱的就是连接.连接有两个,一个是客户端与后端的连接,另一个是后端与数据库的连接.简单如图下两个蓝色框框(其实,这张图是我在悟空问答 ...
- Linux下"负载均衡+高可用"集群的考虑点 以及 高可用方案说明(Keepalive/Heartbeat)
当下Linux运维技术越来越受到企业的关注和追捧, 在某些企业, 尤其是牵涉到电子商务和电子广告类的网站,通常会要求作负载均衡和高可用的Linux集群方案.那么如何实施Llinux集群架构,才能既有效 ...
- linux系统下对网站实施负载均衡+高可用集群需要考虑的几点
随着linux系统的成熟和广泛普及,linux运维技术越来越受到企业的关注和追捧.在一些中小企业,尤其是牵涉到电子商务和电子广告类的网站,通常会要求作负载均衡和高可用的Linux集群方案. 那么如何实 ...
- LVS+Keepalived-DR模式负载均衡高可用集群
LVS+Keepalived DR模式负载均衡+高可用集群架构图 工作原理: Keepalived采用VRRP热备份协议实现Linux服务器的多机热备功能. VRRP,虚拟路由冗余协议,是针对路由器的 ...
- apache、mod_jk负载均衡与tomcat集群
最近需要搭建apache和tomcat的集群,实现静态网站直接通过apache访问,动态网站转交给tomcat处理,实现负载均衡和tomcat集群配置. apache安装 wget http://ap ...
- Apache+Tomcat部署负载均衡(或集群)
本来只打算写Tomcat集群部署,简化Apache和Tomcat整合过程的.后来想了想,这样不便于没有用过Apache的朋友来学习本文内容.于是干脆加大篇幅,让对Apache不了解的朋友能对Apach ...
- 3.dubbo 负载均衡策略和集群容错策略都有哪些?动态代理策略呢?
作者:中华石杉 面试题 dubbo 负载均衡策略和集群容错策略都有哪些?动态代理策略呢? 面试官心理分析 继续深问吧,这些都是用 dubbo 必须知道的一些东西,你得知道基本原理,知道序列化是什么协议 ...
- 05.haproxy+mysql负载均衡 整合 redis集群+ssm
本篇重点讲解haproxy+mysql负载均衡,搭建完成后与之前搭建的redis+ssm进行整合 (注:这里用到了两台mysql数据库,分别安装两台虚拟机上,已经成功实现主主复制,如果有需要,请查看我 ...
- Nginx+Keepalived+Tomcat高可用负载均衡,Zookeeper集群配置,Mysql(MariaDB)搭建,Redis安装,FTP配置
JDK 安装步骤 下载 http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html rpm ...
随机推荐
- ytxgnopyvw
Rt.不是我的博客被盗了 而是我要测试一下某网站是自动抓取我的博客还是手动抓取. 如果是手动抓取,那么该网站的管理员一定会看见这篇博文, 希望管理员能够自己反省. ytxgn只是为了百度搜索方便罢了.
- 用Backbone.js创建一个联系人管理系统(二)
欢迎大家回来继续这一教程,第一部分我们学习了model,collection和view在Backbone中的 基本用法,还有怎么样用主视图去绑定collection去渲染出每个Contact. 这部分 ...
- Xcode7.2 导入XMPP框架错误解决
1.修改Build Settings 在 Header Search Paths 中添加: "/usr/include/libxml2" 在Other Linker Flags 中 ...
- MKMapView的使用
#import "ViewController.h" #import "BVAnnotation.h" @interface ViewController () ...
- module中build.gradle文件参数含义
主要是module的build.gradle,截图如下: 01行:apply plugin: 'com.android.application' 表示该module是这个应用程序的module ...
- Mysql --分区表(1)
检查是否支持分区 通过如下命令检查的Mysql是否支持partition mysql> SHOW PLUGINS; ... | ARCHIVE | ACTIVE | STORAGE ENGINE ...
- First Blog, “Hello, world!”
As every single book says as a tradition, "Hello, world!" An explanation about the name – ...
- 使用ODP.NET查询数据参数顺序问题及莫名ORA-01722错误提示
最近由于项目需要,必须使用C#配合Oracle来进行开发,在开发的过程中,发现有些查询无法正确获取数据.例如: Select * From tabParam Where ParamCode = :Pa ...
- C# ADO.NET SqlDataAdapter中传递参数
ADO.NET的SQL语句中,往往不是静态的语句,而是需要接受传递过来的参数,比如典型的登录功能,需要查找指定的用户名: string sqlQuery = "SELECT * FROM W ...
- 聊聊JS与设计模式之(工厂Factory)篇------(麦当劳的故事)
一,总体概要 1,笔者浅谈 说起设计模式其实并不是什么很新奇的概念,它也不是基于特定语言所形成的产物,它是基于软件设计原则以及相关的方法论和经过特定时期衍生出的若干解决方案.本文会以一个实例带入大家学 ...