You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Redis Lua脚本调用TS.ADD报错:参数需为字符串或整数

Azure Redis TimeSeries Lua脚本C#执行报错问题解决

问题背景

在启用TimeSeries模块的Azure Redis缓存Enterprise E10实例中,通过redis-cli执行以下Lua脚本可正常运行,多次调用能为key1时间序列添加4个值为1的时间戳:

EVAL "redis.call('TS.ADD', KEYS[1], '*', ARGV[1], 'RETENTION', ARGV[2], 'ON_DUPLICATE', 'SUM', 'ENCODING', 'UNCOMPRESSED'); return redis.call('TS.RANGE', KEYS[1], '-', '+')" 1 key1 1 1800000

执行输出:

1) 1) (integer) 1693323424958
   2) 1
2) 1) (integer) 1693323485951
   2) 1
3) 1) (integer) 1693323528702
   2) 1
4) 1) (integer) 1693323531678
   2) 1

但在C# .NET控制台应用中调用相同脚本时,抛出错误:

StackExchange.Redis.RedisServerException: 'ERR Error running script (call to f_503fcb14af1e60051a54d3617d5265f753dfe423): @user_script:1: @user_script: 1: Lua redis() command arguments must be strings or integers'

原C#代码

private static readonly TimeSpan RETENTION_TIME = TimeSpan.FromMinutes(30);

private const string LUA_SCRIPT = @"redis.call('TS.ADD', KEYS[1], '*', ARGV[1], 'RETENTION', ARGV[2], 'ON_DUPLICATE', 'SUM', 'ENCODING', 'UNCOMPRESSED'); return redis.call('TS.RANGE', KEYS[1], '-', '+')";

private static async Task<int> AddTimestampReturnSumAsync(IDatabase db, string key, int retentionTime)
{
    RedisResult result = await db.ScriptEvaluateAsync(LUA_CMD, new RedisKey[] { key }, new RedisValue[] { retentionTime });
    Console.WriteLine(JsonSerializer.Serialize(result));
    return 0; // a placeholder, I actually want to return a sum of the values
}

调用代码:

int sum = await AddTimestampReturnSumAsync(redis.GetDatabase(), "key1", (int)RETENTION_TIME.TotalMilliseconds);

问题原因

  1. 参数传递不完整:原Lua脚本需要两个ARGV参数(ARGV[1]是要添加的数值1,ARGV[2]是保留时间),但C#代码中仅传递了保留时间,导致脚本执行时ARGV[1]缺失,Lua解析参数时出现类型错误。
  2. 脚本变量名笔误:代码中调用ScriptEvaluateAsync时使用的LUA_CMD未定义,实际定义的脚本变量是LUA_SCRIPT,这会导致编译或运行时错误。

修正后的代码

修正方法与参数传递

private static readonly TimeSpan RETENTION_TIME = TimeSpan.FromMinutes(30);

private const string LUA_SCRIPT = @"redis.call('TS.ADD', KEYS[1], '*', ARGV[1], 'RETENTION', ARGV[2], 'ON_DUPLICATE', 'SUM', 'ENCODING', 'UNCOMPRESSED'); return redis.call('TS.RANGE', KEYS[1], '-', '+')";

private static async Task<int> AddTimestampReturnSumAsync(IDatabase db, string key, int value, int retentionTime)
{
    // 传递完整的ARGV参数:第一个是要添加的数值,第二个是保留时间
    RedisResult result = await db.ScriptEvaluateAsync(LUA_SCRIPT, new RedisKey[] { key }, new RedisValue[] { value, retentionTime });
    
    // 解析TS.RANGE的结果并计算总和
    if (result.IsNull) return 0;
    var entries = (RedisResult[])result;
    int sum = 0;
    foreach (var entry in entries)
    {
        var parts = (RedisResult[])entry;
        sum += (int)parts[1];
    }
    return sum;
}

修正调用代码

int sum = await AddTimestampReturnSumAsync(redis.GetDatabase(), "key1", 1, (int)RETENTION_TIME.TotalMilliseconds);

说明

  • 确保Lua脚本的参数顺序与C#传递的RedisValue数组顺序完全对应,ARGV[1]对应数组第一个元素,ARGV[2]对应第二个元素。
  • 原子性需求:Lua脚本在Redis中是原子执行的,修正后的代码可以保证TS.ADD和TS.RANGE操作的原子性。

内容的提问来源于stack exchange,提问作者Alexander Farber

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 04:17:12