說說在JAVA中使用Redis,以及Redis分佈鎖
阿新 • • 發佈:2019-01-26
只上程式碼和說明,其他的不講了,權當做個筆記。
該程式碼使用了1年多,在高併發的情況下並無問題,所以分享給大家。
package util; import java.io.UnsupportedEncodingException; import java.net.SocketTimeoutException; import com.system.PublicParameter; import net.sf.json.JSONObject; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; import redis.clients.jedis.exceptions.JedisConnectionException; public final class RedisUtil{ private static String ADDR = "XXX.XXX.X.XXX"; //Redis的埠號 private static int PORT = 6379; //訪問密碼 private static String AUTH = "XXXX"; //可用連線例項的最大數目,預設值為8; //如果賦值為-1,則表示不限制;如果pool已經分配了maxActive個jedis例項,則此時pool的狀態為exhausted(耗盡)。 private static int MAX_ACTIVE = 800; //控制一個pool最多有多少個狀態為idle(空閒的)的jedis例項,預設值也是8。 private static int MAX_IDLE = 100; //等待可用連線的最大時間,單位毫秒,預設值為-1,表示永不超時。如果超過等待時間,則直接丟擲JedisConnectionException; private static long MAX_WAIT = 50000; private static int TIMEOUT = 50000; //在borrow一個jedis例項時,是否提前進行validate操作;如果為true,則得到的jedis例項均是可用的; private static boolean TEST_ON_BORROW = true; public static JedisPool jedisPool = null; /** * 初始化Redis連線池 */ static { try { JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(MAX_ACTIVE); config.setMaxIdle(MAX_IDLE); config.setMaxWaitMillis(MAX_WAIT); config.setTestOnBorrow(TEST_ON_BORROW); jedisPool = new JedisPool(config, ADDR, PORT,TIMEOUT); } catch (Exception e) { e.printStackTrace(); } } /** * 獲取Jedis例項 * @return */ public synchronized static Jedis getJedis() { int timeoutCount = 0; while (true) // 如果是網路超時則多試幾次 { try { Jedis jedis = jedisPool.getResource(); return jedis; } catch (Exception e) { // 底層原因是SocketTimeoutException,不過redis已經捕捉且丟擲JedisConnectionException,不繼承於前者 if (e instanceof JedisConnectionException || e instanceof SocketTimeoutException) { timeoutCount++; System.out.println("getJedis timeoutCount="+timeoutCount); if (timeoutCount > 3) { break; } }else { break; } } } return null; } /** * 釋放jedis資源 * @param jedis */ public static void returnResource(final Jedis jedis) { if (jedis != null) { jedisPool.returnResource(jedis); } } public static void mset(String key,String value){ Jedis redis = getJedis(); try { redis.set(key, value); } catch (Exception e) { e.printStackTrace(); }finally{ jedisPool.returnResource(redis); } } public static String mget(String co_make,String key){ Jedis redis = getJedis(); String value=""; try { if(key.equals("")){ value=redis.get(co_make); }else{ if(redis.get(co_make)!=null){ net.sf.json.JSONObject json1 = net.sf.json.JSONObject.fromObject(redis.get(co_make).toString()); if(json1.get(key)!=null){ value=json1.getString(key); } } } } catch (Exception e) { e.printStackTrace(); }finally{ jedisPool.returnResource(redis); } return setNullToBanlk(value); } public static String mget(String key){ Jedis redis = getJedis(); String value=""; try { value=redis.get(key); } catch (Exception e) { e.printStackTrace(); }finally{ jedisPool.returnResource(redis); } return setNullToBanlk(value); } public static void mdel(String key){ Jedis redis = getJedis(); try { redis.del(key); } catch (Exception e) { e.printStackTrace(); }finally{ jedisPool.returnResource(redis); } } public static String setNullToBanlk(String name) { if (name == null) { name = ""; } return name != null ? name.trim() : ""; } public RedisUtil() { } public static void main(String[] args) { for (int i = 0; i < 3000; i++) { new Thread(new Runnable() { public void run() { Jedis redis = getJedis(); try { for (int i = 0; i < 1000; i++) { redis.mset("a", "1"); System.out.println("執行緒1成功==="+i); } } catch (Exception e) { e.printStackTrace(); } } }).start(); } } }
使用的jar包:
jedis-2.7.2.jar
commons-pool2-2.2.jar
jackson-core-asl-1.6.4.jar
再說說分佈鎖,這個比較重要,因為在分散式架構哦的併發情況下,如果有業務需要計算金額,或者計數,就需要用到分佈鎖
package com.qh_goal; import java.net.SocketTimeoutException; import java.util.Collections; import java.util.UUID; import net.sf.json.JSONObject; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; import redis.clients.jedis.exceptions.JedisConnectionException; public final class RedisUtil{ private static String ADDR = "xxx.xxx.x.xxx"; //Redis的埠號 private static int PORT = 6379; //訪問密碼 private static String AUTH = "xxxxxx"; //可用連線例項的最大數目,預設值為8; //如果賦值為-1,則表示不限制;如果pool已經分配了maxActive個jedis例項,則此時pool的狀態為exhausted(耗盡)。 private static int MAX_ACTIVE = 800; //控制一個pool最多有多少個狀態為idle(空閒的)的jedis例項,預設值也是8。 private static int MAX_IDLE = 100; //等待可用連線的最大時間,單位毫秒,預設值為-1,表示永不超時。如果超過等待時間,則直接丟擲JedisConnectionException; private static long MAX_WAIT = 50000; private static int TIMEOUT = 50000; //在borrow一個jedis例項時,是否提前進行validate操作;如果為true,則得到的jedis例項均是可用的; private static boolean TEST_ON_BORROW = true; public static JedisPool jedisPool = null; private static DistributedLock lock = null; /** * 初始化Redis連線池 */ static { try { JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(200); config.setMaxIdle(50); config.setMinIdle(8);//設定最小空閒數 config.setMaxWaitMillis(10000); config.setTestOnBorrow(true); config.setTestOnReturn(true); //Idle時進行連線掃描 config.setTestWhileIdle(true); //表示idle object evitor兩次掃描之間要sleep的毫秒數 config.setTimeBetweenEvictionRunsMillis(30000); //表示idle object evitor每次掃描的最多的物件數 config.setNumTestsPerEvictionRun(10); //表示一個物件至少停留在idle狀態的最短時間,然後才能被idle object evitor掃描並驅逐;這一項只有在timeBetweenEvictionRunsMillis大於0時才有意義 config.setMinEvictableIdleTimeMillis(60000); jedisPool = new JedisPool(config, ADDR, PORT,TIMEOUT); lock = new DistributedLock(jedisPool); System.out.println("1"); } catch (Exception e) { e.printStackTrace(); } } /** * 獲取Jedis例項 * @return */ synchronized public static Jedis getJedis() { int timeoutCount = 0; while (true) // 如果是網路超時則多試幾次 { try { Jedis jedis = jedisPool.getResource(); return jedis; } catch (Exception e) { // 底層原因是SocketTimeoutException,不過redis已經捕捉且丟擲JedisConnectionException,不繼承於前者 if (e instanceof JedisConnectionException || e instanceof SocketTimeoutException) { timeoutCount++; System.out.println("getJedis timeoutCount="+timeoutCount); if (timeoutCount > 3) { break; } }else { break; } } } return null; } /** * 釋放jedis資源 * @param jedis */ public static void returnResource(final Jedis jedis) { if (jedis != null) { jedisPool.returnResource(jedis); } } public static void msetValue(String key,String value){ Jedis redis = getJedis(); try { redis.set(key, value); } catch (Exception e) { e.printStackTrace(); }finally{ redis.close(); redis = null; } } public static String mgetValue(String key){ Jedis redis = getJedis(); String value=""; try { value=redis.get(key); } catch (Exception e) { e.printStackTrace(); }finally{ redis.close(); redis = null; } return setNullToBanlk(value); } public static void mset(String key,String value,Jedis redis){ try { redis.set(key, value); } catch (Exception e) { e.printStackTrace(); }finally{ } } public static String mget(String co_make,String key){ Jedis redis = getJedis(); String value=""; try { if(key.equals("")){ value=redis.get(co_make); }else{ if(redis.get(co_make)!=null){ net.sf.json.JSONObject json1 = net.sf.json.JSONObject.fromObject(redis.get(co_make).toString()); if(json1.get(key)!=null){ value=json1.getString(key); } } } } catch (Exception e) { e.printStackTrace(); }finally{ } return setNullToBanlk(value); } public static String mget1(String key,Jedis redis){ String value=""; try { value=redis.get(key); } catch (Exception e) { e.printStackTrace(); }finally{ } return setNullToBanlk(value); } public static void mdel(String key){ Jedis redis = getJedis(); try { redis.del(key); } catch (Exception e) { e.printStackTrace(); }finally{ jedisPool.returnResource(redis); } } public static String setNullToBanlk(String name) { if (name == null) { name = ""; } return name != null ? name.trim() : ""; } public RedisUtil() { } static int n = 500; public static String seckill(String company_id,float value) { Jedis redis = getJedis(); String a = ""; try { // 返回鎖的value值,供釋放鎖時候進行判斷 String indentifier = lock.lockWithTimeout("resource", 5000, 1000); System.out.println("REDIS----1----"+Thread.currentThread().getName() + "獲得了鎖"); a = mget1(company_id,redis); mset(company_id, Float.parseFloat(a)-value+"",redis); a = mget1(company_id,redis); lock.releaseLock("resource", indentifier,redis); } catch (Exception e) { e.printStackTrace(); }finally{ redis.close(); redis = null; } return a; } public static String secGetValue(String company_id) { Jedis redis = getJedis(); String value = ""; try { // 返回鎖的value值,供釋放鎖時候進行判斷 String indentifier = lock.lockWithTimeout("resource", 5000, 1000); System.out.println("REDIS----1----"+Thread.currentThread().getName() + "獲得了鎖"); value = mget1(company_id,redis); lock.releaseLock("resource", indentifier,redis); } catch (Exception e) { e.printStackTrace(); }finally{ redis.close(); redis = null; } return setNullToBanlk(value); } public static void seckill2() { Jedis redis = getJedis(); try { // 返回鎖的value值,供釋放鎖時候進行判斷 String indentifier = lock.lockWithTimeout("resource", 5000, 1000); // System.out.println("REDIS----1----"+Thread.currentThread().getName() + "獲得了鎖"); // String a = mget1("a",redis); // mset("a", n--+"",redis); System.out.println("執行緒成功2==="+mget1("a",redis)); lock.releaseLock("resource", indentifier,redis); } catch (Exception e) { // TODO: handle exception }finally{ redis.close(); redis = null; } } public static void main(String[] args) throws InterruptedException { final String uuid = UUID.randomUUID().toString(); Jedis redis = getJedis(); mset("a", "0",redis); jedisPool.returnResource(redis); for (int i = 0; i < 500; i++) { new Thread(new Runnable() { public void run() { try { seckill("",1); seckill2(); } catch (Exception e) { e.printStackTrace(); } } }).start(); } } }
main方法中的seckill("",1); seckill2();兩個方法都使用了分散式鎖。
大家先看程式碼,有疑問可以提出。