手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜的Vultr , 注册 | 登陆
浏览模式: 标准 | 列表全部文章

手机升级惊魂

对于一个穷人来说,手机就是平时通讯的全部了。
昨天,出于一直对手机响应速度太慢的感觉,于是下载了update程序对手机进行了升级。不料,在恢复备份的时候,机器立刻白屏了。然后就在这种情况下,居然还能收到短信,但无法接电话,无法查看短信。
最后不得己,重刷机器。然后再进行恢复备份,结果还是这样。
如此三次后,只得选择重要的资料进行恢复,一些设置和机器中的文件就放弃了。

现在,机器又健康的在运行了。
感谢备份,里面有一些朋友的生小孩时所发的短信还在上面,可以让我不至于忘掉。(索爱好象没有单独把短消息导出的软件。。。。。)

Tags: 手机, 升级

小议mysql变量及其优化

本文属摘抄文章,以作备份

原文地址为:http://www.tbqu.com/post/251.html

mysql里的变量分系统变量和用户变量.
系统变量
其中系统变量,又分全局(global)和会话(session)两种.
全局系统变量,主要影响整个mysql实例的全局设置.
大部分变量都是作为mysql的服务器调节参数存在.新增或修改这类变量, 会影响mysql的运行方式.
比如: auto_increment_increment 代表序列的自增值, 默认为1

另外, mysql中,只有一部分变量是支持运行时动态修改的.
变量修改的作用范围,是那些重新创建连接到mysql服务器的客户端连接.

如果你的连接是由应用通过连接池来维护的,并且,是长连接的,那么,此时在服务器运行过程中,动态地修改全局变量对你是没有什么影响的.

 

通过全局变量, 我们可以想到一些应用场景:
1, 在存储过程, 函数, sql里,使用一些业务相关的全局变量.
经常编写业务相关的存储过程,函数的朋友, 可能会需要针对不同业务,设置能共享访问的全局变量.

比如, 公司的总人数,很多存储过程都需要调用这个值,但是因为这个值,不是经常会改变的,不需要每次都count.
所以大多数人会考虑把它cache一把,那么mysql提供的全局变量,就是一个好的存储场所.

2, 数据库配置中心

首先,这不一定是一种好的解决方式, 特别是大型地分布式系统.但是想到了,就跟大家分享一下.
主要就是利用了三层,四层架构的系统, 必不可少的数据库层来实现的.

大家知道, 应用的配置, 大多数是用配置文件或配置服务器来实现, 前者需要跟着项目打包, 部署.
后者, 只要在应用初始化或运行时,去配置中心取配置就行了.(淘宝这边两者都在用)

而数据库的配置中心, 其实类似配置服务器, 只不过灵活运用了mysql的变量机制.
它能继承配置服务器的多数优点, 但最大的特色就是在 sql, function , procedure 里都可以很方便地引用到.(相比用表的方式, 要方便一些)
并且本身就具有缓存, 移植得话, mysql得导出也是很快.
所以小系统, 想快速得搭建一个配置中心,利用mysql感觉还是不错的.

调用语法:
select * from user_info where id = @@global.admin_id — 例子,通过全局里配置的管理员id来取用户信息

以下是全局变量的一些常用命令,比较简单:
set global auto_increment_increment=1; — 设置序列的增长值
show global variables; — 显示所有的global变量
show global variables like ‘%test%’ — 查询包含test字符串的global变量

会话系统变量, 主要用于在当前客户端连接的生命周期内.它的变量值是全局变量的一份拷贝.
如果连接断开, 对当前会话变量所做修改都会被重置.

比如, 服务器会话变量 autocommit 默认为 true , 而你在非常连的客户端连接里设置了 false , 那么在执行完sql后, 连接就会断开. 此后,如果创建新的连接来执行sql, autocommit又会默认 true.

会话变量的使用场景与全局类似,只是生命周期不同, 因此可以用来
统计同一连接内请求sql次数, sql类型等信息.

session变量的一些常用操作:
set session auto_increment_increment=1; — 设置序列的增长值
show variables; or show session variables; — 如果不指明, 默认使用session变量
show variables like ‘%test%’ or show session variables lile ‘%test%’ — 查询包含test字符串的session变量

用户变量
基于会话变量实现的, 可以暂存值, 并传递给同一连接里的下一条sql使用的变量.
当客户端连接退出时,变量会被释放.

应用场景:
同一连接,未关闭情况下,帮你暂存一些计算结果.

比如
select @admin_id:=max(id) from user_info;
select * from user_info where id = @admin_id
以上两条sql在同一connection中完成.
另外,注意,用户变量前只有1个@, 2个@是用于存取系统变量的
业务相关的变量定义太多,无法区分系统全局变量?

