Pinboard 的 PHP/MySQL 架构

Pinboard 是一个提供在线书签服务的网站,和 Delicious 类似,不同的是 Pinboard 不是免费的,而且是从一开始就收费——采用有趣的渐进式收费,也就是说每增加一个人、后来的人就需多付0.001美元(按照 number of users * 0.001 的公式),这样的收费方式利用了人们的 “趁便宜赶快买,明天会更贵” 的心理,提供了一套独特的收费模式。让 VPSee 惊讶的是他们背后的技术出奇的简单,没有 Fotolog 那种 MySQL 集群+Memcached 集群,也没有 Netlog 那么复杂的数据库切分。在他们的 About 页面上,这位来自罗马利亚的创始人说:

Pinboard is written in PHP and Perl. The site uses MySQL for data storage, Sphinx for search, and Amazon S3 to store backups. There is absolutely nothing interesting about the Pinboard architecture or implementation; I consider that a feature!

数据

1亿6千多万个书签
5200多万个标签
9400多万个 urls
989 GB 的数据

平台

MySQL
PHP
Perl
Ubuntu
APC
Sphinx
Cron jobs
Amazon S3

硬件

服务器 1:64 GB, 主数据库(master),用来存储用户数据和搜索;
服务器 2:32 GB, 备用主数据库(failover master),用来爬 feeds 等一些后台任务
服务器 3:16 GB, web 服务器和从数据库(slave)
另外提一下,他们租用的这三台服务器有两台是从 DigitalOne 租用的,还有一台是从 ServerBeach 租的。

pingboard arch

架构

  • 他们运行的是 Ubuntu 操作系统;
  • 每台服务器上(一共3台)均保留一份整体数据库的拷贝;
  • 网站运行在 16GB 的服务器上,数据库完全放在内存里,页面装载时间提高了10倍;
  • 采用 master-master 数据库架构加上一个只读的 slave,所有写操作都在一个数据库上进行,第二个 master 数据库服务器主要用来计算,比如统计全局链接数,用户统计等;每天晚上数据库用 mysqldump 备份,然后备份的数据以压缩的形式储存在 Amazon S3 上。
  • Perl 脚本用来运行后台任务,比如下载 feeds、缓存页面、处理 email、生成 tag 云标签、备份数据等。他们选择 Perl 的理由是因为自己很熟悉而且有大量的库可以使用。像 “最受欢迎的书签” 这样的功能一般都是在晚上里通过后台的定时任务(cron job)完成。PHP 用来生成 HTML 页面,没有使用任何 templating engine,也没有使用任何框架(framework)。APC 用来做 PHP 缓存,没有用其他缓存技术,Sphinx 用来做搜索引擎。

经验

  • 使用成熟、老掉牙的技术,这样保证网站和程序运行快而且不会因为软件 bug 丢失数据。(VPSee 非常赞同这点,使用简单和可以理解的技术,我们相信技术是拿来用的,不是拿来炫的。)
  • 保持小规模会有趣得多,当你自己亲自提供客服支持和与客户打交道的时候你会发现很有价值;
  • 服务器成本用每 GB 内存(或存储)的价格来衡量,Pinboard 最初使用的是 Linode 和 Slicehost 的 VPS,后来发现 VPS 不够用,随着内存增大 VPS 越来越贵,价格不如独立服务器。(按照 VPSee 的个人经验,低端(<= 4GB)用 VPS 划算、高端(>=16GB)用独立服务器划算。)
  • 按照服务划分服务器,比如 web 服务器就拿来做 web 服务器,最好不要拿来干别的。

在 Debian 上源码编译和安装 Nginx+PHP+FastCGI+MySQL

