首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PHP Predis:如何将‘Predis cli script load $LUA_SCRIPT`转换为Predis方法?

PHP Predis:如何将‘Predis cli script load $LUA_SCRIPT`转换为Predis方法?
EN

Stack Overflow用户
提问于 2016-04-21 13:34:27
回答 1查看 646关注 0票数 0

如何将redis-cli script load $LUA_SCRIPT转换为Predis方法?

下面是lua脚本:

代码语言:javascript
复制
local lock_key = 'icicle-generator-lock'
local sequence_key = 'icicle-generator-sequence'
local logical_shard_id_key = 'icicle-generator-logical-shard-id'

local max_sequence = tonumber(KEYS[1])
local min_logical_shard_id = tonumber(KEYS[2])
local max_logical_shard_id = tonumber(KEYS[3])
local num_ids = tonumber(KEYS[4])

if redis.call('EXISTS', lock_key) == 1 then
  redis.log(redis.LOG_INFO, 'Icicle: Cannot generate ID, waiting for lock to expire.')
  return redis.error_reply('Icicle: Cannot generate ID, waiting for lock to expire.')
end

--[[
Increment by a set number, this can
--]]
local end_sequence = redis.call('INCRBY', sequence_key, num_ids)
local start_sequence = end_sequence - num_ids + 1
local logical_shard_id = tonumber(redis.call('GET', logical_shard_id_key)) or -1

if end_sequence >= max_sequence then
  --[[
  As the sequence is about to roll around, we can't generate another ID until we're sure we're not in the same
  millisecond since we last rolled. This is because we may have already generated an ID with the same time and
  sequence, and we cannot allow even the smallest possibility of duplicates. It's also because if we roll the sequence
  around, we will start generating IDs with smaller values than the ones previously in this millisecond - that would
  break our k-ordering guarantees!
  The only way we can handle this is to block for a millisecond, as we can't store the time due the purity constraints
  of Redis Lua scripts.
  In addition to a neat side-effect of handling leap seconds (where milliseconds will last a little bit longer to bring
  time back to where it should be) because Redis uses system time internally to expire keys, this prevents any duplicate
  IDs from being generated if the rate of generation is greater than the maximum sequence per millisecond.
  Note that it only blocks even it rolled around *not* in the same millisecond; this is because unless we do this, the
  IDs won't remain ordered.
  --]]
  redis.log(redis.LOG_INFO, 'Icicle: Rolling sequence back to the start, locking for 1ms.')
  redis.call('SET', sequence_key, '-1')
  redis.call('PSETEX', lock_key, 1, 'lock')
  end_sequence = max_sequence
end

--[[
The TIME command MUST be called after anything that mutates state, or the Redis server will error the script out.
This is to ensure the script is "pure" in the sense that randomness or time based input will not change the
outcome of the writes.
See the "Scripts as pure functions" section at http://redis.io/commands/eval for more information.
--]]
local time = redis.call('TIME')

return {
  start_sequence,
  end_sequence, -- Doesn't need conversion, the result of INCR or the variable set is always a number.
  logical_shard_id,
  tonumber(time[1]),
  tonumber(time[2])
}



redis-cli script load $LUA_SCRIPT

我试过了

代码语言:javascript
复制
$predis->eval(file_get_contents($luaPath), 0);

代码语言:javascript
复制
class ListPushRandomValue extends \Predis\Command\ScriptCommand {
    public function getKeysCount() {
        return 0;
    }

    public function getScript() {
        $luaPath = Aa::$vendorRoot .'/icicle/id-generation.lua';
        return file_get_contents($luaPath);
    }
}
$predis->getProfile()->defineCommand('t', '\Controller\ListPushRandomValue');

$response = $predis->t();

但上面两个都显示了下面的错误。

代码语言:javascript
复制
ERR Error running script (call to f_5849d008682280eed4ec67b97ba50ae546fc5e8d): @user_script:19: user_script:19: attempt to perform arithmetic on local 'end_sequence' (a table value)
EN

回答 1

Stack Overflow用户

发布于 2016-11-09 23:59:04

首先,我要说的是,我不是LUA方面的专家,但我刚刚使用Redis和LUA脚本实现了简单的锁定,并注意到问题中的一些错误。

在Redis和LUA之间有一个转换过程需要检查:Conversion。我认为这将有助于纠正所给出的错误。

在此呼叫中:

代码语言:javascript
复制
$predis->eval(file_get_contents($luaPath), 0);

您传递脚本的内容和访问键,但不传递任何要计算的键。这个调用更正确:

代码语言:javascript
复制
$predis->eval(file_get_contents($luaPath), 4, oneKey, twoKey, threeKey, fourKey);

这实际上可能是导致上述错误的原因。希望这对将来的人有所帮助。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36760482

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档