0
点赞
收藏
分享

微信扫一扫

Maven聚合与继承

瑾谋 2024-09-10 阅读 7

文章目录

使用背景

lua 脚本
所有操作封装到一起,依次执行,整个操作是原子性,不会被其它中断。
批量执行脚本

语法介绍

输出字符串

EVAL "return 'Hello'" 0

有参数

redis> EVAL "return ARGV[1]" 0 Hello
"Hello"
redis> EVAL "return ARGV[1]" 0 Parameterization!
"Parameterization!"

执行redis函数

1 代表key的参数个数
foo key
bar value
相当于set foo bar

> EVAL "return redis.call('SET', KEYS[1], ARGV[1])" 1 foo bar

缓存脚本

想当于把脚本缓存到客户端,这样能够减少每次执行时传输的数据量
SCRIPT LOAD 加载
EVALSHA 执行脚本

redis> SCRIPT LOAD "return 'Immabe a cached script'"
"c664a3bf70bd1d45c4284ffebb65a6f2299bfc9f"
redis> EVALSHA c664a3bf70bd1d45c4284ffebb65a6f2299bfc9f 0
"Immabe a cached script"

清除脚本

把服务器的缓存脚本清除

SCRIPT FLUSH c664a3bf70bd1d45c4284ffebb65a6f2299bfc9f

场景

更新json 对象

SET mykey '{"name": "原始名字", "age": 30}'
-- Lua 脚本开始
local json = require 'cjson' -- 确保 cjson 库可用

-- 查询 JSON 数据
local data = redis.call('GET', 'mykey')

if data then
    -- 解析 JSON 数据
    local jsonData = json.decode(data)

    -- 修改数据
    jsonData.name = '新的名字' -- 修改字段

    -- 将修改后的数据编码为 JSON 字符串
    local newData = json.encode(jsonData)

    -- 更新到 Redis
    redis.call('SET', 'mykey', newData)
    return '数据更新成功'
else
    return '没有找到数据'
end
-- Lua 脚本结束

实现计数器

-- Lua 脚本开始
local counter_key = KEYS[1] -- 计数器的键
local threshold = tonumber(ARGV[1]) -- 阈值

-- 获取当前计数
local current_count = tonumber(redis.call('GET', counter_key) or 0)

-- 增加计数
current_count = current_count + 1

-- 检查是否达到阈值
if current_count >= threshold then
    current_count = 0 -- 重置计数
end

-- 更新计数到 Redis
redis.call('SET', counter_key, current_count)

return current_count
-- Lua 脚本结束

spring 和lua 结合

lua 脚本定义

-- Lua 脚本
local user_ids = cjson.decode(ARGV[1]) -- 从参数中获取用户 IDs
local age_increment = tonumber(ARGV[2]) -- 从参数中获取年龄增量

local updated_users = {}

for _, user_id in ipairs(user_ids) do
    local user_key = 'user:' .. user_id
    local user_data = redis.call('HGETALL', user_key)

    if #user_data > 0 then
        local user_info = {}
        for i = 1, #user_data, 2 do
            user_info[user_data[i]] = user_data[i + 1]
        end

        -- 更新年龄
        local current_age = tonumber(user_info['age']) or 0
        user_info['age'] = current_age + age_increment

        -- 更新到 Redis
        redis.call('HMSET', user_key, 'name', user_info['name'], 'age', user_info['age'])
        table.insert(updated_users, user_info)
    end
end

return cjson.encode(updated_users)

spring 代码

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.util.List;

@Service
public class UserService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public List<Object> updateUserAges(List<String> userIds, int ageIncrement) {
        String script = loadLuaScript("scripts/updateUser.lua");
        return (List<Object>) redisTemplate.execute(
                new DefaultRedisScript<>(script, List.class),
                Collections.emptyList(),
                JsonUtils.toJson(userIds), // 将 List 转换为 JSON 字符串
                ageIncrement
        );
    }

    private String loadLuaScript(String path) {
        // 从文件加载 Lua 脚本
        try {
            return new String(Files.readAllBytes(Paths.get(path)), StandardCharsets.UTF_8);
        } catch (IOException e) {
            throw new RuntimeException("Failed to load Lua script", e);
        }
    }
}

举报

相关推荐

0 条评论