去重之后统计条数_利用redis实现大数据量去重算法

本文介绍了在大数据量场景下,如何利用Redis的Set和Bitmap数据类型实现用户去重和统计。通过设置不同的Redis集合,进行去重操作,并在发送营销短信前精确统计可发送用户数量。Bitmap方案在节省空间的同时,需要注意性能和最大数据量限制,避免过度消耗资源。
摘要由CSDN通过智能技术生成

应用场景复现:

某服务商有数千万用户,要有计划的给用户手机发送营销短信。

  1. 服务商的用户是在不断变化的,每次发送的用户是从总量中按指定条件的用户画像进行筛选的
  2. 一个用户一个月内只允许收到一条营销短信
  3. 每次发送营销短信前要能较精确的统计出可发送到的用户数量
  4. 运营提供的手机号清单禁止发送

采用redis set数据类型程序业务设计:

  1. 每次待发送用户从库中导入redis set1
  2. 每天已发送的用户计入set2,set2按日期命名方便后续编程计算,如set20191010、set20191011
  3. 准备发送时将筛选的用户set1与最近30天的set2进行去重操作并写入set3
  4. 然后按set3的数据分页读取并发送,或者每次取固定条数发送并删除

采用redis bitmap数据类型程序业务设计:

  1. 方案与set数据类型类似,主要是bitmap整体存储空间更小,但需要考虑其性能和32位int范围可支持的数据量,非数字型的数据无法使用
  2. redis里bitmap实际是一个不超过512M的字符串,因此会变成一个大key操作

假设当前站点有5000W用户,那么一天的数据大约为50000000 / 8 / 1024 / 1 024 = 6MB

步骤一 将原始数据写入 key1

FOR $i

SETBIT key1 $i 1

End

步骤二 将去重数据写入 key 2

FOR $i

SETBIT key2 $i 1

End

步骤三 key1 与 key2 去重得出 key3

BITOP NOT key3 key1

BITOP OR key4 key3 key2

BITOP NOT key5 key4

其中 key5就是我们需要的排重后的数据

<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->select(0);

$sendCache = 'sendList';
$redis->setbit($sendCache, 10, 1);
$redis->setbit($sendCache, 11, 1);
$redis->setbit($sendCache, 12, 1);
$redis->setbit($sendCache, 102, 1);

$sendedCache = 'sendedList';
$redis->setbit($sendedCache, 11, 1);
$redis->setbit($sendedCache, 12, 1);
$redis->setbit($sendedCache, 13, 1);
$redis->setbit($sendedCache, 105, 1);

$sendList = $redis->get($sendCache);
$sendedList = $redis->get($sendedCache);

$sendList = unpack('C*', $sendList);
$sendedList = unpack('C*', $sendedList);

$count = 0;
$arr = [];
$n=0;
foreach($sendList as $key => $number) {
    $sendedNumber = $sendedList[$key];
    for($i = 0; $i < 8; $i++) {
        if(($number >> $i & 1) == 1) {
            if (($number >> $i & (~($sendedNumber >> $i))) == 1) {
                $count++;
                $arr[$n+7-$i] = 1;
            }
        }
    }
    $n += 8;
}

print_r($arr);
die;

实际验证是可行的,但是要注意 userId 的最大位数,尽量不要超过7位,不然会有很大的性能问题

下边两组数据测试数据,一个7位的userId,get 最大需要花费17s,一个8位的userId,get 最大需要花费170s

9999999 17.77s
99999999 170.57s

4fbe0b39abac1476d048a955f4b9ee43.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值