1. 程式人生 > >說說在JAVA中使用Redis,以及Redis分佈鎖

說說在JAVA中使用Redis,以及Redis分佈鎖

只上程式碼和說明,其他的不講了,權當做個筆記。

該程式碼使用了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();兩個方法都使用了分散式鎖。

大家先看程式碼,有疑問可以提出。