【发布时间】:2016-08-13 08:49:13
【问题描述】:
我需要一个 appengine 的访问统计模块来跟踪一些请求处理程序并将统计信息收集到 bigtable。我没有在 github 上找到任何现成的解决方案,Google 的示例要么过于简单(memcached frontpage counter with cron),要么过度杀伤(accurate sharded counter)。但最重要的是,其他地方讨论的 appengine-counter 解决方案都没有包含统计所需的时间组件(每小时、每天计数)。
要求:系统不需要 100% 准确,可以忽略 memcache 丢失(如果不常见)。这应该大大简化事情。这个想法是只使用内存缓存并按时间间隔累积统计信息。
用例:您系统上的用户创建内容(例如页面)。你想跟踪大约。 每小时或每天查看用户页面的频率。有些页面经常查看,有些则从不查看。您想按用户和时间范围查询。子页面可能有固定的 ID(查询主页上点击次数最多的用户)。您可能想要删除旧条目(查询年份=xxxx 的条目)。
class StatisticsDB(ndb.Model):
# key.id() = something like YYYY-MM-DD-HH_groupId_countableID ... contains date
# timeframeId = ndb.StringProperty() YYYY-MM-DD-HH needed for cleanup if counter uses ancestors
countableId = ndb.StringProperty(required=True) # name of counter within group
groupId = ndb.StringProperty() # counter group (allows single DB query with timeframe prefix inequality)
count = ndb.Integerproperty() # count per specified timeframe
@classmethod
def increment(class, groupID, countableID):
# increment memcache
# save hourly to DB (see below)
注意:groupId 和 countableId 索引对于避免查询中的 2 个不等式是必要的。 (查询一个 groupId/userId 和 chart/highcount-query 的所有可数:countableId 具有最高计数派生 groupId/user),在 DB 中使用祖先可能不支持图表查询。
问题是如何最好地将memcached计数器保存到DB:
- cron:示例文档 (example front-page counter) 中提到了这种方法,但使用在 cron 处理程序中硬编码的固定计数器 ID。由于没有对现有 memcache 键的前缀查询,因此确定在最后一个时间间隔内在 memcache 中创建了哪些计数器 ID 并且需要保存可能是瓶颈。
- task-queue:如果创建了一个计数器,则安排一个任务来收集它并将其写入 DB。 COST:队列处理程序保存数据时,每个使用的计数器有 1 个任务队列条目,每个时间粒度(例如 1 小时)有一个 ndb.put。似乎也是最有希望准确捕捉偶发事件的方法。
- increment(id) 执行时不经常:如果新的时间范围开始,则保存前一个时间范围。这需要每次增量至少 2 次 memcache 访问(获取日期、增量计数器)。一个用于跟踪时间范围,一个用于计数器。缺点:过期时间较长的突发计数器可能会丢失缓存。
- increment(id) 执行时不经常:概率性:如果随机 % 100 == 0 则保存到 DB,但计数器应具有均匀分布的计数事件
- increment(id) 执行时不经常:如果计数器达到例如100 然后保存到数据库
有没有人解决这个问题,设计这个的好方法是什么? 每种方法的弱点和优势是什么? 这里是否缺少替代方法?
假设:计数可能会稍微不准确(缓存丢失),counterID 空间很大,counterID 偶尔递增(有些每天一次,有些经常每天)
更新:1)我认为可以使用类似于任务队列的cron。只需使用 memcached=True 创建计数器的数据库模型,并在 cron 中为所有以这种方式标记的计数器运行查询。成本:1 次增量,cron 查询,1 次更新计数器。如果没有充分考虑,这似乎比任务方法更昂贵/复杂。
在别处讨论过:
- High concurrency non-sharded counters - 每个时间段不计数
- Open Source GAE Fast Counters - 每个时间范围内没有计数,与分片解决方案的性能相比很好,报告了由于 memcache 丢失而导致的预期损失
【问题讨论】: