`

实战低成本服务器搭建千万级数据采集系统

阅读更多

上一篇文章《社会化海量数据采集框架搭建》提到如何搭建一个社会化采集系统架构,讲架构一般都比较虚,这一篇讲一下如何实战用低成本服务器做到日流水千万级数据的分布式采集系统。

有这样一个采集系统的需求,达成指标: 需要采集30万关键词的数据 、微博必须在一个小时采集到、覆盖四大微博(新浪微博、腾讯微博、网易微博、搜狐微博)。为了节约客户成本,硬件为普通服务器:E5200 双核 2.5G cpu, 4 G DDR3 1333内存,硬盘 500G SATA 7200转硬盘。数据库为mysql。在这样的条件下我们能否实现这个系统目标?当然如果有更好的硬件不是这个文章阐述的内容。现通过采集、存储来说明一下如何实现:

一、采集,目标是在一个小时内把30万关键词对应的数据从四大微博采集下来,能够使用的机器配置就是上面配置的普通服务器。采集服务器对硬盘没有太多要求,属于cpu密集型运算,需耗费一些内存。评估下来硬件资源不是瓶颈,看下获取数据的接口有什么问题?

  • 1、通过各大微博的搜索api。就比如新浪微博API针对一个服务器IP的请求次数,普通权限限制是一个小时1w次,最高权限合作授权一个小时4w次。使用应用时还需要有足够的用户,单用户每个应用每小时访问1000次,最高权限4w次需要40个用户使用你的应用。达到30w关键词,至少需要8个应用,如果每个关键词需要访问3页,总共需要24个合作权限的应用。实际操作我们是不可能为这个项目做到开发24个合作权限的应用,所以这个方式不是很合适。新浪微博API限制参考链接

  • 2、通过各大微博的最新微博收集数据,微博刚推出的时候,各大微博都有微博广场,可以把最新的微博都收集下来,然后通过分词,如果出现了30万关键词中的一个就留下,其他就丢弃掉。不过现在除了腾讯微博和搜狐微博有微博广场类似的功能,新浪微博和网易微博已经没有这项功能了。另按照新浪微博之前公布的数据,注册用户已经超过5亿,每小时超过1亿条微博,如果全量采集对数据存储是个大的考验,也需要大量的系统资源,实际采集了一亿条,也许就1000w条有用,浪费了9000w条数据的资源。

  • 3、通过各大微博的网页搜索,可见即可抓的方式,结合反监控系统模块模拟人的正常行为操作,搜索30万关键词数据,使资源最大化利用。为了保证在一个小时采集到,需要采用分布式多线程模式抓取,并发采集。并发的时候不能从同一个ip或者同一个ip网段出去,保证对方不会监测到我们的爬虫。

我们最后采用了第三种方式,目前运行状况为通过30w关键词搜索得到的所有微博加在一起总量1000多w条每天,新浪和腾讯最多,新浪微博略胜一筹。使用了6台普通PC服务器,就算一台机器7000元,总共4万元硬件设备解决采集硬件问题。整体部署图为:

海量采集系统部署图

二、存储,采集下来的数据如何处理?首先存储采集数据是个密集写的操作,普通硬盘是否能够支持,mysql数据库软件能否支持,未来量突然增加如何应对?再就是评估存储空间,每天增量这么多需要耗费大量的存储资源,如何存放并且易扩展。

    • 1、如何存储。正常来说我们上面配置的服务器,mysql使用myisam引擎一张表最多20w,使用innodb引擎最多400w,如果超过这个数量,查询更新速度奇慢。这里我们采用一个比较取巧的做法,使用mysql的innodb存储引擎做了一层缓存库,这个缓存库有两个缓存表,每个表只存储少于300w的数据,有一张表多于300w的数据就切换到另一张表插入直到超过300w再切换回去。切换成功后,把多于300w数据的表truncate掉,记得一定要没有数据插入的时候再truncate,防止数据丢失。这里一定要用truncate,不能使用delete,因为delete需要查询,要用到索引读写,并且delete还会写数据库log耗费磁盘IO,存储空间也没有释放。truncate和drop是操作数据库删除数据比较好的做法。由于有两个表作为数据插入表,使用数据库表的自增id并不太合适,需要一个高速的唯一自增Id服务器提供生成分布式ID。另数据库完全可以关闭写事务日志 ,提高性能,因为抓取的数据当时丢失再启动抓取就可以了, 这样数据库可以保持在一个比较高性能的情况完成插入操作。抓取缓存表结果如图:

抓取缓存表结构图

    • 2、存储空间。插入后的数据需要保存下来,不能在超过300w后被truncate掉了。我们需要有个程序在达到300万时被truncate掉之前把数据同步走,存放到另外一个库上(我们叫做结果库,结果库也是使用innodb引擎)。不过我们每天采集的数据1000多万,按天递增,mysql一张表一天就撑爆了,我们这个表不是写操作密集型,所以结果库可以存储多点数据,设定上限500w,但是500万还是存不下1000万数据。我们需要对mysql最终结果分库分表。将数据先按照时间分机器分库,再按照数据源分表,比如201301通过hash计算的数据存放在一个机器,201302通过hash计算在另一个机器。到了机器后再按照天或者半天分表,比如表名为 weibo_2013020101 、weibo_2013020112。weibo_2013020101表示2月1日上午一个表,weibo_2013020112表示2月1日下午一个表。光这样分了还是不够,1000w/2=500w,经不起压力扩展。我们还需要把表再拆分,比如weibo_2013020101 拆成 weibo_2013020101_1(新浪微博)、weibo_2013020101_2(腾讯微博)、weibo_2013020101_3(网易微博)、weibo_2013020101_4(搜狐微博)。这样一张表平均就存放 500w/4 = 125w 条数据,远远小于500w上限,还可以应对未来突发的增长。再从存储空间来算,就算一条微博数据为1k,一天 1000w*1k=10G,硬盘500G最多存放50天的数据,所以我们规划机器的时候可以挂接多一点硬盘,或者增加机器。结果库分表如图:

分库分表结构图

按照这样的架构,我们使用开源免费软件、低成本服务器搭建的千万级数据采集系统在生产运转良好。

原创文章,转载请注明: 转载自LANCEYAN.COM

本文链接地址: 实战低成本服务器搭建千万级数据采集系统

 
1
2
分享到:
评论
17 楼 jd2bs 2014-02-19  
一天1000万,一年下来就接近40亿数据了,每条数据1K的话,存储的数据和索引之类的也有10T了;用Mysql分库分表最后会疯掉的。

上10T的数据建议用Hadoop MapReduce+HBase来分析和处理

16 楼 saiyaren 2013-08-07  
我擦,头一次看到用关系型数据库做这个东西的……
15 楼 须等待 2013-08-07  
分享经验的好文章踩的人是个什么心态呢。。真是有病,LZ自己给自己点个赞,踩得都看不到了
14 楼 lanceyan 2013-08-06  
须等待 写道
lanceyan 写道

感觉这种设计耦合度比较高,以后做扩展会痛苦

LZ如何做的同步?一次同步大概花多少时间?


扩展痛苦怎讲?

同步是一个定时任务, 取模同步,比如当前缓存表为 1、2、3、4、5,假设两个同步线程,1线程同步1、3、5,  2线程同步2、4,同步完了 1线程记录下当前最后的id为5,2线程记录下4。同步完了休眠5s,继续从 5、4开始同步。


嗯,我是比较好奇你们这个经验值:同步大概300W数据,需要多少时间



两个线程 2-3分钟 ,同步这块不是瓶颈
13 楼 须等待 2013-08-06  
lanceyan 写道

感觉这种设计耦合度比较高,以后做扩展会痛苦

LZ如何做的同步?一次同步大概花多少时间?


扩展痛苦怎讲?

同步是一个定时任务, 取模同步,比如当前缓存表为 1、2、3、4、5,假设两个同步线程,1线程同步1、3、5,  2线程同步2、4,同步完了 1线程记录下当前最后的id为5,2线程记录下4。同步完了休眠5s,继续从 5、4开始同步。


嗯,我是比较好奇你们这个经验值:同步大概300W数据,需要多少时间
12 楼 lanceyan 2013-08-06  

感觉这种设计耦合度比较高,以后做扩展会痛苦

LZ如何做的同步?一次同步大概花多少时间?


扩展痛苦怎讲?

同步是一个定时任务, 取模同步,比如当前缓存表为 1、2、3、4、5,假设两个同步线程,1线程同步1、3、5,  2线程同步2、4,同步完了 1线程记录下当前最后的id为5,2线程记录下4。同步完了休眠5s,继续从 5、4开始同步。
11 楼 须等待 2013-08-06  
lanceyan 写道
须等待 写道
lanceyan 写道
须等待 写道
分库分表、保持小表,很棒的数据库实践经验。

LZ有没有考虑过直接用nosql这样的技术来做存储可能比mysql要更加轻松呢?比如HBase


恩,用过mongodb,不过由于我们机器内存太小,4G内存,用mongodb出现了很多问题。使用它的autosharding还是没有mysql这样自主控制来的痛快,hbase目前在测试中,将来会结合我们hdfs一起使用,hdfs保存离线,hbase保存经常更新的数据。


你们的自主控制的代码是嵌入到dao层里的么?有没有用中间件来完成分库分表的工作?



恩,嵌入到dao层封装,没有使用 tddl 类似的组件


感觉这种设计耦合度比较高,以后做扩展会痛苦

LZ如何做的同步?一次同步大概花多少时间?
10 楼 lanceyan 2013-08-06  
须等待 写道
814687491 写道
我觉得1000多万也没必要分得这么细。你按不同 微薄 加当天时间来分表就可以了!
感觉没必要用缓存表!

他们的爬虫应该是24小时不停的,不用缓存表的话可能在同步或者离线分析的时候对线上的效率有影响



须等待说的对,不用缓存表对读写会带来影响,保证这个表足够小可以不用担心万一某一天增加1500万影响性能。814687491 你说的按天分表我们中间也有,不过没在这个文章写出来哈:)
9 楼 lanceyan 2013-08-06  
须等待 写道
lanceyan 写道
须等待 写道
分库分表、保持小表,很棒的数据库实践经验。

LZ有没有考虑过直接用nosql这样的技术来做存储可能比mysql要更加轻松呢?比如HBase


恩,用过mongodb,不过由于我们机器内存太小,4G内存,用mongodb出现了很多问题。使用它的autosharding还是没有mysql这样自主控制来的痛快,hbase目前在测试中,将来会结合我们hdfs一起使用,hdfs保存离线,hbase保存经常更新的数据。


你们的自主控制的代码是嵌入到dao层里的么?有没有用中间件来完成分库分表的工作?



恩,嵌入到dao层封装,没有使用 tddl 类似的组件
8 楼 须等待 2013-08-06  
814687491 写道
我觉得1000多万也没必要分得这么细。你按不同 微薄 加当天时间来分表就可以了!
感觉没必要用缓存表!

他们的爬虫应该是24小时不停的,不用缓存表的话可能在同步或者离线分析的时候对线上的效率有影响
7 楼 814687491 2013-08-06  
除非结果表,除了插入数据外,还有很多频繁的操作!
6 楼 814687491 2013-08-06  
我觉得1000多万也没必要分得这么细。你按不同 微薄 加当天时间来分表就可以了!
感觉没必要用缓存表!
5 楼 须等待 2013-08-06  
lanceyan 写道
须等待 写道
分库分表、保持小表,很棒的数据库实践经验。

LZ有没有考虑过直接用nosql这样的技术来做存储可能比mysql要更加轻松呢?比如HBase


恩,用过mongodb,不过由于我们机器内存太小,4G内存,用mongodb出现了很多问题。使用它的autosharding还是没有mysql这样自主控制来的痛快,hbase目前在测试中,将来会结合我们hdfs一起使用,hdfs保存离线,hbase保存经常更新的数据。


你们的自主控制的代码是嵌入到dao层里的么?有没有用中间件来完成分库分表的工作?
4 楼 lanceyan 2013-08-06  
须等待 写道
分库分表、保持小表,很棒的数据库实践经验。

LZ有没有考虑过直接用nosql这样的技术来做存储可能比mysql要更加轻松呢?比如HBase


恩,用过mongodb,不过由于我们机器内存太小,4G内存,用mongodb出现了很多问题。使用它的autosharding还是没有mysql这样自主控制来的痛快,hbase目前在测试中,将来会结合我们hdfs一起使用,hdfs保存离线,hbase保存经常更新的数据。
3 楼 须等待 2013-08-06  
分库分表、保持小表,很棒的数据库实践经验。

LZ有没有考虑过直接用nosql这样的技术来做存储可能比mysql要更加轻松呢?比如HBase
2 楼 lanceyan 2013-08-06  
meizhiwen84 写道
1.首先,1000万条数据完全不明白你为什么整得这么复杂,我们mysql存1亿数据太常见。
2.你只说了采集过程存储数据,没说明你采集这么多数据之后,应用这么些数据的应用场景是什么,你分这么多的机器,每机器分这么多的表,我在想,你在查询或者统计的时候,你这种架构估计够你喝上N壶的。
3,如果数据增长一段时间后,你无限的分库分表,这....................
4。为什么有更好的方案不知道采用,还要选用这种老掉牙的分库分表。

说的不对,勿喷,随口说说而已


我回复一下,可能描述不是很清楚。
1、硬件使用的是普通PC服务器,1000万是每天的增量,一张表存储达到一千万不管是更新、查询还是删除都会奇慢无比。我们使用mysql做了两个东西,第一个是作为高速采集缓存数据库,做为缓存不一定用它,只是他比较稳定;第二个是作为我们常规查询数据服务器。关于分表分库是为了满足业务小范围时间段的查询,对于我们足够用也比较保险,后续处理没有写到文章,我们加上了搜索索引即时查询和hdfs离线处理。
2、你说的很对,关于场景确实没有描述清楚,我们主要是做分析处理,存放下来用于备份,统计处理使用hdfs+hadoop,查询使用搜索引擎。
3、无线分表分库主要是满足保存历史数据,保存下来可以冷备份
4、老掉牙但是对于自动备份和扩展还是足够用了,也比较稳定健壮:)  meizhiwen有什么建议哈
1 楼 meizhiwen84 2013-08-05  
1.首先,1000万条数据完全不明白你为什么整得这么复杂,我们mysql存1亿数据太常见。
2.你只说了采集过程存储数据,没说明你采集这么多数据之后,应用这么些数据的应用场景是什么,你分这么多的机器,每机器分这么多的表,我在想,你在查询或者统计的时候,你这种架构估计够你喝上N壶的。
3,如果数据增长一段时间后,你无限的分库分表,这....................
4。为什么有更好的方案不知道采用,还要选用这种老掉牙的分库分表。

说的不对,勿喷,随口说说而已

相关推荐

Global site tag (gtag.js) - Google Analytics