前天有一位新客户购买我们的 VPS 后多次在上面源码编译和安装 Nginx+PHP+FastCGI+MySQL 不成功,遇到一些问题,总的来说分为两类,一个是包依赖问题,一个是 MySQL 目录的权限设置问题。昨天这位客户给我们发来一个论坛链接很细致的描述了他的安装过程和遇到的问题,可惜后面回帖的人都没说到重点,还有一位回帖人居然是我们的客户,呵呵,世界好小。VPSee 决定花点时间写个教程,可能对其他的 Linux/VPS 用户也有帮助。我们的 VPS 和那些使用 SolusVM 控制面板和模版的 VPS 服务商不同,我们自己制作 VPS 模版,采用最小化安装,不添加任何乱七八糟的东西,保持最简和干净,所以 VPS 上只装有必备的软件包和库,在编译 Nginx+PHP+FastCGI+MySQL 之前必须先安装一些编译时需要的软件包和库。

记得以前有位客户问过为什么我们的 VPS 上连基本的 gcc 工具都没有?为什么我们采用最小化安装?为什么我们没有提供那些都安装好的模版?有3个原因,1、不需要 gcc Linux 也可以运行,所以 gcc 不是必须的,这满足我们最小化的要求;2、安全,如果有人得到 Linux 普通用户帐号可以下载、通过 gcc 编译和运行一些后门代码以得到 root 权限或者干坏事,所以不是必要的话不推荐安装 gcc 等编译工具,同样的道理也适用我们对其他工具的要求;3、定制,每个人的要求是不同的,有的人喜欢 nginx,有的人喜欢 apache,所以我们采用最小化安装,把选择留给客户。我们认为最小化可以带来简单、安全和灵活。

下面的操作步骤在我们的 256MB Debian 5.0 VPS 上测试通过,Nginx/PHP/MySQL 都采用当前最新稳定源代码版本。

安装必备软件包

# aptitude install libtidy-dev curl libcurl4-openssl-dev libcurl3 \
libcurl3-gnutls zlib1g zlib1g-dev libxslt1-dev libzip-dev libzip1 \
libxml2 libsnmp-base libsnmp15 libxml2-dev libsnmp-dev libjpeg62 \
libjpeg62-dev libpng12-0 libpng12-dev zlib1g zlib1g-dev libfreetype6 \
libfreetype6-dev libbz2-dev libxpm-dev libmcrypt-dev libmcrypt4 \
sqlite3 bzip2 build-essential libreadline5-dev libedit-dev autoconf

编译和安装 MySQL

下载和编译 MySQL,但是先不要安装:

# wget http://mysql.mirror.rafal.ca/Downloads/MySQL-5.1/mysql-5.1.50.tar.gz
# tar zxvf mysql-5.1.50.tar.gz
# cd mysql-5.1.50

# ./configure \
 --prefix="/usr/local/mysql-5.1.50" \
 --enable-thread-safe-client \
 --with-extra-charsets=all
# make

需要改几个权限问题才能安装 MySQL,否则会出现 Access denied for user ‘root’@'localhost’ (using password: NO) 经典问题:

# groupadd mysql
# useradd -g mysql mysql

# cp support-files/my-small.cnf /etc/my.cnf
# vi /etc/my.conf
...
[mysqld]
user = mysql
...

# chown -R mysql:mysql /usr/local/mysql-5.1.50/
# chmod 777 /tmp

安装和启动 MySQl,修改 root 密码,登录 MySQL:

# cd mysql-5.1.50
# make install

# /usr/local/mysql-5.1.50/bin/mysql_install_db --user=mysql
# /usr/local/mysql-5.1.50/bin/mysqld_safe &
# /usr/local/mysql-5.1.50/bin/mysqladmin -u root password 'new-password'
# /usr/local/mysql-5.1.50/bin/mysql -u root -p

编译和安装 PHP

先下载 PHP 软件包,然后配置、编译,这里采用 php 5.2 分支的最新稳定代码:

# wget http://www.php.net/get/php-5.2.13.tar.bz2/from/us.php.net/mirror
# tar jxvf php-5.2.13.tar.bz2
# cd php-5.2.13