这类问题,可以通过mysql提供的结构化系统变量来解决.

他们有独特的表示形式:
instance_name.test_var

比一般的变量多了一个instance_name.这样,你就可以很方便地对他们进行分类,比如 app.test_var,就可以区别于系统的var了.

PS: 其实,普通的系统变量,它也属于结构化变量,只不过他们默认隶属于 default 这个 instance, 不需要显示出来罢了.
影响mysql性能的系统变量
以下内容参考 http://www.mysqlperformanceblog.com/2006/06/08/mysql-server-variables-sql-layer-or-storage-engine-specific/

bulk_insert_buffer_size

批量插入缓存大小, 这个参数是针对MyISAM存储引擎来说的.适用于在一次性插入100-1000+条记录时, 提高效率.默认值是8M.可以针对数据量的大小,翻倍增加.

concurrent_insert
并发插入, 当表没有空洞(删除过记录), 在某进程获取读锁的情况下,其他进程可以在表尾部进行插入.
值可以设0不允许并发插入,1当表没有空洞时,执行并发插入,2.不管是否有空洞都执行并发插入.
默认是1.针对表的删除频率来设置.

delay_key_write

针对MyISAM存储引擎,延迟更新索引.意思是说,update记录时,先将数据up到磁盘,但不up索引,将索引存在内存里,当表关闭时,将内存索引,写到磁盘. 值为 0不开启, 1开启. 默认开启.

delayed_insert_limit, delayed_insert_timeout, delayed_queue_size
延迟插入, 将数据先交给内存队列, 然后慢慢地插入.但是这些配置,不是所有的存储引擎都支持, 目前来看, 常用的InnoDB不支持, MyISAM支持. 根据实际情况调大, 一般默认够用了.

expire_logs_days

自动删除超过指定天数的日志. 建议为0,表示“不自动删除”.

flush, flush_time

是否启用, 同步表数据到磁盘.以及自动同步的间隔时间.
针对flush_time, 官方建议只在Windows 9x或Me,或有最小资源的系统中使用该选项.所以,建议关闭.

ft_boolean_syntax, ft_max_word_len, ft_min_word_len,ft_query_expansion_limit, ft_stopword_file

针对MyISAM设置的参数, 全文搜索特性. 如果你不使用 FULLTEXT 索引,就不需要优化了. 详见mysql参考手册.

join_buffer_size

用于表间关联(join)的缓存大小.建议设为 131072.(128K)

key_buffer_size

索引块缓存区大小, 针对MyISAM存储引擎,该值越大,性能越好.但是超过操作系统能承受的最大值,反而会使mysql变得不稳定.
如果不是MyISAM存储引擎,一般设置为 4-32M大小.

key_cache_age_threshold, key_cache_block_size, key_cache_division_limit

键值缓存的相关设置.需要针对实际情况调优.只是针对MyISAM储存引擎.

large_pages

是否启动大页面支持.意思是,可以一些缓存分配更大的空间.这个特性已经被InnoDB, MyISAM等常用存储引擎支持.

low_priority_updates

低优先级更新.意思是, 所有的写操作(表写锁), 包括update,delete,insert等都需要等待读操作完成后才执行 (表读锁解开).
因为是针对表的锁,所以,这里仅支持MyISAM.

max_write_lock_count

最大写锁数量.这个变量的含义是, 当写锁达到一定数量后, 就不限制读锁, 允许一部分读锁进入.(可以读数据了,否则需要等待写锁释放后,才能读)

因为是针对表的锁,所以,这里仅支持MyISAM.

preload_buffer_size

重载索引时分配的缓冲区大小, 该变量仅支持MyISAM.

read_buffer_size, read_rnd_buffer_size

每个线程连续扫描时为扫描的每个表分配的缓冲区的大小(字节)。如果进行多次连续扫描,可能需要增加该值, 默认值为131072。

sort_buffer_size

每个排序线程分配的缓冲区的大小。增加该值可以加快ORDER BY或GROUP BY操作.默认数值是2097144(2M),建议加大到 16777208 (16M)。

timed_mutexes

显示mutexes的统计信息, 默认关闭OFF

tmp_table_size

临时表的大小,在未超过大小之前进行的操作是在内存中的, 当超过后,mysql会自动转换到硬盘上.

Tags: mysql, 变量优化

JS/CSS/images lazyLoader for JQuery

在jQuery的插件库里面,有一个imageLazyLoader,是专门用来进行延迟加载图片的。这次看到这个对于JS,CSS,IMAGE三者都能进行延迟加载的代码,当然是用来查看一下的。代码很小,大约只有3K左右,100多行代码,却实现了这么多的效果,看来jQuery的功能是被挖掘的越来越多了。

