我有kafka流包含用户与网站的交互,所以每个事件都有一个时间戳和关于事件的信息。对于每个用户,我希望在cassandra中存储最后k个事件(例如100个事件)。
我们的网站经常遇到机器人/大量用户,这就是为什么我们要限制事件,只是为了考虑“正常”用户。
我目前在Cassandra有当前的数据模型:
user_id, event_type, timestamp, event_blob
哪里
<user_id, event_type> = partition key, timestamp = clustering key
目前,我们在一个新事件发生时立即在cassandra中写一个新记录,然后我们去清理“较重”的分区(即事件计数>100)。这不是实时发生的,除非我们不清理沉重的分区,否则有时在读取时会出现不好的延迟。
对于这种情况,你有什么更好的table设计建议吗?有没有办法告诉cassandra最多只存储k个元素作为分区,并以fifo方式终止旧的元素?还是有更好的table设计我可以选择?
2条答案
按热度按时间gab6jxml1#
对于这种情况,你有什么更好的table设计建议吗?
在为这样的场景进行数据建模时,我建议使用一种模式,该模式使用以下三个方面:
表上的默认ttl设置。
按降序对时间分量进行聚类。
调整查询以使用时间戳上的范围,从不查询超过ttl的数据。
ttl公司:
稍后我们去清理“较重”的分区
清理工作(平均)还要多久?我要做的一件事是,在你的团队通常需要清理它们之前,将表上的ttl设置为最长时间。
聚类键,降序:
所以您的主键定义如下所示:
确保在时间戳上按降序进行聚类。
这一点与ttl结合使用很重要。在这里,您的墓碑位于分区的“底部”(排序时)
timestamp
最近的数据(您关心的数据)位于分区的“顶部”。范围查询:
最后,确保您的查询在
timestamp
.例如:如果今天是11号,我的ttl是5天,那么我可以查询最后4天的数据,而不必回拉墓碑:
rfbsl7qr2#
现有实现的问题是删除会创建逻辑删除,这最终会导致读取延迟。不建议创建太多的墓碑。
基于计数(每个分区的行数)的fifo实现是不可能的。对于您的用例,更好的方法是不要删除同一个表中的记录。使用spark将表迁移到新的temp表中,并删除迁移过程中的额外记录。比如:
1) 创建新表
2) 使用spark,从原始表中读取,迁移所有必需的记录(过滤额外的记录)并写入新的temp表。
3) 截断原始表。请注意,truncate操作不会创建逻辑删除。
4) 使用spark将temp表中的所有内容迁移回原始表。
5) 截断临时表。
您可以在应用程序的维护窗口中执行此操作(大约一个月一次),直到您可以使用每个分区限制100次的读取。