ZMcursor / ZMFilter

C实现的基于T-tree的高性能滤重器,同时支持Python和Java

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ZMFilter

C实现的基于T-tree的高性能超低内存占用的滤重器,同时支持Python2、Python3和Java

项目起源

这个项目起源于今日头条自媒体爬虫,当时滤重使用的是set。当自媒体号id超过5000万时,set占用内存已经超过3G(每个自媒体号id为long整型)。加上长度超过3000万的Queue,程序占用内存接近5G,采集速度也降至正常速度的五分之一不到。只有8G内存的服务器已经不堪重负,甚至无法运行新程序。于是写了一个FileQueue,将队列缓存到硬盘,去除了Queue的内存占用,将程序占用内存降至3G多。但程序效率问题得不到改善。经分析性能瓶颈出现在滤重上,爬取程序的id滤重非常频繁,至少2000次/s。在set不大时倒没问题,当set非常庞大时,相当多的hash值下形成非常长的链表,查找插入速度大大降低。且由于系统内存紧张,系统将set部分数据被换出到swap区,滤重时系统内存和swap区频繁的数据交换更加拖慢了程序的运行速度,导致滤重的速度降至正常的五分之一不到。当时有想换用Redis进行滤重,但公司同时有许多程序在用Redis,怕影响公司其他服务,于是作罢。最后只有先放弃采集新账号,去掉滤重,处理Queue中已有的账号。于是萌生开发一个通用,高性能,超高内存利用率的适用于千万级数据量的id滤重器

项目目标

  1. 高性能,至少达到10万/s的写入速度和50万/s的读取速度。
  2. 超高内存利用率,平均超过60%的内存利用率。这里的利用率计算公式是:数据大小/数据结构内存占用;例如5000万个8byte长整形id数据大小为:(5000w*8)/(1024*1024)=381.5M。如果内存利用率为50%,则数据结构内存占用为763M,只相当于原来的五分之一。
  3. 通用,支持Python2、Python3、Java,Linux、Windows平台,支持任何数据类型(但只支持固定字节长度的数据,所以非常适合id滤重)。

数据结构选择

  • 首先排除hash表,hash表对大数据量不友好,且内存利用率不高。
  • SkipList跳表,redis使用的数据结构,不熟悉,后期考虑实现,对比性能。
  • 树结构,B树相比于红黑树和AVL树,对于内存数据库没有性能优势。而红黑树比AVL树有插入速度优势,查找速度劣势。而本项目之所以选择AVL树,是因为90%以上的id都是重复的,添加较少。后期会添加红黑树实现,拓展程序适用范围。

T-tree

  • T-tree首先是一个平衡树
  • 传统树结构是每个节点保存一个值,此时内存利用率为(节点拥有指向父、左右孩子节点的指针,64位系统下指针占用8btye空间,每个id设为8byte):8/(8+8+8+8)=25%。这显然满足不了要求,所以选择每个节点保存T个值的T-tree数据结构。当T较大时,节点其他数据可以忽略。
  • T-tree每个节点最大保存T个值,当一个满节点插入一个值时,节点拆分为两个节点,每个节点保存一半的值,新节点插入后进行一次rebalance操作,保证树的平衡。
  • 除了初始时所有值加起来都无法填满根节点,其他任何时候,T-tree任一节点至少填充一半的值,不难得出T-tree内存利用率最低50%。
  • 由于每个节点保存多个值,添加不一定导致树增加新节点,插入新值导致节点拆分的概率处于(1/T,2/T)区间,,且开发中使用了一些trick,减少了节点拆分和拆分后树的rebalance操作的概率,从而大大减少rebalance的次数,提高了程序效率。
  • 每个节点保存连续的值一定程度上可以利用内存的局部性原理加快查找速度。

项目进度

  • 项目封装完成

编译运行

  • 编译需要GCC编译器
  • Java Windows下双击运行win_build.bat,Linux下运行linux_build.sh即可
  • Python 需要修改对应运行文件的头文件路径,Windows+Python2就是win_build_py2.bat,Windows+Python3就是win_build_py3.bat,然后就可以运行文件进行编译了

性能

  • 机器:Intel(R) Core(TM) i5-3210M @2.50GHz, 16GB RAM, Windows10 64位
  • 数据:id长度为8byte,随机写入1亿个不重复的id,随机读取1亿个id
  • Java:写入50万/s,读取50万/s (其实不加锁轻松可上百万/s的写入速度),占用1GB内存,内存利用率74% 测试中。。。

未来计划

  • 加入删除功能(没错,现在还无法删除值,因为它本来定位为滤重器。且删除操作会大大降低内存利用率)
  • 在C语言层面使用锁,实现节点锁,提升锁的细粒度

待续

About

C实现的基于T-tree的高性能滤重器,同时支持Python和Java

License:Apache License 2.0


Languages

Language:C 70.2%Language:Java 23.1%Language:Python 4.8%Language:Batchfile 1.1%Language:Shell 0.7%