JavaScript代码
  1. /* 
  2.  * xLazyLoader 1.0 - Plugin for jQuery 
  3.  * Load js, css and  images 
  4.  * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
  5.  * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. 
  6.  * Depends: 
  7.  *   jquery.js 
  8.  *  Copyright (c) 2008 Oleg Slobodskoi (jimdo.com) 
  9.  */  
  10. ;(function($){  
  11.     $.xLazyLoader =  function ( method, options ) {  
  12.         if (typeof method == 'object') {  
  13.             options = method;  
  14.             method = 'load';  
  15.         };  
  16.         xLazyLoader[method]( options );  
  17.     };  
  18.       
  19.     var xLazyLoader = new function ()  
  20.     {  
  21.         var head = document.getElementsByTagName("head")[0];  
  22.         this.load = function ( options )  
  23.         {  
  24.             //Defaults  
  25.             var d = {  
  26.                 js: [],  
  27.                 css: [],  
  28.                 image: [],  
  29.                 name: null,  
  30.                 load: function(){}  
  31.             };  
  32.             $.extend(d, options);  
  33.               
  34.             var self = this,  
  35.                 ready = false,  
  36.                 loaded = {  
  37.                     js: [],  
  38.                     css: [],  
  39.                     image: []  
  40.                 }  
  41.             ;  
  42.               
  43.             each('js', d.js);  
  44.             each('css', d.css);  
  45.             each('image', d.image);  
  46.               
  47.             function each (type, urls)  
  48.             {  
  49.                 if ( $.isArray(urls) && urls.length>0 )  
  50.                     $.each( urls, function(i, url){  
  51.                         load(type, url);  
  52.                     });  
  53.                 else if (typeof urls == 'string')  
  54.                     load(type, urls);  
  55.             };  
  56.             function load (type, url)  
  57.             {  
  58.                 self[type](url, function() {   
  59.                     $.isArray(d[type]) ? loaded[type].push(url) : loaded[type] = url;  
  60.                     d.js.length == loaded.js.length   
  61.                     && d.css.length == loaded.css.length   
  62.                     && d.image.length == loaded.image.length  
  63.                     && d.load.apply(loaded, []);  
  64.                     return;  
  65.                 }, d.name ?'lazy-loaded-'+ d.name : 'lazy-loaded-'+new Date().getTime());  
  66.             };  
  67.         };  
  68.           
  69.         this.js = function (src, callback, name)  
  70.         {  
  71.             if ($('script[src*="'+src+'"]').length>0) {  
  72.                 callback();  
  73.                 return;  
  74.             };  
  75.             var script = document.createElement('script');  
  76.             script.setAttribute("type","text/javascript");  
  77.             script.setAttribute("src", src);  
  78.             script.setAttribute('id', name);  
  79.             if ($.browser.msie)  
  80.                 script.onreadystatechange = function () {  
  81.                      /loaded|complete/.test(script.readyState) && callback();  
  82.                 }  
  83.             else  
  84.                 //FF, Safari, Opera  
  85.                 script.onload = callback;  
  86.             head.appendChild(script);  
  87.         };  
  88.           
  89.         this.css = function (href, callback, name)  
  90.         {  
  91.             if ($('link[href*="'+href+'"]').length>0) {  
  92.                 callback();  
  93.                 return;  
  94.             };  
  95.               
  96.             var link = $('<link rel="stylesheet" type="text/css" media="all" href="'+href+'" id="'+name+'"></link>')[0];  
  97.             if ($.browser.msie)  
  98.                 link.onreadystatechange = function ()   {  
  99.                     /loaded|complete/.test(link.readyState) && callback();  
  100.                 }  
  101.             else if ($.browser.opera)  
  102.                 link.onload = callback;  
  103.             else  
  104.                 //FF, Safari, Chrome  
  105.                 (function(){  
  106.                     try {  
  107.                         link.sheet.cssRule;  
  108.                     } catch(e){  
  109.                         setTimeout(arguments.callee, 20);  
  110.                         return;  
  111.                     };  
  112.                     callback();  
  113.                 })();  
  114.             head.appendChild(link);  
  115.         };  
  116.           
  117.         this.image = function (src, callback)  
  118.         {  
  119.             var img = new Image();  
  120.             img.onload = callback;  
  121.             img.src = src;  
  122.         };  
  123.       
  124.         this.disable = function ( name )  
  125.         {     
  126.             $('#lazy-loaded-'+name, head).attr('disabled''disabled');  
  127.         };  
  128.         this.enable = function ( name )  
  129.         {     
  130.             $('#lazy-loaded-'+name, head).removeAttr('disabled');  
  131.         };  
  132.           
  133.         this.destroy = function ( name )  
  134.         {  
  135.             $('#lazy-loaded-'+name, head).remove();   
  136.         };  
  137.     };  
  138. })(jQuery);  
