Android腾挪手机内存空间的几个方法
百万级访问量网站的技术准备工作
当今从纯网站技术上来说,因为开源模式的发展,现在建一个小网站已经很简单也很便宜,所以很多人都把创业方向定位在互联网应用。这些人里大多数不是很懂技术,或者不是那么精通,而网站开发维护方面的知识又很分散,学习成本太高,所以这篇文章将这些知识点结合起来,系统的来说,一个从日几千访问的小小网站,到日访问一两百万的小网站,中间可能会产生什么问题,以及怎么才能在一开始做足工作尽量避免这些问题。
对于不同的初期投资成本,技术路线的选择是不同的。这里假设网站刚刚只是一个构想,计划第一年服务器硬件带宽投入5万左右。对于这个资金额度,有很多种方案可选择,例如租用虚拟主机、租用单独服务器,或者流行的私有云,或者托管服务器。前两种选择,网站发展到一定规模时需迁移,那时再重做规划显然影响更大。服务器托管因为配置自主、能完全掌握控制权,所以有一定规模的网站基本都是这种模式。采用自己托管服务器的网站,一开始要注意以下几点。
一、开发语言
一般来说,技术人员(程序员)都是根据自己技术背景选择自己最熟悉的语言,不过不可能永远是一个人写程序,所以在语言的选择上还要是要费些心思。首先明确一点,无论用什么语言,最终代码质量是看管理,因此我们从前期开发成本分析。现在国内流行的适用于网站的语言,大概有java、php、.net、 python、ruby这五大阵营。python和ruby因为在国内流行的比较晚,现在人员还是相对难招一些。.net平台的人相对多,但是到后期需要解决性能问题时,对人员技能的要求比较高。剩余的java、php用人可以说是最多的。java和php无法从语言层面做比较,但对于初期,应用几乎都是靠前端支撑的网站来说,php入门简单、编写快速,优势相对大一点。至于后端例如行为分析、银行接口、异步消息处理等,等真正需要时,就要根据不同业务需求来选择不同语言了。
二、代码版本管理
稍微有点规模的网站就需要使用代码版本管理了。代码版本管理两点最大的好处,一是方便协同工作,二是有历史记录可查询比较。代码版本管理软件有很多,vss/cvs/svn/hg等,目前国内都比较流行,其中svn的普及度还是很高的。
向服务器部署代码,可以手工部署也可以自动部署。手工部署相对简单,一般可直接在服务器上svn update,或者找个新目录svn checkout,再把web root给ln -s过去。应用越复杂,部署越复杂,没有什么统一标准,只是别再用ftp上传那种形式,一是上传时文件引用不一致错误率增加,二是很容易出现开发人员的版本跟线上版本不一致,导致本来想改个错字结果变成回滚。如果有多台服务器还是建议自动部署,更换代码的机器从当前服务池中临时撤出,更新完毕后再重新加入。
三、服务器硬件
在各个机房里,靠一台服务器孤独支撑的网站数不清,但如果资金稍微充足,建议至少三台的标准配置,分别用作web处理、数据库、备份。web服务器至少要8G内存,双sata raid1,如果经济稍微宽松,或静态文件或图片多,则15k sas raid10。数据库至少16G内存,15k sas raid 10。备份服务器最好跟数据库服务器同等配置。硬件可以上整套品牌,也可以兼容机,也可以半品牌半组装,取决于经济能力。当然,这是典型的搭配,有些类型应用的性能瓶颈首先出现在web上,那种情况就要单独分析了。
web服务器可以既跑程序又当内存缓存,数据库服务器则只跑主数据库(假如是MySQL的话),备份服务器所承担就相对多一些,web配置、缓存配置、数据库配置都要跟前两台一致,这样WEB和数据库任意一台出问题,很容易就可以将备份服务器切换过去临时顶替,直到解决完问题。要注意,硬件是随时可能坏掉的,特别是硬盘,所以宁可WEB服务器跟数据库服务器放在一起,也一定不能省掉备份,备份一定要异机,并且有异步,电力故障、误操作都可能导致一台机器上的所有数据丢失。很多的开源备份方案可选择,最简单的就是rsync,写crontab里,定时同步。备份和切换,建议多做测试,选最安全最适合业务的,并且尽可能异地备份。
四、机房
三种机房尽量不要选:联通访问特别慢的电信机房、电信访问特别慢的联通机房、电信联通访问特别慢的移动或铁通机房。机房要尽可能多的实地参观,多测试,找个网络质量好,管理严格的机房。机房可以说是非常重要,直接关系到网站访问速度,网站访问速度直接关系到用户体验,访问速度很慢的网站,很难获得用户青睐。
五、架构
在大方向上,被熟知的架构是web负载均衡+数据库主从+缓存+分布式存储+队列。在一开始,按照可扩展的原则设计和编程就可以。只是要多考虑缓存失效时的雪崩效应、主从同步的数据一致性和时间差、队列的稳定性和失败后的重试策略、文件存储的效率和备份方式等等意外情况。缓存失效、数据库复制中断、队列写入错误、电源损坏,在实际运维中经常发生,如果不注意这些,出现问题时恢复期可能会超出预期很长时间。
六、服务器软件
操作系统Linux很流行。在没有专业运维人员的情况下,应倾向于择使用的人多、社区活跃、配置方便、升级方便的发行版,例如RH系列、 debian、ubuntu server等,硬件和操作系统要一起选择,看是否有适合的驱动,如果确定用某种商业软件或解决方案,也要提前知晓其对哪种操作系统支持最佳。web服务器方面,apache、nginx、lighttpd三大系列中,apache占有量还是最大,但是想把性能调教好还是需要很专业的,nginx和 lighttpd在不需要太多调整的情况下可以达到一个比较不错的性能。无论选择什么软件,除非改过这些软件或你的程序真的不兼容新版本,否则尽量版本越新越好,版本新,意味着新特性增多、BUG减少、性能增加。一个典型的php网站,基本上大多数人都没改过任何服务器软件源代码,绝大多数情况是能平稳的升级到新版本的。类似于jdk5到 jdk6,python2到python3这类变动比较大的升级还是比较少见的。看看ChangeLog,看看升级说明,结合自己情况评估测试一下,越早升级越好,升级的越晚,所花费的成本越高。对于软件包,尽量使用发行版内置的包管理工具,没有特殊要求时不建议自己编译,那样对将来运维不利。
七、数据库
几乎所有操作最后都要落到数据库身上,它又最难扩展(存储也挺难)。数据库常见的扩展方法有复制、分片,设计时要考虑到每种应用的数据如何复制、分片,当然这种考虑一般会推迟到技术设计时期。在初期进行数据库结构设计时,要根据不同的业务类型和增长量预期来考虑是否要分库、分区,并且尽量不要使用联合查询、不使用自增ID以方便分片。复制延时问题、主从数据库数据一致性问题,可以自己写或者用已有的运维工具进行检测。
用存储过程是比较难扩展的,这种情形多发生于传统C/S,特别是OA系统转换过来的开发人员。低成本网站不是一两台小型机跑一个数据库处理所有业务的模式,是机海作战。方便水平扩展比那点预分析时间和网络传输流量要重要的多的多。
另外,现在流行一种概念叫NoSQL,可以理解为非传统关系型数据库。实际应用中,网站有着越来越多的密集写操作、上亿的简单关系数据读取、热备等,这都不是传统关系数据库所擅长的,于是就产生了很多非关系型数据库,比如Redis/TC&TT/MongoDB/Memcachedb等,在测试中,这些几乎都达到了每秒至少一万次的写操作,内存型的甚至5万以上。在设计时,可根据业务特点和性能要求来选择是否使用这类数据库。例如 MongoDB,几句配置就可以组建一个复制+自动分片+failover的环境,文档化的存储也简化了传统设计库结构再开发的模式。但是当你决定采用一项技术时,一定要真正了解其优劣,例如可能你所选择的技术并不能支持你所需要的事务和数据一致性要求。
八、文件存储
存储的分布几乎跟数据库扩展一样困难,不过只有百万的PV的情况下,磁盘IO方面一般不会成大问题,一两台采用SATA做条带RAID的机器可以应付,反而是自己做异步备份比较复杂,因为小文件多。如果只有一台机器做存储,可以做简单的优化,例如放最小缩略图的分区和放中等缩略图的分区,根据平均大小调整一下块大小。存储要规划好目录结构,否则文件增多后维护起来复杂,也不利于扩展。同时还要考虑将来扩容,例如采用LVM,或者把文件根据不同规则散列到不同机器。磁盘IO繁重的情况下更容易出现故障,所以要做好备份,若发现有盘坏掉,要马上行动更换,很多人的硬盘都是坏了一块之后,接二连三的坏下去。
为了将来图片走cdn做准备,一开始最好就将图片的域名分开,且不用主域名。因为很多网站都将cookie设置到了.domain.ltd,如果图片也在这个域名下,很可能因为cookie而造成缓存失效,并且占多余流量,还可能因为浏览器并发线程限制造成访问缓慢。
九、程序
一定硬件条件下,应用能承载多少访问量,很大一部分也取决于程序如何写。程序写的不好,可能一万的访问都承载不了,写的好,可能一两台机器就能承担几百万PV。越是复杂、数据实时性要求越高的应用,优化起来越难,但对普通网站有一个统一的思路,就是尽量向前端优化、减少数据库操作、减少磁盘IO。向前端优化指的是,在不影响功能和体验的情况下,能在浏览器执行的不要在服务端执行,能在缓存服务器上直接返回的不要到应用服务器,程序能直接取得的结果不要到外部取得,本机内能取得的数据不要到远程取,内存能取到的不要到磁盘取,缓存中有的不要去数据库查询。减少数据库操作指减少更新次数、缓存结果减少查询次数、将数据库执行的操作尽可能的让你的程序完成(例如join查询),减少磁盘IO指尽量不使用文件系统作为缓存、减少读写文件次数等。程序优化永远要优化慢的部分,换语法是无法“优化”的。
然而编程时不应该把重点放在优化上,应该关注扩展性。当今的WEB应用,需求变化非常之快,适应多种需求的架构是不存在的,我们的扩展性就要把要点放在跟底层交互的架构上,例如持久化数据的存取规则、缓存的存取规则等,还有一些共用服务,例如用户信息等。先把不变的部分做完善,剩下的部分就很容易将精力放在业务逻辑上面了。
关于作者
刘志一,从1999年做个人网站开始一直专注于互联网,目前就职于一家垂直行业C2C网站,做产品和开发方面工作。
原文链接:http://www.infoq.com/cn/articles ... hnical-preparations
GO Contact Sync – 同步 Outlook 与 Gmail 联系人工具
GO Contact Sync 用来同步 Outlook 与 Gmail 的联系人,让你的通讯录从此彻底生活在云端。
在 GO Contact Sync 出现之前,同步 Outlook 与 Gmail 联系人最好的办法是通过手机,先让手机与 Gmail 通过网络自动同步,再用手机连接 Outlook 同步。
几天前还有人在 Group 里询问
GO Contact Sync 实现了 Outlook 与 Gmail 联系人的直接同步,让通讯录彻底云端。
同步很简单,填写你的 Gmail 用户名密码,随意填写 Sync Profile,如果你想同步多台电脑的Outlook,这个 Sync Profile 需要唯一。Sync Deletion 为是否同步删除联系人。
同步选项有以下几种:
* Merge Prompt: 如果两边的联系人都更新了,弹出对话框让你选择覆盖哪一个。
* Merge Outlook Wins: 如果两边的联系人都更新了, Google 联系人信息会被覆盖掉.
* Merge Google Wins: 如果两边的联系人都更新了, Outlook 联系人信息会被覆盖掉.
* Outlook To Google Only: 只把 Outlook 的联系人更新到 Google.
* Google To Outlook Only: 只把 Google 的联系人更新到 Outlook. via
鱼漂注: 通过go contact,可以方便将WM与Android手机同步联系人.
很给力的一个纯JS的图表库Highcharts
What is Highcharts?
Highcharts is a charting library written in pure JavaScript, offering an easy way of adding interactive charts to your web site or web application. Highcharts currently supports line, spline, area, areaspline, column, bar, pie and scatter chart types.
Compatible
It works in all modern browsers including the iPhone/iPad and Internet Explorer from version 6. Standard browsers use SVG for the graphics rendering. In Internet Explorer graphics are drawn using VML.
Pure JavaScript
Highcharts is solely based on native browser technologies and doesn't require client side plugins like Flash or Java. Furthermore you don't need to install anything on your server. No PHP or ASP.NET. Highcharts needs only two JS files to run: The highcharts.js core and either the jQuery or the MooTools framework. One of these frameworks is most likely already in use in your web page.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
[转]内存文件系统使用及示例:ramdisk, ramfs, tmpfs
在Linux中可以将一部分内存mount为分区来使用,通常称之为RamDisk。
RamDisk有三种实现方式:
第一种就是传统意义上的,可以格式化,然后加载。
这在Linux内核2.0/2.2就已经支持,其不足之处是大小固定,之后不能改变。
为了能够使用Ramdisk,我们在编译内核时须将block device中的Ramdisk支持选上,它下面还有两个选项,一个是设定Ramdisk的大小,默认是4096k;另一个是initrd的支持。
如果对Ramdisk的支持已经编译进内核,我们就可以使用它了:
查看一下可用的RamDisk,使用ls /dev/ram*
首先创建一个目录,比如test,运行mkdir /mnt/test;
然后对/dev/ram0 创建文件系统,运行mke2fs /dev/ram0;
最后挂载 /dev/ram0,运行mount /dev/ram /mnt/test,就可以象对普通硬盘一样对它进行操作了。
更详细的内容可以参考: http://www.linuxfocus.org/ChineseGB/November1999/article124.html http://www.vanemery.com/Linux/Ramdisk/ramdisk.html
另两种则是内核2.4才支持的,通过Ramfs或者Tmpfs来实现:
它们不需经过格式化,用起来灵活,其大小随所需要的空间而增加或减少。
Ramfs顾名思义是内存文件系统,它它处于虚拟文件系统(VFS)层,而不像ramdisk那样基于虚拟在内存中的其他文件系统(ex2fs)。
因而,它无需格式化,可以创建多个,只要内存足够,在创建时可以指定其最大能使用的内存大小。
如果你的Linux已经将Ramfs编译进内核,你就可以很容易地使用Ramfs了。创建一个目录,加载Ramfs到该目录即可:
# mkdir /testRam
# mount -t ramfs none /testRAM
缺省情况下,Ramfs被限制最多可使用内存大小的一半。可以通过maxsize(以kbyte为单位)选项来改变。
# mount -t ramfs none /testRAM -o maxsize=2000 (创建了一个限定最大使用内存为2M的ramdisk)
Tmpfs是一个虚拟内存文件系统,它不同于传统的用块设备形式来实现的Ramdisk,也不同于针对物理内存的Ramfs。
Tmpfs可以使用物理内存,也可以使用交换分区。在Linux内核中,虚拟内存资源由物理内存(RAM)和交换分区组成,这些资源是由内核中的虚拟内存子系统来负责分配和管理。
Tmpfs向虚拟内存子系统请求页来存储文件,它同Linux的其它请求页的部分一样,不知道分配给自己的页是在内存中还是在交换分区中。同Ramfs一样,其大小也不是固定的,而是随着所需要的空间而动态的增减。
使用tmpfs,首先你编译内核时得选择"虚拟内存文件系统支持(Virtual memory filesystem support)" 。
然后就可以加载tmpfs文件系统了:
# mkdir -p /mnt/tmpfs
# mount tmpfs /mnt/tmpfs -t tmpfs
同样可以在加载时指定tmpfs文件系统大小的最大限制:
# mount tmpfs /mnt/tmpfs -t tmpfs -o size=32m
使用df -aT命令可以看到有个/dev/shm目录,该目录的文件系统是tmpfs的,因此这个目录下的文件访问是非常快的,但是其大小可能不同机器都不一样,而且每次重启后文件也就丢失了。
第二部分
LINUX下我所接触过的内存文件系统有三个:
(1)ramdisk,使用前需要先创建文件系统,并且调整文件系统大小比较麻烦,需要修改内核引导参数并重新启动操作系统,在繁杂多变的应用与需要 7X24不间断运行的系统来说,并不是一个可以接受的选择.好处是自2.0版本起内核便支持(这也算好处?嗯,确实算,如果你手头真有这样的系统的话)
(2)ramfs,使用前不需要去创建文件系统了,直接通过mount的方式即可挂载上来用,需要的时候可以使用"mount -o remount,maxsize=..."这种方式来调整大小.
(3)tmpfs,同ramfs在表面上基本上一样啦,不同于ramfs针对"物理内存",tmpfs是在虚拟内存下分配空间的,也就是说tmpfs实例中存储的文件既可能存在于物理内存中,也可能存在于交换分区中,具体存在哪里,是由"虚拟内存子系统"来调度的.
纯性能角度讲,ramfs会在进程占用内存使用较多的情况下会优于tmpfs,在没有交换分区或进程占用内存较小而不发生swap行为的情况下,两者性能不会有差异(这个结论没有实测过,我"想当然"用猜的)
基本情况介绍完毕,下面介绍tmpfs的应用,(没办法,我手头机器内存不是那么宽裕...)
0,根据需要创建挂载目录,例:
mkdir -p $DIR_TMP;
1,挂载
mount my_tmpfs $DIR_TMP -t tmpfs -o size=512m
my_tmpfs这个名字需要起,一个标识而已,会出现在df 的Filesytem一列,起个别致点的名字比较容易被自己写的其它监控脚本找到,如果非要起个none或tmpfs之类的名字的话...反正系统默认挂载的tmpfs都比较喜欢用这两个名字,好坏自己琢磨吧.
成功以后自己用df 看一下就知道了,写监控脚本时可以用"df -t tmpfs|grep ^my_tmpfs"来找到这一行.
2,调整
应用中如果感觉不合适,随时可以用mount命令调整
mount $DIR_TMP -o remount,size=1024m,nr_inodes=100k
nr_inodes为最大节点数,如果你的$DIR_TMP使用df命令查看明明有空间,却无法创建新文件(例如touch一个新文件),可能是文件节点用到上限了,可以用"df -i"命令来查看,如果是有空间但节点达到上限,就需要用nr_inodes来调整了.
其它可以调整的参数:
mode,uid,gid,
uid和gid就不多说了,不知道的回家补基础,mode也不多说了,取值是3个八进制数字,表示许可权限,不知道这个的也回家...
其它参数,参见mount命令的man page之OPTIONS一节中"-o"参数的说明.
3,卸载
umount $DIR_TMP
4,其它
mount 命令的man page中对tmpfs提及不多,详细一些的文档,请参阅内核文档Documentation/filesystems/tmpfs.txt(内核源代码目录内)
Android开发环境搭建
Android这几年发展迅猛,系统越来越稳定,强大.同时,越来越多的手机都搭上这个免费开源的系统.
最近也在入手一台Android2.1手机, 所以也开始尝试一下Android的开发. 下面是一个简单的环境搭建过程.
Android的开发语言是Java(个人认为,主要是采用了Java的语法, 因为Google为Android编写了一个特别的虚拟机, 程序的框架和运行方式,也与传统Java不太一样). 开发环境主要是使用Eclipse+Android插件的形式。
由于需要安装Eclipse,所以PC端的Java环境是必不可少的,同时,为了编译和运行Android模拟器,Android SDK也需要安装。(来源:http://www.eit.name 转载请注明)
以下大体步骤:
1. 安装JDK
到Oracle的Java官方,直接下载Windows的安装包,运行安装程序,根据提示完成即可。
http://www.oracle.com/technetwork/java/javase/downloads/jdk6-jsp-136632.html
2. 安装Eclipse
到Eclipse的下载官方: http://www.eclipse.org/downloads/
下载“Eclipse Classic 3.6.1”,解压即可。双击eclipse文件夹中的eclipse.exe程序即可。
3. 安装Android SDK
到Android开发官方: http://developer.android.com/sdk 下载sdk installer,根据提示安装即可。
安装完后,运行SDK Manager下载和安装2.1, 2.2等sdk.
(可恶的是,这网站被墙了。)
4. 安装ADT (https://dl-ssl.google.com/android/eclipse/)
运行Eclipse,打开Help=>Install New Software...菜单, 添加一个新站点ADT,网址为:
https://dl-ssl.google.com/android/eclipse/
再从此站点下载和安装ADT。
5. Eclipse中配置sdk
在Eclipse中,打开Window=>Preferences,在左边找到Android,并配置好SDK的根目录。
打开Window=>Android SDK and AVD Manager,创建一个相应版本的AVD。
6. 开始第一个程序
在Eclipse,打开File=>New=>Project, 开始你的Android开发之旅吧。
C++和Java的语法对比手册
首先,两件大事-主函数和怎样编译,下面是它们的小差别:
主函数
C++
// 自由函数
int main( int argc, char* argv[])
{
printf( "Hello, world" );
}
Java
// 每个函数必须是类成员;当java类运行时类中的主函数就会被调用
//(所以你可以为每个类写一个主函数--这样用于给类写单元测试时会很方便)
class HelloWorld
{
public static void main(String args[])
{
System.out.println( "Hello, World" );
}
}
编译
C++
// 编译
g++ foo.cc -o outfile
// 运行
./outfile
Java
// 编译在foo.java里的类成为<类名>.class
javac foo.java
// 调用<类名>中的静态main函数
java <classname>
注释
两种语言完全相同 (// 和 /* */ 都能工作)
类声明
大部分一样,除了Java不要求后面有个分号
C++
class Bar {};
Java
class Bar {}
方法声明
基本相同,除了Java中必须是类成员并且可能有public/private/protected前缀之外。
构造和析构
构造语法相同,Java没有析构的等价物。
静态成员函数和变量
方法声明方式相同,不过Java提供了static initialization blocks 来初始化静态变量(代替在源码文件中放定义):
class Foo
{
static private int x;
// static initialization block
{ x = 5; }
}
对象声明
C++
// 栈对象
myClass x;
// 堆对象
myClass *x = new myClass;
Java
// 总是分配在堆上(而且,构造总是要写括号)
myClass x = new myClass();
引用vs.指针
C++
// 引用是不可改的,使用指针能得到更大的弹性
int bar = 7, qux = 6;
int& foo = bar;
Java
// 引用是可改的,它仅存放对象的地址。没有原生指针。
myClass x;
x.foo(); // 错误,x是空“指针”
// 注意Java里总是使用 . 存取域
继承
C++
class Foo : public Bar
{ ... };
Java
class Foo extends Bar
{ ... }
保护级别
C++
public:
void foo();
void bar();
Java
public void foo();
public void bar();
虚函数
C++
virtual int foo();
Java
// 函数默认就是虚函数;使用final防止被重载
int foo();
抽象类
C++
// 只要包含一个纯虚函数
class Bar { public: virtual void foo() = 0; };
Java
// 可以用语法直接定义
abstract class Bar { public abstract void foo(); }
// 或者指定为接口
interface Bar { public void foo(); }
// 然后,用一个类实现implement
它:
class Chocolate implements Bar
{
public void foo() { /* do something */ }
}
内存管理
大致相同--new 分配, 不过因为Java著名的垃圾回收机制所以没有delete 。
NULL vs. null
C++
// 初始化指针为NULL
int *x = NULL;
Java
// 使用未初始化的引用会被计算机捕获,不过可以赋值为null指明引用为无效。
myClass x = null;
布尔值
Java要长一点,你得写boolean来代替简短的bool。
C++
bool foo;
Java
boolean foo;
常量
C++
const int x = 7;
Java
final int x = 7;
Throw说明
首先, Java在编译时强制要求有throw说明-如果一个方法要抛出一个异常你必须先说明它
C++
int foo() throw (IOException)
Java
int foo() throws IOException
数组
C++
int x[10];
// 或者
int *x = new x[10];
// 使用x然后收回内存
delete[] x;
Java
int[] x = new int[10];
// 使用x,内存由垃圾回收机制回收
集合和迭代
C++
迭代器是类成员,一个范围起始于<container>.begin(), 终止于<container>.end(). 使用++操作前进,使用*存取。
vector myVec;
for ( vector<int>::iterator itr = myVec.begin();
itr != myVec.end();
++itr )
{
cout << *itr;
}
Java
迭代器仅仅是一个接口。一个范围起始于<collection>.iterator, 接着使用itr.hasNext()检查确认是否已到末尾。使用itr.next()取得下一个数据。
ArrayList myArrayList = new ArrayList();
Iterator itr = myArrayList.iterator();
while ( itr.hasNext() )
{
System.out.println( itr.next() );
}
// 在Java 5中:
ArrayList myArrayList = new ArrayList();
for( Object o : myArrayList ) {
System.out.println( o );
}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>dnsstuff.com 收费后的选择
互联网服务当有一定知名度后应否收费呢? 这是一个有趣问题。 Dnsstuff.com 是一个很受 email administrator 喜爱的网站。不明白为何它要转为收费形容:
1. 它的服务提供没有独特性。如果你用心使用 dig, nslookup 的工具,也可以有齐所有结果。
2. 基本上所有查询都是全自动,不经人手。不似其他 Free website, free webmail, free storage 等网站愈人多就要投资更多。但 dnsstuf.com 的 marginal cost 非常低。这类网站的最佳收入是增大会员数目,用广告支持。
无论如何,当你收费后,人家就会找替代品:
http://www.intodns.com/
http://www.thednsreport.com/
这两个「抄」得最似,接近一样。
其他还有:
http://www.squish.net/dnscheck/
http://www.iptools.com/
http://www.netsystools.com/
http://www.freednsinfo.com/
http://www.diggip.com/
>>>>>>>>>>>>>>>>>>>>>>>>CentOS5系统安装和配置HA+DRBD+MySQL笔记
DRBD(Distributed Replicated Block Device),分布式复制块设备,是一种通过TCP/IP网络实现块设备数据实时镜像的方案。利用这种方案,单一主节点模式(single primary mode)双机系统能够实时地将业务数据保存在主备节点的磁盘中,正常情况下两个节点的数据是一模一样的。
HeartBeat在此是用来做热备切换的,两节点间通过心跳线连接,如果主节点死机的话,可以通过HA将DRBD快速切换到另外一个节点,同时抢占虚拟IP,并启动MySQL,对MySQL客户端来说,只有很短时间的中断。此模式能有效提高MySQL的可用性。
此文档参考了DRBD(http://www.drbd.org), HA(http://linux-ha.org), MySQL的相关官方文档。安装笔记由鱼漂(ipaddr)原创,最新版本可以在http://www.eit.name/找到,转载请注明。
--------------------------------
一.环境说明
--------------------------------
OS: CentOS 5.5 32位
MySQL: 系统自带
DRBD: 8.3.8.1编译安装 (http://www.drbd.org/)
HeartBeat: 3.0.3编译安装 (http://linux-ha.org/)
====Node1====
Hostname: db_node1.systemadmin.cn
Ip: 192.168.0.201
====Node2====
Hostname: db_node2.systemadmin.cn
Ip: 192.168.0.202
HB的虚IP: 192.168.0.200
用来做DRBD的分区:/dev/sdb1
挂载点:/data/dbdata
--------------------------------
二. 编译安装DRBD
--------------------------------
从www.drbd.org下载drbd-8.3.8.1.tar.gz,分别在两个节点上编译安装:
注意,DRBD需要内核模块支持,2.6.33后的Linux内核已内置DRBD的支持,在此版本前,安装时需要kernel-devel包,同时编译drbd时要带上--with-km。
#./configure --prefix=/ --with-km
#make
#make install
#chkconfig --add drbd
#chkconfig drbd on
检查安装是否成功:
#drbdadm
看是否以执行成功?
#cat /proc/drbd
是否可以看到版本信息
重启后再次检查cat /proc/drbd
--------------------------------
三. 配置DRBD
--------------------------------
注意,新版本的DRBD的配置文件已拆分成多个,全部放在/etc/drbd.d/目录,具体可参考/etc/drbd.conf中的配置.
如果开了iptables防火墙,需要打开对应的7789端口。
在主节点配置/etc/drbd.d/dbdata.res:
=========dbdata.res begin===========
resource dbdata {
on db_node1.systemadmin.cn {
device /dev/drbd1;
disk /dev/sdb1;
address 192.168.0.201:7789;
meta-disk internal;
}
on db_node2.systemadmin.cn {
device /dev/drbd1;
disk /dev/sdb1;
address 192.168.0.202:7789;
meta-disk internal;
}
}
=========dbdata.res end===========
创建drbd设备
#drbdadm create-md all
#/etc/init.d/drbd restart
查看是否有相应的块设备:
#ls -l /dev/drbd1
#cat /proc/drbd
设置当前节点为主节点并进行格式化:
#drbdadm -- --overwrite-data-of-peer primary all
#mkfs.ext3 /dev/drbd1
#mount /dev/drbd1 /data/dbdata
#mkdir /data/dbdata/etc
#mkdir /data/dbdata/data
在从节点做如下配置:
复制dbdata.res到从节点的/etc/drbd.d/
#drbdadm create-md all
#/etc/init.d/drbd restart
通过cat /prod/drbd查看是否开始复制,以及两节点的状态。
此时开始同步两个节点的磁盘,需要一定时间,在同步完成前,请不要重启,否则会重新同步。
同步完成后,如果两个节点都是Secondary/Secondary,并且已经UpToDate了,可以挑一个节点设置为主节点:
#drbdadm primary all
DRDB的一些常规操作:
切换主从节点前,要注意umount
主从切换: drbdadm primary all, drbdadm secondary all
节点间连接:drbdadm connect|disconnect all
DRBD脑裂后的处理:
脑裂后,两个节点间数据不同步,主从关系失效,需要按下面的步骤修复:
a.在从节点如下操作:
#drbdadm secondary dbdata
#drbdadm -- --discard-my-data connect dbdata
b.在主节点上,通过cat /proc/drbd查看状态,如果不是WFConnection状态,需要再手动连接:
#drbdadm connect dbdadta
--------------------------------
四. 迁移MySQL到DRBD磁盘
--------------------------------
确保drbd当前工作正常,将/data/dbdata加载,再在主节点按如下步骤操作。
a. 关闭MySQL: /etc/init.d/mysqld stop
b. #mv /etc/my.cnf /data/dbdata/etc/
c. #ln -s /data/dbdata/etc/my.cnf /etc/my.cnf
d. 修改my.cnf,将数文件文件指向 /data/dbdata/data
e. 将原来的数据文件移动到 /data/dbdata/data
f. 再启动MySQL
从节点只需要删除/etc/my.cnf,同时,建立链接到/data/dbdata/etc/my.cnf即可。
现在已完成MySQL+DRBD的配置,但切换时仍然是手动进行,假设主节点从node1转到node2,手动操作如下:
a. 在node1上停止MySQL
b. 在node1上unmout /data/dbdata
c. 在node1上执地drbdadm secondary all,两个节点都是secondary状态后,才可以将node2设置为primary
d. 在node2上执行drbdadm primary all,将node2变成主节点
e. 观察两个节点的/proc/drbd是否正常
f. 在node2上mount /dev/drbd1 /data/dbdata
g. 在node2上面启动MySQL
鱼漂建议:据说MyISAM在DRBD上容易造成数据丢失,或表文件损坏,所以此模式下最好用InnoDB,打开Binlog,同时,innodb_flush_log_at_trx_commit=1可以保证数据完整,但会严重影响性能。设置为2的话性能约有10倍提升,不过故障时可能会丢失1秒的数据。
--------------------------------
五. 安装配置HA
--------------------------------
需分别下载和安装:
* Cluster Glue 1.0.6: glue-1.0.6.tar.bz2
* Resource Agents 1.0.3: agents-1.0.3.tar.bz2
* Heartbeat 3.0.3: Heartbeat-3-0-STABLE-3.0.3.tar.bz2
鱼漂特别提醒,编译安装过程中,还会连接网络下载文件和校验xml,请在安装前确保网络连接和DNS解析正常。
A. 先安装glue
1. 从linux-ha.org下载 glue-1.0.6.tar.bz2
2. 解压
3. 编译安装:
./autogen.sh
./configure
打开lib/stonith/main.c,将version相关的注释掉,否则编译不过,有点诡异。
1、找到其64行,将其注释掉。
2、找到其76到81行全部注释掉。
3、找到其390行,将其注释
groupadd haclient
useradd -g haclient hacluster
make
make install
B. 安装Cluster agent
#./autogen.sh
#./configure
#make
#make install
C. 安装HA3.0.3
下载HA3.0.3解压并进入到源代码目录:
#./bootstrap
#./ConfigureMe configure
#make
#make install
D. 配置/etc/ha.d/ha.cf
=========ha.cf begin==============
logfacility local0
keepalive 500ms
deadtime 10
warntime 5
initdead 60
mcast eth0 225.0.0.1 694 1 0
auto_failback off
node db_node1.systemadmin.cn
node db_node2.systemadmin.cn
=========ha.cf end==============
注意,防火墙需要打开端口为694,目标Ip为225.0.0.1的udp通信
E. 配置/etc/ha.d/haresources
========haresource begin===========
db_node1.systemadmin.cn drbddisk Filesystem::/dev/drbd1::/data/dbdata::ext3 IPaddr::192.168.0.200/24/eth0 mysql
========haresource end===========
F.生成/etc/ha.d/authkeys
#( echo -ne "auth 1\n1 sha1 "; \
dd if=/dev/urandom bs=512 count=1 | openssl md5 ) \
> /etc/ha.d/authkeys
#chmod 0600 /etc/ha.d/authkeys
G. 编写MySQL启动脚本/etc/ha.d/resource.d/mysql
=========mysql being============
#!/bin/bash
#
# Author: ipaddr ( admin.net [#] 163.com )
#
. /etc/ha.d/shellfuncs
case "$1" in
start)
res=`/etc/init.d/mysqld start`
ret=$?
ha_log $res
exit $ret
;;
stop)
res=`/etc/init.d/mysqld stop`
ret=$?
ha_log $res
exit $ret
;;
status)
if [[ `ps -ef | grep '[m]ysqld'` > 1 ]] ; then
echo "running"
else
echo "stopped"
fi
;;
*)
echo "Usage: mysql {start|stop|status}"
exit 1
;;
esac
exit 0
=========mysql end============
F. 拷贝一些常用脚本
1. 从Heartbeat-3-0源码目录的heartbeat/lib/复制hb_standby, hb_takeover到/usr/lib/heartbeat 并设置为可执行.
2. 将Cluster agent的一些文件拷到/etc/ha.d/:
cp /usr/etc/ha.d/shellfuncs /etc/ha.d/
cp -rf /etc/ha.d/* /usr/etc/ha.d/
(这个操作很奇怪,Cluster Agent与HA使用不同的目录,但又要共用文件,不知在编译agent时是否可以使用--prefix=/来解决,由于编译时间实在太长,所有没有测试)
G. 使用:
1. 设置为自启动:
chkconfig mysqld off
chkconfig --add heartbeat
chkconfig heartbeat on
2. 手动切换两个节点:
/usr/lib/heartbeat/hb_takeover 将当前节点设为主节点
/usr/lib/heartbeat/hb_standby 将当前节点设为从节点
3. 查看HA状态
查看当前节点heartbeat状态:
#/usr/lib/heartbeat/heartbeat -s
查看当前节点heartbeat状态:
#/usr/bin/cl_status hbstatus
列出所有节点:
#/usr/bin/cl_status listnodes
(如果是64位系统,HA的安装目录通常为/usr/lib64/)
一些题外话:
个人觉得HA3.0还不够成熟,尤其是在编译安装时,非常麻烦,主要有几个小问题:
a. glue必须把version相关的注释掉才可以编译通过,很诡异;
b. 个人认为HA是一个整体,把它拆成三个软件包编译安装实在是很难理解;
c. 安装完后,还需要手动复制一些脚本文件,另外,agent和ha默认使用不同的/etc/目录也很郁闷;
d. 几个包都要从网络下载xml文件,编译过程实在太久,花了一个下午才把agent编译完成,为什么不把相关xml打包在源码中一起下载呢?
当然,瑕不掩玉,HA还是非常了不起的一个开源作品。
附 MySQL的DRBD文档:
[file]attachment/201008/1283093603_0.rar[/file]
The really right, modern and clean way to load modules in CentOS 5
# Load other user-defined modules
for file in /etc/sysconfig/modules/*.modules ; do
[ -x $file ] && $file
done
# Load modules (for backward compatibility with VARs)
if [ -f /etc/rc.modules ]; then
/etc/rc.modules
fi
The cleanest way therefore seems to be like so:
echo "modprobe some_module" > /etc/sysconfig/modules/something.modules
chmod +x /etc/sysconfig/modules/something.modules
This kind of files could even be installed from a RPM without needing any special pre-install/uninstall handling.
This probably also applies to various Flavor of Redhat and Fedora. Personally i prefer gentoos nice modules.autoload file.>>>>>>>>>>>>>>>>>>>>>