endTime then redis.call('HSET', redpacketKey, 'status', 2) return {0, "红包已结束", 0} end -- 检查是否已经抢过 local hasGrabbed = redis.call('SISMEMBER', userSetKey, userId) if hasGrabbed == 1 then return {0, "已经抢过该红包", 0} end -- 检查是否还有剩余 local leftAmount = tonumber(redpacket['left_amount']) local leftCount = tonumber(redpacket['left_count']) if leftCount <= 0 or leftAmount <= 0 then return {0, "红包已抢完", 0} end -- 计算红包金额 local amount = 0 local isFinished = 0 if leftCount == 1 then -- 最后一个红包,获得剩余所有金额 amount = leftAmount isFinished = 1 else -- 随机算法:二倍均值法,保证公平性 local maxAmount = leftAmount / leftCount * 2 amount = math.random(1, math.floor(maxAmount)) -- 确保金额不会超过剩余金额 if amount > leftAmount then amount = leftAmount end -- 检查是否是最后一个(由于浮点数计算可能有误差) if leftCount == 1 or (leftAmount - amount) < 0.01 then isFinished = 1 end end -- 更新红包数据 local newLeftAmount = leftAmount - amount local newLeftCount = leftCount - 1 redis.call('HSET', redpacketKey, 'left_amount', newLeftAmount) redis.call('HSET', redpacketKey, 'left_count', newLeftCount) -- 标记用户已抢 redis.call('SADD', userSetKey, userId) -- 如果抢完了,更新状态为已结束(2) if isFinished == 1 then redis.call('HSET', redpacketKey, 'status', 2) end return {1, tostring(amount), isFinished} LUA; } }