Redis查询键值并条件判断的Java实现



import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.BooleanSupplier;

@Component
public class LabCounterUtil {
    private final RedisTemplate<String, Object> redisTemplate;

    // Lua脚本:条件满足时INCR,不满足时DEL
    private static final RedisScript<Long> COUNTER_SCRIPT = new DefaultRedisScript<>(
            "if ARGV[1] == 'true' then " +
                    "  return redis.call('INCR', KEYS[1]) " +
                    "else " +
                    "  return redis.call('DEL', KEYS[1]) " +
                    "end",
            Long.class
    );

    public LabCounterUtil(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 对匹配的Redis Key执行条件计数或删除操作
     * @param keyPattern 键匹配模式(如"lab:*")
     * @param conditionSupplier 条件判断函数
     */
    public void processLabCounters(String keyPattern, BooleanSupplier conditionSupplier) {
        // 使用SCAN命令避免阻塞Redis
        List<String> matchingKeys = scanKeys(keyPattern);

        // 并行处理每个Key(根据实际情况调整)
        matchingKeys.parallelStream().forEach(key -> {
            boolean conditionMet = conditionSupplier.getAsBoolean();
            executeCounterScript(key, conditionMet);
        });
    }

    /**
     * 使用SCAN命令获取匹配的Key列表
     */
    private List<String> scanKeys(String pattern) {
        return redisTemplate.execute((RedisCallback<List<String>>) connection -> {
            List<String> keys = new ArrayList<>();
            Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions().match(pattern).count(1000).build());
            while (cursor.hasNext()) {
                keys.add(new String(cursor.next()));
            }
            cursor.close();
            return keys;
        });
    }

    /**
     * 执行Lua脚本实现原子操作
     */
    private void executeCounterScript(String key, boolean conditionMet) {
        redisTemplate.execute(
                COUNTER_SCRIPT,
                Collections.singletonList(key),
                String.valueOf(conditionMet)
        );
    }


    // Lua脚本:查询key的值,大于3返回1,否则返回0
    private static final RedisScript<Long> CHECK_VALUE_SCRIPT = new DefaultRedisScript<>(
            "local value = redis.call('GET', KEYS[1]) " +
                    "if value and tonumber(value) > 3 then " +
                    "  return 1 " +
                    "else " +
                    "  return 0 " +
                    "end",
            Long.class
    );

    /**
     * 查询key的值,若大于3则返回true,否则返回false
     */
    public boolean checkValueGreaterThanThree(String key) {
        // 执行Lua脚本
        Long result = redisTemplate.execute(
                CHECK_VALUE_SCRIPT,
                java.util.Collections.singletonList(key)
        );

        // 将结果转换为布尔值
        return result != null && result == 1L;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值