使用方法也很方便 :

Example 1:

Load some files

 $.xLazyLoader({
     js
: 'jquery.ui.all.js',
     css
: 'ui.allplugins.css',
     image
: 'your_image.jpg',
     load
: function(){
         alert
('All files are loaded');
     
}
 
});
 

Example 2:

Load multiple files of each type

 $.xLazyLoader({
     js
: ['ui.core.js','ui.dialog.js'],
     css
: ['ui.core.css', 'ui.dialog.css'],
     image
: ['your_image.jpg', 'your_image1.jpg', 'your_image2.jpg'],
     name
: 'dialog',
     load
: function(){
         alert
('All files are loaded');
     
}
 
});
 

Example 3:

Remove tags from head (javascript is still working, but css is completely destroyed )

 $.xLazyLoader('destroy','dialog');
 

Example 4:

Disable css.

 $.xLazyLoader('disable','dialog');
 

Enable css.

 $.xLazyLoader('enable','dialog');

项目存在于GOOGLECODE上,网址为:http://code.google.com/p/ajaxsoft/
估计还是会有BUG,不过相信作者应该会更新的

Tags: jquery, lazyloader

Debian GNU/Linux 5.0 Lenny 官方中文声明

2009年02月14日
Debian 计划高兴地宣布在经历了 22 个月坚持不懈地开发之后,Debian GNU/Linux 5.0 版(代号Lenny)正式发布了。Debian GNU/Linux 是一个 自由的操作系统,它支持 12 种处理器架构并带有KDE、Gnome、Xfce 和 LXDE 桌 面环境。同时它和 FHS v2.3 兼容,其软件针对 LSB 3.2 版开发。 Debian GNU/Linux 可以在多种计算机上运行,从掌上机和手持系统到超级计 算机,在它们之间的几乎任何机型都可以。它支持十二种架构:Sun SPARC (sparc)、HP Alpha (alpha)、Motorola/IBM PowerPC (powerpc)、Intel IA-32 (i386)、IA-64 (ia64)、HP PA-RISC (hppa)、MIPS (mips, mipsel)、ARM (arm, armel)、IBM S/390 (s390) 以及 AMD64 和 INTEL EM64T (amd64)。

Debian GNU/Linux 5.0 Lenny 加入了对 Marvell 的 Orion 平台的支 持,它被用于许多存储设备。所支持的存储设备包括 QNAP Turbo Station、HP mv2120 和 Buffalo Kurobox Pro。另外,Lenny 现在支持多种网络笔记 本计算机(Netbook),特别是华硕出品的 Eee PC。Lenny 还包含了用于 Emdebian 的编译工具,用它可以对 Debian 源代码包进行交叉编译并收缩,使之 适用于嵌入式 ARM 系统。

Debian GNU/Linux 5.0 Lenny 包括了新的 ARM EABI 移 植,armel。这个新的移植可以更有效地使用现代和未来的 ARM 处理器。 因此,老的 ARM 移植 (arm) 就过时了。

本次发布包括了多种升级过的软件包,比如 K 桌面环境 3.5.10 (KDE)、升级 的 GNOME 桌面环境 2.22.2、Xfce 4.4.2 桌面环境、LXDE 0.3.2.1、GNUstep 桌 面 7.3、X.Org 7.3、OpenOffice.org 2.4.1、GIMP 2.4.7、Iceweasel 3.0.6 (去除品牌版本的 Mozilla Firefox)、Icedove 2.0.0.19 (去除品牌版本的 Mozilla Thunderbird)、PostgreSQL 8.3.6、MySQL 5.0.51a、GNU 编 译器集合 (GCC) 4.3.2、Linux 内核 2.6.26 版、Apache 2.2.9、Samba 3.2.5、 Python 2.5.2 和 2.4.6、Perl 5.10.0、PHP 5.2.6、Asterisk 1.4.21.2、 Emacs 22、Inkscape 0.46、Nagios 3.06、Xen Hypervisor 3.2.1 (dom0 及 domU 支持)、OpenJDK 6b11,以及超过 23,000 个其他完全可用的软件包(从 12,000 个源码包编译而成)。

