我们的Python应用程序每天提供大约200万个API请求。我们从业务中得到了一项新要求,即生成报告,该报告应包含每天唯一请求和响应的计数。
最简单的选择是使用LPUSH和RPOP。但RPOP将一次返回一个值,这将影响性能。有没有办法从Redis那里做大量的流行音乐?
对该场景的其他建议将受到高度赞赏。
答案 0 :(得分:2)
一个简单的解决方案是使用redis pipelining
在单个请求中,您将被允许执行多个RPOP指令。 大多数redis驱动程序都支持它。在使用Redis-py的python中,它看起来像这样:
pipe = r.pipeline()
# The following RPOP commands are buffered
pipe.rpop('requests')
pipe.rpop('requests')
pipe.rpop('requests')
pipe.rpop('requests')
# the EXECUTE call sends all buffered commands to the server, returning
# a list of responses, one for each command.
pipe.execute()
答案 1 :(得分:1)
可以从不同的角度来看待这个问题。您的要求是:
要求......生成每天应包含唯一请求和响应计数的报告。
为什么不使用Redis功能来解决实际需求并避免批量LPUSH / LPOP的问题,而不是将请求存储在列表中然后对结果进行后处理。
如果我们只想记录唯一计数,那么您可能需要考虑使用排序集。
这可能是这样的:
# Collect the request statistics in the sorted set.
# The key includes date so we can do the "by date" stats.
key = 'requests:date'
r.zincrby(key, request, 1)
Python代码:
# ZSCAN: Iterate over all members in the set in batches of about 10.
# This will be unordered list.
# zscan_iter returns tuples (member, score)
batchSize = 10
for memberTuple in r.zscan_iter(key, match = None, count = batchSize):
member = memberTuple[0]
score = memberTuple[1]
print str(member) + ' --> ' + str(score)
# ZRANGE: Get all members in the set, ordered by score.
# Here there maxRank=-1 means "no max".
minRank = 0
maxRank = -1
for memberTuple in r.zrange(key, minRank, maxRank, desc = False, withscores = True):
member = memberTuple[0]
score = memberTuple[1]
print str(member) + ' --> ' + str(score)
解决实际需求 - 按天报告唯一请求的数量。
无需后处理任何内容。
可以执行其他查询,例如"热门请求"开箱即用:)
答案 2 :(得分:0)
另一种方法是使用Hyperloglog data structure。 那是especially designed for this kind of use case。
它允许计算具有低误差范围(0.81%)且内存使用率非常低的唯一项目。
使用HLL非常简单:
PFADD myHll "<request1>"
PFADD myHll "<request2>"
PFADD myHll "<request3>"
PFADD myHll "<request4>"
然后得到计数:
PFCOUNT myHll
答案 3 :(得分:0)
实际问题是关于Redis List,您可以使用lrange在一次调用中获取所有值,下面是解决方案;
xproto