Redis+Luaスクリプトによる自己増分プライマリ・キーの生成

3812 ワード

一.概要
redisの2.6バージョンからluaスクリプトのサポートが追加されました.現在使用可能なライブラリは以下のとおりです.
  • base  lib
  • table  lib
  • string  lib
  • math  lib
  • struct  lib
  • cjson  lib
  • cmsgpack  lib
  • bitop  lib
  • redis.sha1hex  function

  • redisのluaスクリプトでosを実行するように.time()はエラーを報告し、osクラスライブラリはサポートされていません.
    二.自己増分プライマリ・キーの生成
    1.luaスクリプト
    local temp = 0
    local key = KEYS[1]
    local inc = ARGV[1]
    local exp = ARGV[2]
    if inc == nil then
    	inc = 1
    end
    if redis.call('EXISTS',key) == 1 then
    	temp = redis.call('GET',key) + inc
    	redis.call('SETEX',key,exp,temp)
    	return temp
    else
    	temp = temp + inc
    	redis.call('SETEX',key,exp,temp)
    	return temp
    end

    2.redisのevalsha呼び出しluaスクリプトによる自己増加プライマリ・キーの生成
    package com.icheetor.jedis;
    
    import java.util.Arrays;
    import java.util.List;
    
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPool;
    import redis.clients.jedis.util.Pool;
    
    public class CreateId {
    
    	private static Pool pool = null;
    	private static String create_id_sha = null;
    	
    	static{
    		pool = new JedisPool("127.0.0.1", 6379);
    		initCreateIdSha();
    	}
    	private static void initCreateIdSha() {
    		Jedis jedis = pool.getResource();
    		create_id_sha = jedis.scriptLoad(LoadLuaScriptUtil.loadLuaScript("/createId.lua"));
    		jedis.close();
    	}
    	/**
    	 *      1 id
    	 * @param sha1
    	 * @param key
    	 * @return
    	 */
    	private static String getId(String sha1,String key){
    		List keyList = Arrays.asList(key);
    		List valueList = Arrays.asList("1","5");
    		Jedis jedis = null;
    		try {
    			jedis = pool.getResource();
    			String res = jedis.evalsha(sha1, keyList, valueList).toString();
    			return res;
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			if(jedis != null){
    				jedis.close();
    			}
    		}
    		return "0";
    	}
    	public static String getCreateId(String key) {
    		if(create_id_sha == null) {
    			Jedis jedis = pool.getResource();
    			create_id_sha = jedis.scriptLoad(LoadLuaScriptUtil.loadLuaScript("/createId.lua"));
    			jedis.close();
    		}
    		return getId(create_id_sha, key);
    	}
    	public static void main(String[] args) {
    		System.out.println(getCreateId("tbl_test"));
    	}
    }
    

    evalshaは、luaスクリプトをメモリに事前にロードし、実行効率を向上させるためにshaの列を生成する必要があります.
    luaスクリプトをメモリにロードし、大きな文字列を生成し、scriptLoadメソッドで生成された大きな文字列をロードし、shaの列を生成します.luaスクリプトをロードする方法は、apacheのcommons-ioを使用する方法と、Googleのguavaツールクラスを使用する方法の2つです.コードは次のとおりです.
    package com.icheetor.jedis;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.Reader;
    
    import com.google.common.io.CharStreams;
    
    /**
     *   lua  ,       
     * @author iCheetor
     *
     */
    public class LoadLuaScriptUtil {
    
    	/**
    	 *   apache commons-io        
    	 * @param path
    	 * @return
    	 */
    	public static String loadLuaScript(String path){
    		String luaStr = null;
    		InputStream in = LoadLuaScriptUtil.class.getResourceAsStream(path);
    		Reader r = new InputStreamReader(in);
    		try {
    			luaStr = org.apache.commons.io.IOUtils.toString(r);
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		return luaStr;
    	}
    	/**
    	 *   guava        
    	 * @param path
    	 * @return
    	 */
    	public static String loadLuaScriptByGuava(String path){
    		String luaStr = null;
    		InputStream in = LoadLuaScriptUtil.class.getResourceAsStream(path);
    		Reader r = new InputStreamReader(in);
    		try {
    			luaStr = CharStreams.toString(r);
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		return luaStr;
    	}
    }
    

    redisは単一スレッドであるためidの自己増加を良好に保証でき,luaスクリプトでの計算,付与,読み出し操作にも原子性がある.