由于集成 X.Org 7.3,X server 可以对绝大多数硬件进行自动配置。新引入 的软件包可以完全地支持 NTFS 文件系统,并且能够直接使用绝大多数多媒体按 键。通过 swfdec 或 Gnash 插件可以支持 Adobe® Flash® 格式的文 件。对笔记本计算机的支持得到了全面提升,比如 CPU 频率自动调节的原生支持。 新加入的几个游戏可用来消磨闲暇时光,包括解谜游戏以及第一人称射击游戏。 还有值得一提的是新增加的 goplay,它是一个图形化游戏管理器,提供 了过滤器、搜索、抓屏以及对 Debian 中的游戏进行介绍等功能。

由 Debian GNU/Linux 5.0 新加入和更新版本的 OpenJDK,GNU Java 编译 器,GNU Java 字节码解释器,Classpath 和其他自由版本的 Sun 的 Java 科技 使我们可以在 Debian 的 main 软件仓库下发布基于 Java 的应用程序了。

系统安全方面的改进有在安装后第一次启动之前就安全所有安全更新、减少标 准安装 setuid root 可执行文件和打开的端口,以及使用 GCC 加强特性编译多 个对安全有严格要求的软件包。其他多种软件也都有特别的改进,比如 PHP 现在 已经使用 Suhosin 的加强补丁编译。

对于非英语母语的用户,包管理系统目前已经支持软件包描述的翻译,如果已 经翻译,它会自动显示用户母语版本的软件包描述。

Debian GNU/Linux 可以用多种介质进行安装,比如 DVD、CD、USB 闪存和软 驱以及网络。GNOME 是缺省的桌面环境,包含在第一张 CD 中。其他桌面环境 — KDE、XFce 或 LXDE — 则可以通过两张新的替代 CD 镜像进行安 装。同样还提供 Debian GNU/Linux 5.0 的多架构安装 CD 和 DVD,用它们可以 从一张光盘上安装多种架构的计算机;同时本发行还提供蓝光光盘,这就让在一张 安装盘上提供一个架构的全部软件成为可能。

除常规的安装,Debian GNU/Linux 也可以直接使用而无需安装。这种特殊的 镜像也称为 live 镜像,可用于 CD、USB 闪存以及多种形式的网络启动。起步阶 段只提供 amd64 和 i386 架构的 Live 镜像。

Debian GNU/Linux 5.0 的安装过程也已经从多个方面进行了改进:在多个其 他改进中,重新加入了对从多张 CD 或 DVD 进行安装的支持,某些设备需要的固 件可以从可移动介质上加载,还支持通过布莱叶显示器进行安装。安装程序的启 动过程同样也得到很多关注:可以在图形界面上选择安装前端和桌面环境,同时 也能选择专家或救援模式。Debian GNU/Linux 的安装系统目前已经被翻译成 63 种语言。

Debian GNU/Linux 现在已经可以通过 bittorrent (推荐使用)、jigdo 或 HTTP 方式下载;更多信息请参见 光盘上的 Debian GNU/Linux。很坑卩个供应商就将开始 提供 DVD、CD-ROM 以及蓝光光盘。

对绝大多数的配置来说,从先前版本即 Debian GNU/Linux 4.0 (代号 Etch) 升级到 Debian GNU/Linux 5.0 可以由 aptitude 包管理工具自动 进行,一定程度上也可以用 apt-get 包管理工具进行。一如往常,Debian GNU/Linux 系统可以平稳无痛地升级,没有任何必须的当机时间,但强烈建议事 先阅读发行注记,以便 了解可能的问题,并获取详细的安装和升级指示。本发行注记将在发行之后的数 周内进行更新,并将翻译成其他语言。
献给
在此特将 Debian GNU/Linux 5.0 Lenny 献给 Thiemo Seufer,他是 一位 Debian 开发者,在2008年12月26日的一场不幸的车祸中去世。Thiemo 通过 多种方式参与了 Debian。他维护着多个软件包并且是 MIPS 的 Debian 移植的主 要支持者。他还是我们内核组及 Debian 安装程序组的成员。他的贡献远远超出 Debian 项目。他还致力于 Linux 内核的 MIPS 移植以及 qemu 的 MIPS 仿真等 工作,同时还参与多个小项目,这里难以一一述及。

我们将永远怀念 Thiemo 的工作、奉献、广泛的技术知识以及同其他人分享的 能力。Thiemo 的贡献不会被遗忘。Thiemo 工作的高标准我们永难企及。
关于 Debian
Debian GNU/Linux 是一个自由操作系统,由遍及世界各地通过互联网协作的 一千多名志愿者开发。Debian 对自由软件的贡献、它的非赢利的天性以及它的开 放式开发模式,都让它在众多 GNU/Linux 发行版中独树一帜。

Debian 项目的关键力量是它的志愿者基础、它对 Debian 社区契约的坚持以 及它对打造最佳操作系统这一承诺的信守。Debian 5.0 是它在这个方向上迈出的 另一重要一步。