# ./configure \
 --prefix="/usr/local/php-5.2.13" \
 --with-mysql="/usr/local/mysql-5.1.50" \
 --with-gd \
 --with-ttf \
 --with-openssl \
 --enable-mbstring \
 --enable-fastcgi
# make && make install

编译和安装 Nginx

下载、配置和编译安装 nginx,注意编译 nginx 需要额外安装几个软件包:

# wget http://nginx.org/download/nginx-0.7.67.tar.gz
# tar zxvf nginx-0.7.67.tar.gz

# aptitude install libgcrypt11-dev libpcre3 libpcre3-dev libssl-dev

# cd nginx-0.7.67
# ./configure  --prefix="/usr/local/nginx-0.7.67"  --with-http_ssl_module
# make && make install

编译和安装 FastCGI

Nginx 需要 FastCGI 的支持才能运行 PHP 脚本,从 lighttpd 下载、编译和安装 spawn-fcgi:

# wget http://www.lighttpd.net/download/spawn-fcgi-1.6.2.tar.bz2
# tar jxvf spawn-fcgi-1.6.2.tar.bz2

# cd spawn-fcgi-1.6.2
# ./configure --prefix="/usr/local/php-5.2.13"
# make && make install

启动 FastCGI:

# /usr/local/php-5.2.13/bin/spawn-fcgi -a 127.0.0.1 -p 9000 \
-u www-data -g www-data -f /usr/local/php-5.2.13/bin/php-cgi \
-P /var/run/fastcgi-php.pid

编辑 Nginx 的配置文件,让 php 脚本被发送到 FastCGI 服务器由 FastCGI 处理,然后启动 nginx:

# vi /usr/local/nginx-0.7.67/conf/nginx.conf
...
        # fix nginx/php/fastcgi important security issue
        # http://cnedelcu.blogspot.com/2010/05/nginx-php-via-fastcgi-important.html
        location ~ \..*/.*\.php$ {
            return 403;
        }

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        location ~ \.php$ {
            #root           html;
            root           /usr/local/nginx-0.7.67/html;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /usr/local/nginx-0.7.67/html$fastcgi_script_name;
            include        fastcgi_params;
        }
...

# /usr/local/nginx-0.7.67/sbin/nginx -c /usr/local/nginx-0.7.67/conf/nginx.conf

安装 Nginx+FastCGI+PHP 完后测试一下是否 PHP 页面能否被正确解析,在 html 下创建一个含有 phpinfo(); 函数的文件,最后打开浏览器检查下面的 index.php 能否被正确执行。:

# vi /usr/local/nginx-0.7.67/html/index.php
phpinfo();

编译源代码需要消耗大量内存,我们只建议 256MB 或以上 VPS 用户使用源码方式安装。

NetBSD 上安装和配置 Nginx+PHP+FastCGI+MySQL

NetBSD 支持 n 种硬件架构,是地球上支持最多体系的系统;OpenBSD 来自 NetBSD,自称是地球上最安全的系统;FreeBSD 和 NetBSD 一样来自原始的 4.4 BSD-lite,但是 FreeBSD 现在主要支持 i386,在 PC 体系上 FreeBSD 比 NetBSD/OpenBSD 好很多,性能也最好。这三种 BSD 各有特点,和不同的 Linux 发行版一样每个系统都有很多粉丝,当然使用 FreeBSD 的人最多。VPSee 的一台老掉牙的 IBM ThinkPad 就在跑 FreeBSD,嗯,现在这台机器还在工作呢。虽然 NetBSD 的性能在 i386 上没有 FreeBSD 那么好,但是它的稳定性是非常的赞,Benchmarking BSD and Linux 这篇测试的作者说:

Please note that NetBSD was the only BSD that never crashed or panicked on me, so it gets favourable treatment for that.

我们上周五发布了 NetBSD VPS,我们鼓励用户自己动手安装 Nginx+PHP+FastCGI+MySQL 和熟悉 NetBSD 环境,这篇文章在我们的 NetBSD VPS 上搭建:

下载 pkgsrc

The NetBSD Packages Collection (pkgsrc) 是 NetBSD 下的基于源码的软件包管理系统,不同于 Debian/Ubuntu 上的 apt-get,pkgsrc 是基于源代码的方式管理软件包的,有点像 Gentoo 里面的 emerge 系统。pkgsrc 有三个分支,HEAD、pkgsrc-yyyyQqq 和 pkgsrc-wip,前两个是 pkgsrc 项目组的正式分支。我们在这里使用 pkgsrc-yyyyQqq(季度分支),下载和解压 pkgsrc 并放到合适的目录:

# ftp ftp://ftp.NetBSD.org/pub/pkgsrc/pkgsrc-2010Q2/pkgsrc-2010Q2.tar.bz2
# tar jxvf pkgsrc-2010Q2.tar.bz2
# mv pkgsrc /usr/

安装 Nginx+PHP+FastCGI+MySQL

编译和安装 PHP,注意编译 PHP 的时候需要加上 fastcgi 说明,这样 PHP 编译才会把 FastCGI 部分编译进去:

# vi /etc/mk.conf
PKG_OPTIONS.php = fastcgi

# cd /usr/pkgsrc/lang/php5
# make install clean clean-depends

配置 PHP:

# /usr/pkg/etc/php.ini
cgi.fix_pathinfo=1

编译和安装 FastCGI:

# cd /usr/pkgsrc/www/spawn-fcgi/
# make install clean clean-depends

编译和安装 Nginx:

# cd /usr/pkgsrc/www/nginx
# make install clean clean-depends

配置 Nginx:

# cp /usr/pkg/share/examples/rc.d/nginx /etc/rc.d/
# vi /usr/pkg/etc/nginx/nginx.conf
location / {
            root   share/examples/nginx/html;
            index  index.html index.htm index.php;
        }

...

location ~ \.php$ {
            root           html;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /usr/pkg/share/examples/nginx/html$f
astcgi_script_name;
            include        /usr/pkg/etc/nginx/fastcgi_params;
        }

把 Nginx 加到启动文件以便启动系统时自动启动:

# vi /etc/rc.conf
nginx=YES

编译和安装 MySQL:

# cd /usr/pkgsrc/databases/php-mysql
# make install clean clean-depends

# cd /usr/pkgsrc/databases/mysql5-server
# make install clean clean-depends

配置 PHP 以便加载 MySQL 动态连接库:

# vi /usr/pkg/etc/php.ini
extension=mysql.so

把 MySQL 加到启动文件以便启动系统时自动启动:

# cp /usr/pkg/share/examples/rc.d/mysqld /etc/rc.d/

# vi /etc/rc.conf
mysqld=YES

启动 FastCGI:

# /usr/pkg/bin/spawn-fcgi -a 127.0.0.1 -p 9000 -f /usr/pkg/libexec/cgi-bin/php
spawn-fcgi: child spawned successfully: PID: 18554

启动 Nginx:

# /etc/rc.d/nginx start
Starting nginx.

启动 MySQL 和设置 root 密码:

# /etc/rc.d/mysqld start

# /usr/pkg/bin/mysqladmin -u root -p password 'new-password'

测试

写一个 phpinfo() 文件放在 nginx 目录下,然后打开浏览器测试是否能正确访问 php 文件:

# vi /usr/pkg/share/examples/nginx/html/index.php


http://www.vpsee.com/index.php

用 Shell 脚本访问 MySQL 数据库

下午写了一个简单的 bash 脚本,用来测试程序,输入一个测试用例文件,输出没有通过测试的用例和结果,然后把结果保存到数据库里。如何在 bash 脚本里直接访问数据库呢?既然在 shell 里可以直接用 mysql 命令操作数据库,那么在 shell script 里也应该可以通过调用 mysql 来操作数据库。比如用下面的 bash shell 脚本查询数据库:

Bash

#!/bin/bash

mysql -uvpsee -ppassword test < < EOFMYSQL
select * from test_mark;
EOFMYSQL

如果需要复杂的数据库操作的话不建议用 shell 脚本,用 Perl/Python/PHP 操作数据库很方便,分别通过 Perl DBI/Python MySQLdb/PHP MySQL Module 接口来操作数据库。这里再给出这三种不同语言连接、查询数据库的简单例子(为了简单和减少篇幅删除一些不必要的代码):

Perl

#!/usr/bin/perl
use DBI;

$db = DBI->connect('dbi:mysql:test', 'vpsee', 'password');
$query = "select * from test_mark";
$cursor = $db->prepare($query);
$cursor->execute;
while (@row = $cursor->fetchrow_array) {
        print "@row\n";
}

Python


继续阅读 »

Fotolog 的 Solaris/MySQL 架构

Fotolog 是一个以图片为主的 SNS 网站,让 VPSee 好奇的是用 Solaris 的 Web 2.0 站点不多,看看 Fotolog 有没有什么新东西。

数据

数据和图片来源(2007):Fotolog: Scaling the World’s Largest Photo Blogging Community

超过1100万用户
超过24亿条评论
每个月超过35亿 PV 和 2000万独立访问,Alexa Top 20
总共有超过2亿张的图片,每天还有超过50万张照片上传
20%用户每天在 Fotolog 停留 24分钟
32台 MySQL 服务器和一个由30台 memcached 服务器组成的集群

技术平台

Solaris 10
MySQL
Apache
Java / Hibernate
PHP
Memcached
3PAR
IBRIX
CDN

MySQL

32台 MySQL 服务器被分成4个集群:User, GB (guest book), PH (photos), FF (friends and favorites lists)。每个集群又被分成一个 shard 集,并由一个应用服务器集做前端。每个 shard 集包括若干个 MySQL 服务器,一个只写的 Master-Master 配几个只读的 Slaves,应用服务器把读请求发给 Slaves,把写请求发给 Master。MySQL 只存储图像的 metadata,没人想要把图像存到数据库里吧?什么是 metadata?metadata 是 “data about other data”,如一张照片的 metadata 就是一些包括:作者,年份,照片说明,摄影设备等信息就是这张照片的 metadata。

继续阅读 »

用 VPS 给博客做镜像

对于一个每日 PV 不超过1万的小博客来说,性能不是问题,一般的 VPS 都可以搞定,稳定性远比性能要重要。服务器 down 掉,会导致博客不能访问,不能更新,长时间 down 的话会失去读者,影响自己的写作计划/情绪,影响pagerank等等。前段时间 Hyperv 报漏洞,导致 FsckVPS 的很多客户丢失重要数据,长时间都不能恢复。小博客/网站的性能不是那么重要,每天没有那么多的访问压力。

为了给博客增加可靠性,给博客做个简单镜像是必要的,幸运的是我们的要求不高,不需要那些什么实时热备份,均衡负载,透明切换等高科技,只需要每隔一段时间同步一下博客以及数据库就可以了,很少有人能坚持每天写一篇博客,能每天写两篇就算牛博了,所以每天同步一次就够了。这里将讨论如何用 rsyn,ssh 和 mysqldump 来同步博客和数据库。

约定

为了更好的描述细节,这里作以下约定:

继续阅读 »

FreeBSD 上安装配置 Nginx+PHP+FastCGI+Mysql

freebsd

