-
假设一个博客系统拥有 105 用户,每个用户平均有 10 篇的文章,每篇文章平均大小为 1kb,那么存储这些文章总共需要大约 1GB 的空间。
-
假设每个时间点有 103 名活跃用户,每个用户大概浏览 5 篇文章。
-
假设热点文章为 104,热点文章需要大约 10MB 的空间。
-
根据博客系统读多写少的特性,数据库端可以使用主从架构来实现读写分离,并且从服务器可以使用 MyISAM 这种读性能比较高的存储引擎;
-
根据博客系统热点文章突出的特性,使用 Redis 对热点文章进行缓存,并且使用 volatile-lru 这种最近最少未使用的策略来淘汰数据,以保证 Redis 存储的数据都为热点数据。
-
为了进行分页,需要记录文章总量,可以使用 Redis 来记录这种计数量。同样地,每篇文章都要记录阅读量,阅读量也可以使用 Redis 进行记录。
本次实现主要是对服务器端进行设计,从而提高系统的性能,因此功能方面实现的比较少,只具有阅读文章以及发布文章两个功能。
本系统运行在两台硬件一致和软件配置一致的云服务器上。
- CPU : 1 Intel(R) Xeon(R) CPU E5-26xx v4
- 内存 : Size: 1024 MB Type: RAM
- Linux : version 2.6.32-642.6.2.el6.x86_64
- MySQL : Ver 14.14 Distrib 5.1.73
- Redis : v=4.0.8
使用 Apache 的 ab 来进行压力测试。
为了防止网络时延的影响,因此在服务器端进行测试。
使用以下命令来使用 ab 工具,其中 -c 参数为并发数,-n 参数为请求数,-k 参数表示持久连接,http://localhost/dblog 就是待测试的网站。
ab -c 1000 -n 5000 -k http://localhost/dblog
在使用 Redis 进行缓存以及使用主从架构来实现读写分离之前,进行以上测试得到的部分结果如下,可以看出可以每秒平均的请求数为 715.81。
Time taken for tests: 6.985 seconds
Total transferred: 2645529 bytes
HTML transferred: 1530306 bytes
Requests per second: 715.81 [#/sec] (mean)
而在使用 Redis 以及主从架构之后,测试的结果如下,每秒平均的请求数以及提高到了 4839.62,大大提高了网站的并发请求数。
Time taken for tests: 1.033 seconds
Total transferred: 2696313 bytes
HTML transferred: 1559682 bytes
Requests per second: 4839.62 [#/sec] (mean)
主要涉及三个线程:binlog 线程、I/O 线程和 SQL 线程。
- binlog 线程:负责将主服务器上的数据更改写入二进制文件(binlog)中。
- I/O 线程:负责从主服务器上读取二进制日志文件,并写入中继日志中。
- SQL 线程:负责读取中继日志并重放其中的 SQL 语句。
主服务器用来处理写操作,而从服务器用来处理读操作。
读写分离常用代理方式来实现,代理服务器接收应用层传来的读写请求,然后决定转发到哪个服务器,例如 Amoeba 代理服务器。
MySQL 读写分离能提高性能的原因在于:
- 主从服务器负责各自的读和写,极大程度缓解了锁的争用;
- 从服务器可以配置 MyISAM 引擎,提升查询技能以及节约系统开销;
- 增加冗余,提高可用性。
在主从服务器都创建用于复制的账号,并且账号必须在 master-host 和 slave-host 都进行授权,也就是说以下的命令需要在主从服务器上都执行一次。
mysql > grant all privileges on *.* to repl@'master-host' identified by 'password';
mysql > grant all privileges on *.* to repl@'slave-host' identified by 'password';
mysql > flush privileges;
完成后最好测试一下主从服务器是否能连通。
mysql -u repl -h host -p
主服务器
[root]# vi /etc/my.cnf
[mysqld]
log-bin = mysql-bin
server-id = 10
从服务器
[root]# vi /etc/my.cnf
[mysqld]
log-bin = mysql-bin
server-id = 11
relay-log = /var/lib/mysql/mysql-relay-bin
log-slave-updates = 1
read-only = 1
重启 MySQL
[root]# service mysqld restart;
《高性能 MySQL》书上的配置文件中使用的是下划线,例如 server_id,使用这种方式有误在当前版本的 MySQL 中不能使用。
先查看主服务器的二进制文件名
mysql > show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000002 | 106 | | |
+------------------+----------+--------------+------------------+
然后配置从服务器
mysql > change master to master_host='master-host', > master_user='repl',
> master_password='password',
> master_log_file='mysql-bin.000002',
> master_log_pos=0;
在从服务器上启动复制
mysql > start slave
查看复制状态,Slave_IO_Running 和 Slave_SQL_Running 必须都为 Yes 才表示成功。
mysql > show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host:
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 106
Relay_Log_File: mysql-relay-bin.000006
Relay_Log_Pos: 251
Relay_Master_Log_File: mysql-bin.000002
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
...
使用了 ThinkPHP 框架自带的读写分离支持。