1. 程式人生 > >redis實現 msetex和 getdel命令

redis實現 msetex和 getdel命令

tin 密文 mar call lsh exc [] cond take

1.redis本身不提供 msetex命令(批量增加key並設置過期時間)

class RedisExtend {
    private static final Logger logger = LoggerFactory.getLogger(RedisExtend.class);
    private static final int Port = 6379;
    private static final String Host = "192.168.1.1";
    private static final String PASS_WORD = "1234";
    private
static Jedis instance; /** * Lua腳本(msetex) */ private static final String LUA_SCRIPT_MSETEX = "local keysLen = table.getn(KEYS);" + "local argvLen = table.getn(ARGV);" + "local idx=1;" + "local argVIdx=1;" + "for idx=1,keysLen,1 do " + "argVIdx=(idx-1)*2+1; " + "redis.call(‘Set‘,KEYS[idx],ARGV[argVIdx],‘EX‘,ARGV[argVIdx+1]);" + "end " + "return keysLen;";
private static String LUA_SCRIPT_MSETEX_SHA1; /** * Lua腳本 (獲取後刪除) */ private static final String LUA_SCRIPT_GET_AND_DELETE = "local current = redis.call(‘get‘, KEYS[1]);\n" + "if (current) then\n" + " redis.call(‘del‘, KEYS[1]);\n" + "end\n" + "return current;";
private static String LUA_SCRIPT_GET_AND_DELETE_SHA1; static { LUA_SCRIPT_MSETEX_SHA1 = SHA1.encode(LUA_SCRIPT_MSETEX); LUA_SCRIPT_GET_AND_DELETE_SHA1 = SHA1.encode(LUA_SCRIPT_GET_AND_DELETE); } public static Jedis getInstance() { if (instance == null) { instance = initJedisLite().getTemplate().getJedisPool().getResource(); } return instance; } private static JedisLite initJedisLite() { return new JedisLite(Host, Port); } private static JedisTemplate jedisTemplate = initJedisLite().getTemplate(); public static long msetex(List<RedisKeyValue> redisKeyValues) { if (CollectionUtils.isEmpty(redisKeyValues)) { return 0; } int keyCount = redisKeyValues.size(); List<String> param = new ArrayList<>(keyCount * 3); for (RedisKeyValue item : redisKeyValues) { Assert.notNull(item, "KeyValue不允許為空"); Assert.hasLength(item.getKey(), "Key不允許為空"); param.add(item.getKey()); } for (RedisKeyValue item : redisKeyValues) { param.add(item.getValue()); param.add(Integer.toString(item.getSeconds())); } String[] paramArr = new String[param.size()]; param.toArray(paramArr); return execLunaScript(new RedisScript(LUA_SCRIPT_MSETEX, LUA_SCRIPT_MSETEX_SHA1), keyCount, paramArr, (o) -> (long) (o == null ? 0L : Integer.parseInt(o.toString()))); } public static String getdel(String key) { return execLunaScript(new RedisScript(LUA_SCRIPT_GET_AND_DELETE, LUA_SCRIPT_GET_AND_DELETE_SHA1), 1, new String[]{key}, (o) -> (o == null ? null : o.toString())); } private static <T> T execLunaScript(RedisScript redisScriptObj, int keyCount, String[] param, Function<Object, T> function) { try { return jedisTemplate.execute((Jedis jedis) -> function.apply(jedis.evalsha(redisScriptObj.sha1, keyCount, param))); } catch (redis.clients.jedis.exceptions.JedisNoScriptException ex) { return jedisTemplate.execute((Jedis jedis) -> function.apply(jedis.eval(redisScriptObj.script, keyCount, param))); } catch (Exception ex) { logger.error("執行redis腳本異常!", ex); return null; } } static class RedisScript { private String script; private String sha1; public RedisScript(String script) { this(script, SHA1.encode(script)); } public RedisScript(String script, String sha1) { this.script = script; this.sha1 = sha1; } } static class RedisKeyValue { private String key; private String value; private int seconds; public RedisKeyValue(String key, String value) { this(key, value, -1); } public RedisKeyValue(String key, String value, int seconds) { this.key = key; this.value = value; this.seconds = seconds; } public String getKey() { return key; } public String getValue() { return value; } public int getSeconds() { return seconds; } } }

2.調用代碼如下

    public static void main(String[] args) {
        long r = msetex(
                Arrays.asList(new RedisKeyValue("key1", "value1", 5000),
                        new RedisKeyValue("key2", "value2", 5000),
                        new RedisKeyValue("ke3", "value3", 5000)
                ));
        System.out.println("返回值:" + r);

        String key1Val = getdel("key1");
        System.out.println("key1的值:" + key1Val);
        key1Val = getdel("key1");
        System.out.println("key1的值:" + key1Val);
    }

3.返回結果如下

返回值:3
key1的值:value1
key1的值:null

4.sha1的代碼如下

import java.security.MessageDigest;


public class SHA1 {
    private static final char[] HEX_DIGITS = {‘0‘, ‘1‘, ‘2‘, ‘3‘, ‘4‘, ‘5‘,
            ‘6‘, ‘7‘, ‘8‘, ‘9‘, ‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘, ‘f‘};

    /**
     * Takes the raw bytes from the digest and formats them correct.
     *
     * @param bytes the raw bytes from the digest.
     * @return the formatted bytes.
     */
    private static String getFormattedText(byte[] bytes) {
        int len = bytes.length;
        StringBuilder buf = new StringBuilder(len * 2);
        // 把密文轉換成十六進制的字符串形式
        for (int j = 0; j < len; j++) {
            buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
            buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
        }
        return buf.toString();
    }

    public static String encode(String str) {
        if (str == null) {
            return null;
        }
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
            messageDigest.update(str.getBytes());
            return getFormattedText(messageDigest.digest());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

redis實現 msetex和 getdel命令