我面临着加速我的应用程序的需求(用PHP编写,简单的GET服务),我决定将它从RDBMS方法转移到Redis。花了一周研究如何做到这一点,并考虑到我的关系数据库中有很多字段,我在redis中创建了这样的结构:
{nameOfTable:clientID:itemID}
,例如
SET clientSubjects:1:1 bigJSONStringHere1
SET clientSubjects:1:2 bigJSONStringHere2
SET clientSubjects:1:3 bigJSONStringHere3
SET clientSubjects:2:1 bigJSONStringHere4
SET clientSubjects:2:2 bigJSONStringHere5
SET clientSubjects:2:3 bigJSONStringHere6
等
我有大约2000万客户,每个客户有大约4-10个主题,所以它大约有1.5亿个密钥。
要查找所有客户的主题,每次我收到某个客户的请求时,我都必须使用SCAN
。我遇到了一个问题,当我把所有客户端加载到Redis时,命令
scan 0 match clientSubjects:{someID}:* count 100
返回:
1) "7241728"
2) (empty list or set)
而且......我的决定是在redis存储中查找密钥总数并将其用作COUNT
参数。
这看起来像:
local keyspace = redis.call("info", "keyspace")
local keysCount = keyspace:match("keys=(%d+),")
local result = redis.call("SCAN", 0, "match", "clientSubjects:" .. ARGV[1] .. ":*", "count", keysCount) --ARGV means I pass clientID to lua script
所以一切正常,但需要大约3秒才能执行!但我需要它几毫秒......我该怎么办?
答案 0 :(得分:1)
拥有2000万条记录,您需要大量内存来存储所有数据结构以及查询它的不同方式。
例如,要查找所有客户的主题,我会有一个名为clientSubjects:{clientID}
的集合或列表,其中包含主题ID的值。
您应该有不同的数据结构以适应不同的查询,并避免使用SCAN之类的东西,因为这不是最佳的。
在我看来,带有一些放置好的索引的关系数据库会更适合这种情况,它会为你节省大量的时间和金钱,因为索引通常会保存在内存中并且可以回退到磁盘上。
请记住,Redis要求您将所有数据存储在内存中,因此当您添加更多数据结构来解决不同的查询类型时,这将变得更加昂贵。