我正在开发一个为数百万用户服务的广告技术系统。基本上,用户(非匿名用户(可以看到营销团队正在创建的不同广告。我们的营销团队希望能够为这些广告设置一些频率上限(以及他们已经制定的其他目标规则(
例如:
-
";如果用户在过去Y天内已经看到/点击该广告超过X次,则我们不应该为他显示该广告";
-
此外,广告可以按活动分组,因此也可以制定这样的规则:"如果用户在过去Y天内在该活动中观看了X次以上的广告,我们不应该向他显示这一点";。
此外,我们的营销部门可能想知道在过去Y天内有多少人查看/点击了某个特定的添加。
我们大约有20万转/分,我们的反应应该非常快。
我们查询的最小时间单位是一天,它不会改变。
一些问题和想法:
- DynamoDB适合吗
- 我考虑为每种事件类型创建一个表(单击/查看/关闭..(
- 配置主键的最佳方式是什么?我考虑将主键设置为用户id,将排序键设置为广告id和当前日期的组合{dd/mm/yyyy}
- 我考虑过使用";ADD";当用户单击/view/..时增加计数器的操作。。特定日期的广告。这些手术费用高吗?我有别的选择吗
- 我可以使用什么样的最佳方式来查询每个广告和活动(例如:"活动中所有广告的所有用户浏览量"或"获取过去40天内的所有广告浏览量"(
- 我还应该考虑哪些其他因素
非常感谢
按照您所说的规模和延迟,我建议使用基于主内存的数据存储,而不是持久数据存储,主要有三个原因:
- 对于一个用户id-广告id对,你会有非常频繁的计数更新(就像在几天内(,并且在广告活动关闭后,它永远不会有任何更新
- 你需要以相对可接受的低持久性(如果这一假设是错误的,请评论(尽快进行计数器更新,即使在可能发生的情况下(如失败(,你最终也会丢失缓存的数据,并且少数用户看到的广告超过了频率上限,这也不是世界末日
- 阅读和反更新将是比营销团队分析查询更常见的用例。因此,这将是我们优化的主要领域
- 对于200K RPM,我们每天有2.88亿个请求(假设频率上限重置的持续时间(。假设每个请求只产生1个广告,因此只有一个频率上限实体,我们的每日数据将限制在30GB以内(基于每个上限数据小于100字节(,这相对容易放入基于内存的数据存储或缓存中。这充其量也是一个教育性的猜测
我建议使用类似于redis的基于主存的数据存储,并将异步备份到任何数据库中(营销查询可以由任何合适的数据库维持(。如果您使用DynamoDB还有其他好处(比如您已经在使用基于AWS的系统或其他什么(,请务必检查提供类似控制的Dynamo DB Accelerator(DAX(。DAX在DDB上提供了一个缓存层,它将确保您可以具有低延迟,并自动负责更新DDB的最新状态。
最后按键:
选项1:Partition: userId Sort: adId-date
然而,这将使查询在该日期有多少人点击了这则广告需要扫描,即不理想。如果使用此选项,则首选选项2的辅助索引。
选项2:Partition: ad-id Sort: date-userId
除非我们的广告太少,大量用户看到一个广告(很少和巨大是相对的,但仍然如此(,否则这应该很好。我更喜欢这个而不是第一个。