联系信息
更多信息,请访问位于 http://www.debian.org/ 的 Debian 网页或发邮件至 <press@debian.org>。
各平台的Release notes:http://debian.org/releases/lenny/releasenotes

Tags: debian, linux

网站体系架构演变[ZZ]

转自:http://www.blogjava.net/BlueDavy/archive/2008/09/03/226749.html

之前也有一些介绍大型网站架构演变的文章,例如LiveJournal的、ebay的,都是非常值得参考的,不过感觉他们讲的更多的是每次演变的结果,而没有很详细的讲为什么需要做这样的演变,再加上近来感觉有不少同学都很难明白为什么一个网站需要那么复杂的技术,于是有了写这篇文章的想法,在这篇文章中 将阐述一个普通的网站发展成大型网站过程中的一种较为典型的架构演变历程和所需掌握的知识体系,希望能给想从事互联网行业的同学一点初步的概念,文中的不对之处也请各位多给点建议,让本文真正起到抛砖引玉的效果。

架构演变第一步:物理分离webserver和数据库

最开始,由于某些想法,于是在互联网上搭建了一个网站,这个时候甚至有可能主机都是租借的,但由于这篇文章我们只关注架构的演变历程,因此就假设这个时候 已 经是托管了一台主机,并且有一定的带宽了,这个时候由于网站具备了一定的特色,吸引了 部分人访问,逐渐你发现系统的压力越来越高,响应速度越来越慢,而这个时候比较明显的是数据库和应用互相影响,应用出问题了,数据库也很容易出现问题,而 数据库出问题的时候,应用也容易出问题,于是进入了第一步演变阶段:将应用和数据库从物理上分离,变成了两台机器,这个时候技术上没有什么新的要求,但你 发现确实起到效果了,系统又恢复到以前的响应速度了,并且支撑住了更高的流量,并且不会因为数据库和应用形成互相的影响。

 

看看这一步完成后系统的图示:

1

这一步涉及到了这些知识体系:

这一步架构演变对技术上的知识体系基本没有要求。

架构演变第二步:增加页面缓存

好景不长,随着访问的人越来越多,你发现响应速度又开始变慢了,查找原因,发现是访问数据库的操作太多,导致数据连接竞争激烈,所以响应变慢,但数据库连 接又不能开太多,否则数据库机器压力会很高,因此考虑采用缓存机制来减少数据库连接资源的竞争和对数据库读的压力,这个时候首先也许会选择采用squid 等类似的机制来将系统中相对静态的页面(例如一两天才会有更新的页面)进行缓存(当然,也可以采用将页面静态化的方案),这样程序上可以不做修改,就能够 很好的减少对webserver的压力以及减少数据库连接资源的竞争,OK,于是开始采用squid来做相对静态的页面的缓存。

看看这一步完成后系统的图示:

2

这一步涉及到了这些知识体系:

前端页面缓存技术,例如squid,如想用好的话还得深入掌握下squid的实现方式以及缓存的失效算法等。

架构演变第三步:增加页面片段缓存

增加了squid做缓存后,整体系统的速度确实是提升了,webserver的压力也开始下降了,但随着访问量的增加,发现系统又开始变的有些慢了,在尝 到了squid之类的动态缓存带来的好处后,开始想能不能让现在那些动态页面里相对静态的部分也缓存起来呢,因此考虑采用类似ESI之类的页面片段缓存策略,OK,于是开始采用ESI来做动态页面中相对静态的片段部分的缓存。

看看这一步完成后系统的图示:

3

这一步涉及到了这些知识体系:

页面片段缓存技术,例如ESI等,想用好的话同样需要掌握ESI的实现方式等;

架构演变第四步:数据缓存

在采用ESI之类的技术再次提高了系统的缓存效果后,系统的压力确实进一步降低了,但同样,随着访问量的增加,系统还是开始变慢,经过查找,可能会发现系 统中存在一些重复获取数据信息的地方,像获取用户信息等,这个时候开始考虑是不是可以将这些数据信息也缓存起来呢,于是将这些数据缓存到本地内存,改变完毕后,完全符合预期,系统的响应速度又恢复了,数据库的压力也再度降低了不少。

看看这一步完成后系统的图示:

4

这一步涉及到了这些知识体系:

缓存技术,包括像Map数据结构、缓存算法、所选用的框架本身的实现机制等。

架构演变第五步: 增加webserver

