前情提要:
特别提醒,本文讨论的不是两张图片如何判断内容是否相似
实现的目标
抓取某论坛发布的主题和图片,根据图片特征判重标记。
硬件
云主机
阿里云(2c2g)服务器一台:某些服务的管理的公网出口(rabbitmq, 路由器管理等),基本不使用
阿里云 hk:proxy 出口
vultr sg:proxy 出口
物理机
db: i5-5200u/8g/hdd: mysql, rabbitmq
web:i5-4200u/8g/ssd: nginx/php/redis
nas:N3150/16g/hdd*n: samba
主要流程
列表页-详情页-图片 item:触发抓取
抓取:触发存储, 计算 md5 判重, 计算图片内容 hash
存储-校验-标记完成
计算 md5 判重-存储判重结果
计算图片内容 hash-redis 建立索引-查找 hash 重复-计算内容判重-存储判重结果
如何高效检索内容 hash 相近的图片
算了一些 hash,考虑汉明距离<=3 以内的作为 hash 接近的图片。
对于 128bit 的 hash,分为 4 组,如果汉明距离<=3, 至少有一组是完全一致的。
因此,将图片的内容 hash 分为四段存入 redis,建立倒排索引。
比如 id=123,hash=aaaabbbbccccdddd, 算法是 average,
存储这么几个数据到 redis:
sadd average:part1:aaaa => 123
sadd average:part1:bbbb => 123
sadd average:part1:cccc => 123
sadd average:part1:dddd => 123
这样下次搜索比如 aaaa000011112222 的判重的时候,就会命中
average:part1:aaaa 这个集合,从中取出 id 搜索对应的 hash 继续判重。
1M 量级的数据,四种 hash 算法,每种算法会分为 64k 个组,平均每个组 16 个 hash
那么对于一个新的图片需要判重 4 种 * 4 个分片 * 16 = 256 个 hash 比对
结合 redis 的读取时间,能压缩到几秒钟以内了。
存量数据花了三四天清洗完了,增量准实时。
剩下的结合索引优化等,继续提升效率。