我们每天都在构建从推文用户 ID 到该用户发布的推文的推文 ID 列表的映射。我们使用的存储引擎是 Percona xtraDB "5.1.63-rel13.4 Percona Server (GPL), 13.4, Revision 443"
我们对每秒行插入的最大吞吐量不满意。我们使用 xtraDB 处理推文的最大吞吐量约为每秒 6000 到 8000 条推文。(例如,如果我们必须从头开始重建数据,我们将不得不等待将近一天)
在大多数情况下,我们能够利用全部 twitter 数据(大约每秒 4000 到 5000 条推文)实时完成这项工作。
我们已将应用程序的瓶颈缩小到 MySQL InnoDB 插入。在我们的应用程序中,我们从磁盘读取提要并使用 jackson 解析它(每秒大约 30,000 条推文)。然后,我们的应用程序分批发送推文。对于生成这些推文的作者集,我们将它们划分为 8 个组(使用用户 id 模 8 进行简单划分)。为每个组分配一个表,并分配 1 个线程将数据写入该表。每天大约有 2600 万唯一用户生成这些推文,因此每个表大约有 400 万行。对于一组用户,我们只使用一个事务进行读取和更新。组大小是运行时可调的。我们尝试了从 8 ~ 64000 的各种大小,我们确定 256 是一个很好的批量大小。
我们表的模式是
CREATE TABLE `2012_07_12_g0` ( `userid` bigint(20) NOT NULL, `tweetId` longblob, PRIMARY KEY (`userid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8
其中 tweetId 是推文 ID 长整数的压缩列表,使用 Google snappy 压缩
每个线程使用
Select userid,tweetId from <tablename> where userid IN (....)
解析用户标识以回读数据,线程使用
INSERT INTO <tablename> (userid,tweetId) VALUES (...) ON DUPLICATE KEY UPDATE tweetId=VALUES(tweetId)
用新的 tweetid 更新行。
我们尝试过设置各种 XtraDB 参数
innodb_log_buffer_size = 4M
innodb_flush_log_at_trx_commit = 2
innodb_max_dirty_pages_pct = 80
innodb_flush_method = O_DIRECT
innodb_doublewrite = 0
innodb_use_purge_thread = 1
innodb_thread_concurrency = 32
innodb_write_io_threads = 8
innodb_read_io_threads = 8
#innodb_io_capacity = 20000
#innodb_adaptive_flushing = 1
#innodb_flush_neighbor_pages= 0"
所有表每天的表大小约为 8G,InnoDB 有 24GB 可供使用。
我们正在使用:
- 6 磁盘(关键 m4 SSD,512 GB,000F 固件)软件 RAID5。
- Mysql innodb数据,SSD分区上的表空间
- ext4 挂载 noatime,nodiratime,commit=60
- centos 6.2
- 太阳jdk 1.6.30
任何使我们的插入速度更快的提示将不胜感激,谢谢。