在 VPS 里很少看见 FreeBSD 的踪影,主要原因是因为两大开源虚拟系统 Xen 和 OpenVZ 对 FreeBSD 都不是那么友好:(,OpenVZ 不能支持非 Linux 内核的操作系统,Xen 对 FreeBSD 的支持不太好(也可以说FreeBSD 对 Xen 的支持不好)。最近 VPSee 从 Advantagecom 订了一个 256MB 的 Xen VPS,想在上面试试 FreeBSD 先,Advantagecom 不提供换操作系统的面板,每次都要提交 ticket 换系统好麻烦,而且一个月只能换一次系统。VPSee 打算先用一个月的 FreeBSD,然后再换成 Linux。就目前 VPS 的状况来说,VPSee.com 还是推荐使用 Linux,对于 VDS 或者自己的服务器来说,Linux 和 FreeBSD 都是很棒的操作系统。

安装所需软件

FreeBSD上 有2种安装软件的方法:一种是二进制安装;另一种是源代码安装(Ports collection)。

二进制安装所需软件:

# /usr/sbin/pkg_add -r -v mysql51-server
# /usr/sbin/pkg_add -r -v nginx
# /usr/sbin/pkg_add -r -v php5
# /usr/sbin/pkg_add -r -v php5-mysql
# /usr/sbin/pkg_add -r -v lighttpd


继续阅读 »

64MB VPS 上优化 MySQL

mysql

MySQL 是一个很棒的 open source 数据库引擎,大部分的网站和博客都是由 MySQL 驱动的。MySQL 的默认安装占用的内存资源比较大(相对于一个只有 64MB 的 VPS来说),优化 MySQL 可以减少内存消耗,把更多的内存省下来留给其他程序。

MySQL 的配置文件在 /etc/mysql/my.cnf(Debian 5),为了方便调整配置,MySQL 为小资源系统提供了一个叫做 my-small.cnf 的配置文件,是给小于 32MB 内存的服务器设置的。我们可以在这个配置文件的基础上作小部分的调整。

先找到 /usr/share/doc/mysql-server-5.0/examples/my-small.cnf,然后覆盖 /etc/mysql/my.cnf(Debian)。如果是 CentOS 5 的话,路径是:/usr/share/doc/mysql-server-5.0.45/my-small.cnf,覆盖 /etc/my.cnf。

参数说明

如果不使用 BDB table 和 InnoDB table 的话,加入下面2行关闭不需要的表类型很有必要,关闭 innodb 可以省下大量内存,虽然 InnoDB 好处多多但是在一个64MB的 VPS 上并不能体现出来,并且很占内存。

skip-bdb
skip-innodb


继续阅读 »

CentOS 5 上配置 Trac 和 Subversion

trac

这是一篇很久以前做项目的时候写的笔记,以前很多笔记都是记在一个一个 txt 里或者干脆不记用到了就去 google 搜,现在有了一个记笔记的好地方:),嗯,就是这个博客。关于 trac 和 subversion 的介绍可以 google 一大堆出来,这里就不赘述了,个人认为 trac 和 subversion 非常适合小型团队或者创业小公司用来管理源代码,追踪 bug,trac 还集成了一个 wiki,可以用来管理文档,发布网页,功能很强大,全 web based 的。很多 open source 项目以及一些欧美小公司都是用 trac + subversin 这个组合来管理项目的。

这里有个问题,为什么装了 lighttpd 后还需要 apache 呢? 原因是 lighttpd 现在还没有 svn-dav 模块,只有 apache 有,所以如果要集成 subversion 的话还需要 apache 的支持,当然只配置 apache 来同时处理 web 和 svn 也是可以的。不过这里用 lighttpd 来处理 web,apache 的 svn-dav module 来处理 svn 部分。

安装必要的软件包

首先下载并且安装必要的软件包

yum install mysql mysql-server MySQL-python
yum install subversion
yum install httpd mod_dav_svn
rpm -ivh lighttpd-1.4.13-3.fc5.i386.rpm lighttpd-fastcgi-1.4.13-3.fc5.i386.rpm
rpm -ivh clearsilver-0.10.4-2.el5.rf.i386.rpm
rpm -ivh python-clearsilver-0.10.4-2.el5.rf.i386.rpm
tar zxvf trac-0.10.4.tar.gz; cd trac-0.10.4; python ./setup.py install


继续阅读 »