先说一下这个需求,需要判断某个域名是否在黑名单中。黑名单中的域名一旦设置,其下任何级的域名都认为是在黑名单中。
如黑名单中加入a.com,则a.com、www.a.com、1.2.3.a.com等都算进入黑名单。
如黑名单中加入com,则所有com域名都算进入黑名单。
下面出现的域名如带*都为违法域名
一开始我使用了like去做查询,如我要做判断的域名是www.a.com。SQL语句如下:
1 | select count (*) from tb_domain_blacklist where '.www.a.com' like concat( '%.' , domain) |
数据量少的情况下速度很快,我测试了一下10W黑名单时,大概在200毫秒左右。
虽然黑名单一般不会有这么多,但是我有研究的兴趣,所以就继续思考。
接下来想到的办法,10W黑名单时,耗时1-3毫秒左右。
我在表中加入了hash字段,设为索引,这里直接用了md5对域名进行处理。
1 2 3 4 | id hash domain 1 07ad577047b305c8a3a2e732eb271404 gp-***.com 2 8b32be4fdce459e135c207eb00426e8a milail-***.com 3 fd0857db5a002dff0d4f4643bd2a061d ni2.org |
然后在php中在查询前对域名进行处理。因为域名是用.来分割一段一段的,所以我把每一段的md5都计算出来,最终进行in查询。由于域名的一段一段不会太多,所以并不需要担心性能问题。
比如域名是www.baidu.com,那么我将com、baidu.com、www.baidu.com分别md5,最终代入in查询条件中。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | /** * 检查域名是否存在于黑名单。true存在,false不存在 * @param string $domain * @return boolean */ public function check( $domain ) { $domainSplitList = array_reverse ( explode ( '.' , $domain )); $tmpDomain = '' ; $hashes = []; foreach ( $domainSplitList as $domainItem ) { if (isset( $tmpDomain [0])) { $tmpDomain = $domainItem . '.' . $tmpDomain ; } else { $tmpDomain = $domainItem ; } $hashes [] = md5( $tmpDomain ); } return $this ->where( array ( 'hash' => array ( 'in' , $hashes )))-> count () > 0; } |
最终结果:
1 2 3 4 5 6 7 8 9 | [SQL] select count (*) from tb_domain_blacklist where `hash` in ( 'a' , 'b' , 'c' , '6c0470f373f41d4d54097676f0d96333' ); 受影响的行: 0 时间: 0.002s [SQL] select count (*) from tb_domain_blacklist where '.futu***.com' like concat( '%.' , domain) 受影响的行: 0 时间: 0.193s |
友情提示:垃圾评论一律封号...