好景不长,发现随着系统访问量的再度增加,webserver机器的压力在高峰期会上升到比较高,这个时候开始考虑增加一台webserver,这也是为了同时解决可用性的问题,避免单台的webserver down机的话就没法使用了,在做了这些考虑后,决定增加一台webserver,增加一台webserver时,会碰到一些问题,典型的有:
1
、如何让访问分配到这两台机器上,这个时候通常会考虑的方案是Apache自带的负载均衡方案,或LVS这类的软件负载均衡方案;
2
、如何保持状态信息的同步,例如用户session等,这个时候会考虑的方案有写入数据库、写入存储、cookie或同步session信息等机制等;
3
、如何保持数据缓存信息的同步,例如之前缓存的用户数据等,这个时候通常会考虑的机制有缓存同步或分布式缓存;
4
、如何让上传文件这些类似的功能继续正常,这个时候通常会考虑的机制是使用共享文件系统或存储等;
在解决了这些问题后,终于是把webserver增加为了两台,系统终于是又恢复到了以往的速度。

看看这一步完成后系统的图示:

5

这一步涉及到了这些知识体系:

负载均衡技术(包括但不限于硬件负载均衡、软件负载均衡、负载算法、linux转发协议、所选用的技术的实现细节等)、主备技术(包括但不限于ARP欺骗、linux heart-beat等)、状态信息或缓存同步技术(包括但不限于Cookie技术、UDP协议、状态信息广播、所选用的缓存同步技术的实现细节等)、共享文件技术(包括但不限于NFS等)、存储技术(包括但不限于存储设备等)。

架构演变第六步:分库

享受了一段时间的系统访问量高速增长的幸福后,发现系统又开始变慢了,这次又是什么状况呢,经过查找,发现数据库写入、更新的这些操作的部分数据库连接的 资 源竞争非常激烈,导致了系统变慢,这下怎么办呢,此时可选的方案有数据库集群和分库策 略,集群方面像有些数据库支持的并不是很好,因此分库会成为比较普遍的策略,分库也就意味着要对原有程序进行修改,一通修改实现分库后,不错,目标达到 了,系统恢复甚至速度比以前还快了。

看看这一步完成后系统的图示:

6

这一步涉及到了这些知识体系:

这一步更多的是需要从业务上做合理的划分,以实现分库,具体技术细节上没有其他的要求;

但同时随着数据量的增大和分库的进行,在数据库的设计、调优以及维护上需要做的更好,因此对这些方面的技术还是提出了很高的要求的。

架构演变第七步:分表、DAL和分布式缓存
随着系统的不断运行,数据量开始大幅度增长,这个时候发现分库后查询仍然会有些慢,于是按照分库的思想开始做分表的工作,当然,这不可避免的会需要对程序 进行一些修改,也许在这个时候就会发现应用自己要关心分库分表的规则等,还是有些复杂的,于是萌生能否增加一个通用的框架来实现分库分表的数据访问,这个在ebay的架构中对应的就是DAL,这个演变的过程相对而言需要花费较长的时间,当然,也有可能这个通用的框架会等到分表做完后才开始做,同时,在这个阶段可 能会发现之前的缓存同步方案出现问题,因为数据量太大,导致现在不太可能将缓存存在本地,然后同步的方式,需要采用分布式缓存方案了,于是,又是一通考察和折磨,终于是将大量的数据缓存转移到分布式缓存上了。

看看这一步完成后系统的图示:

7

这一步涉及到了这些知识体系:

分表更多的同样是业务上的划分,技术上涉及到的会有动态hash算法、consistent hash算法等;

DAL涉及到比较多的复杂技术,例如数据库连接的管理(超时、异常)、数据库操作的控制(超时、异常)、分库分表规则的封装等;

架构演变第八步:增加更多的webserver

在做完分库分表这些工作后,数据库上的压力已经降到比较低了,又开始过着每天看着访问量暴增的幸福生活了,突然有一天,发现系统的访问又开始有变慢的趋势 了,这个时候首先查看数据库,压力一切正常,之后查看webserver,发现apache阻塞了很多的请求,而应用服务器对每个请求也是比较快的,看来 是请求数太高导致需要排队等待,响应速度变慢,这还好办,一般来说,这个时候也会有些钱了,于是添加一些webserver服务器,在这个添加 webserver服务器的过程,有可能会出现几种挑战:
1
Apache的软负载或LVS软负载等无法承担巨大的web访问量(请求连接数、网络流量等)的调度了,这个时候如果经费允许的话,会采取的方案是购 买硬件负载,例如F5NetsclarAthelon之类的,如经费不允许的话,会采取的方案是将应用从逻辑上做一定的分类,然后分散到不同的软负载集群中;
2
、原有的一些状态信息同步、文件共享等方案可能会出现瓶颈,需要进行改进,也许这个时候会根据情况编写符合网站业务需求的分布式文件系统等;
在做完这些工作后,开始进入一个看似完美的无限伸缩的时代,当网站流量增加时,应对的解决方案就是不断的添加webserver

