【问题标题】:loop get vs mget, Is there any performance difference in redis lua?loop get vs mget,redis lua有性能差异吗?
【发布时间】:2020-05-29 22:38:21
【问题描述】:

给定一个支持 lua 脚本的单实例 redis。一次调用'mget'和多次调用'get'获取多个key的值有什么性能差异吗?

【问题讨论】:

    标签: redis lua


    【解决方案1】:

    时间复杂度,两者的结果相同:O(N) = N*O(1)

    但是处理每个命令并将结果解析回 Lua 会产生开销。所以MGET会给你更好的性能。

    你可以衡量这个。下面的脚本接收一个key列表,一个调用GET多次,另一个调用MGET

    多次调用GET

    local t0 = redis.call('TIME')
    local res = {}
    for i = 1,table.getn(KEYS),1 do 
        res[i] = redis.call('GET', KEYS[i])
    end
    local t1 = redis.call('TIME')
    local micros = (t1[1]-t0[1])*1000000 + t1[2]-t0[2]
    table.insert(res,'Time taken: '..micros..' microseconds')
    table.insert(res,'T0: '..t0[1]..string.format('%06d', t0[2]))
    table.insert(res,'T1: '..t1[1]..string.format('%06d', t1[2]))
    return res
    

    呼叫MGET一次:

    local t0 = redis.call('TIME')
    local res = redis.call('MGET', unpack(KEYS))
    local t1 = redis.call('TIME')
    local micros = (t1[1]-t0[1])*1000000 + t1[2]-t0[2]
    table.insert(res,'Time taken: '..micros..' microseconds')
    table.insert(res,'T0: '..t0[1]..string.format('%06d', t0[2]))
    table.insert(res,'T1: '..t1[1]..string.format('%06d', t1[2]))
    return res
    

    多次调用GET 耗时51 微秒,而调用MGET 一次耗时20 微秒:

    > EVAL "local t0 = redis.call('TIME') \n local res = {} \n for i = 1,table.getn(KEYS),1 do  \n     res[i] = redis.call('GET', KEYS[i]) \n end \n local t1 = redis.call('TIME') \n local micros = (t1[1]-t0[1])*1000000 + t1[2]-t0[2] \n table.insert(res,'Time taken: '..micros..' microseconds') \n table.insert(res,'T0: '..t0[1]..string.format('%06d', t0[2])) \n table.insert(res,'T1: '..t1[1]..string.format('%06d', t1[2])) \n return res" 10 key:1 key:2 key:3 key:4 key:5 key:6 key:7 key:8 key:9 key:10
     1) "value:1"
     2) "value:2"
     3) "value:3"
     4) "value:4"
     5) "value:5"
     6) "value:6"
     7) "value:7"
     8) "value:8"
     9) "value:9"
    10) "value:10"
    11) "Time taken: 51 microseconds"
    12) "T0: 1581664542637472"
    13) "T1: 1581664542637523"
    > EVAL "local t0 = redis.call('TIME') \n local res = redis.call('MGET', unpack(KEYS)) \n local t1 = redis.call('TIME') \n local micros = (t1[1]-t0[1])*1000000 + t1[2]-t0[2] \n table.insert(res,'Time taken: '..micros..' microseconds') \n table.insert(res,'T0: '..t0[1]..string.format('%06d', t0[2])) \n table.insert(res,'T1: '..t1[1]..string.format('%06d', t1[2])) \n return res" 10 key:1 key:2 key:3 key:4 key:5 key:6 key:7 key:8 key:9 key:10
     1) "value:1"
     2) "value:2"
     3) "value:3"
     4) "value:4"
     5) "value:5"
     6) "value:6"
     7) "value:7"
     8) "value:8"
     9) "value:9"
    10) "value:10"
    11) "Time taken: 20 microseconds"
    12) "T0: 1581664667232092"
    13) "T1: 1581664667232112"
    

    【讨论】:

      【解决方案2】:

      在某些情况下会有所不同。

      MGET key [key ...] 时间复杂度:O(N),其中 N 是要检索的键的数量。
      GET key 时间复杂度: O(1)

      根据时间复杂度,GET效率更高。
      但是,将单个命令传递给 redis 和多次传递是有区别的。
      如果不使用池,则差异更大。

      当然,我建议根据您要处理的数据类型来使用它。
      您可以决定在 Google 地图中管理数据是否更有效。

      【讨论】:

        猜你喜欢
        • 2019-02-09
        • 1970-01-01
        • 1970-01-01
        • 2020-07-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-03
        相关资源
        最近更新 更多