zoukankan      html  css  js  c++  java
  • redis实现 msetex和 getdel命令

    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]);
    " +
                        "if (current) then
    " +
                        "    redis.call('del', KEYS[1]);
    " +
                        "end
    " +
                        "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);
            }
        }
    }
  • 相关阅读:
    C++调用外部应用程序
    SVN文件加锁
    vs ComboBox显示多行
    __slots__ Python Class限制添加属性
    Python数据分析之pandas学习
    整理Lua和Unity和Lua交互文章链接
    [整理]Unity3D游戏开发之Lua
    ping telnet ssh netstat
    java rpc
    css 手机适配
  • 原文地址:https://www.cnblogs.com/zhshlimi/p/9642218.html
Copyright © 2011-2022 走看看