看看这一步完成后系统的图示:

8

这一步涉及到了这些知识体系:

到了这一步,随着机器数的不断增长、数据量的不断增长和对系统可用性的要求越来越高,这个时候要求对所采用的技术都要有更为深入的理解,并需要根据网站的需求来做更加定制性质的产品。

架构演变第九步:数据读写分离和廉价存储方案

突然有一天,发现这个完美的时代也要结束了,数据库的噩梦又一次出现在眼前了,由于添加的webserver太多了,导致数据库连接的资源还是不够用,而这个时候又已经分库分表了,开始分析数据库的压力状况,可能会发现数据库的读写比很高,这个时候通常会想到数据读写分离的方案,当然,这个方案要实现并不 容易,另外,可能会发现一些数据存储在数据库上有些浪费,或者说过于占用数据库资源,因此在这个阶段可能会形成的架构演变是实现数据读写分离,同时编写一些更为廉价的存储方案,例如BigTable这种。

看看这一步完成后系统的图示:

9

这一步涉及到了这些知识体系:

数据读写分离要求对数据库的复制、standby等策略有深入的掌握和理解,同时会要求具备自行实现的技术;

廉价存储方案要求对OS的文件存储有深入的掌握和理解,同时要求对采用的语言在文件这块的实现有深入的掌握。

架构演变第十步:进入大型分布式应用时代和廉价服务器群梦想时代

经过上面这个漫长而痛苦的过程,终于是再度迎来了完美的时代,不断的增加webserver就可以支撑越来越高的访问量了,对于大型网站而言,人气的重要毋 庸置疑,随着人气的越来越高,各种各样的功能需求也开始爆发性的增长,这个时候突然发现,原来部署在webserver上的那个web应用已经非常庞大 了,当多个团队都开始对其进行改动时,可真是相当的不方便,复用性也相当糟糕,基本是每个团队都做了或多或少重复的事情,而且部署和维护也是相当的麻烦, 因为庞大的应用包在N台机器上复制、启动都需要耗费不少的时间,出问题的时候也不是很好查,另外一个更糟糕的状况是很有可能会出现某个应用上的bug就导 致了全站都不可用,还有其他的像调优不好操作(因为机器上部署的应用什么都要做,根本就无法进行针对性的调优)等因素,根据这样的分析,开始痛下决心,将 系统根据职责进行拆分,于是一个大型的分布式应用就诞生了,通常,这个步骤需要耗费相当长的时间,因为会碰到很多的挑战:
1
、拆成分布式后需要提供一个高性能、稳定的通信框架,并且需要支持多种不同的通信和远程调用方式;
2
、将一个庞大的应用拆分需要耗费很长的时间,需要进行业务的整理和系统依赖关系的控制等;
3
、如何运维(依赖管理、运行状况管理、错误追踪、调优、监控和报警等)好这个庞大的分布式应用。
经过这一步,差不多系统的架构进入相对稳定的阶段,同时也能开始采用大量的廉价机器来支撑着巨大的访问量和数据量,结合这套架构以及这么多次演变过程吸取的经验来采用其他各种各样的方法来支撑着越来越高的访问量。

看看这一步完成后系统的图示:

10

这一步涉及到了这些知识体系:

这一步涉及的知识体系非常的多,要求对通信、远程调用、消息机制等有深入的理解和掌握,要求的都是从理论、硬件级、操作系统级以及所采用的语言的实现都有清楚的理解。

运维这块涉及的知识体系也非常的多,多数情况下需要掌握分布式并行计算、报表、监控技术以及规则策略等等。

说起来确实不怎么费力,整个网站架构的经典演变过程都和上面比较的类似,当然,每步采取的方案,演变的步骤有可能有不同,另外,由于网站的业务不同,会有不同的专业技术的需求,这篇blog更多的是从架构的角度来讲解演变的过程,当然,其中还有很多的技术也未在此提及,像数据库集群、数据挖掘、搜索等,但在真实的演变过程中还会借助像提升硬件配置、网络环境、改造操作系统、CDN镜像等来支撑更大的流量,因此在真实的发展过程中还会有很多的不同,另外一个大型网站要做到的远远不仅仅上面这些,还有像安全、运维、运营、服务、存储等,要做好一个大型的网站真的很不容易,写这篇文章更多的是希望能够引出更多大型网站架构演变的介绍

ps:最后附上几篇LiveJournal架构演变的文章:
从LiveJournal后台发展看大规模网站性能优化方法
http://blog.zhangjianfeng.com/article/743
另外从这里:http://www.danga.com/words/大家可以找到更多关于现在LiveJournal网站架构的介绍。

Tags: 架构, 演变