1. 程式人生 > >利用Redis實現應用程式主備

利用Redis實現應用程式主備

需要實現主備的每個任務都先進行爭奪主機,通過爭奪redis中的key值。Rredis需要搭建主備高可用。

搶到key值的程式為主機,可以開始任務,備機執行緒開始等待,過段時間再進行爭奪主機。一般情況下首先搶到key值的主機會一直執行任務直到主機異常,程式崩潰等錯誤發生時,備機才有可能搶到key值,變為主機。

Main:

import java.util.Date;
import java.util.UUID;

public class Test {

    private static final String CODE = UUID.randomUUID().toString();
    private static final Integer TIMEOUT = 10;

	public static void main(String[] args) throws InterruptedException {
		while (true) {
			execute();
		}
	}

	private static void execute() throws InterruptedException {
		String threadKey = "MainScanThread";
		String threadTimeKey = "MainScanTime";
		String oldUuid = RedisOpr.get(threadKey);
		String oldTime = RedisOpr.get(threadTimeKey);
		System.out.println("開始爭奪主機。。。");
		// 如果有其他程序在進行
		if (oldUuid != null && !oldUuid.equals(CODE)) {
			// 如果程序剛進行結束,並且其他執行緒一直在持續執行,那麼返回
			// 表示主機資訊失效時長
			if (oldTime != null && (new Date().getTime() - Long.parseLong(oldTime)) < TIMEOUT*10) {
				System.out.println("RecodeScanServiceJob 未奪取主機執行權");
				// 表示不是主機則睡眠兩倍時間再爭奪主機
				Thread.sleep(TIMEOUT * 2);
				return;
			}
		}
		RedisOpr.set(threadKey, CODE);
		// 儲存當前時間
		RedisOpr.set(threadTimeKey, String.valueOf(new Date().getTime()));
		System.out.println("奪取成功。。。");
		//開始執行任務

	}
}

 RedisOpr :Redis基本操作工具類

import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;

import redis.clients.jedis.Jedis;

/**
 * 
 * @ClassName: RedisOpr
 * @Description: TODO(redis基本操作類)
 * @author zoe 
 * @date 2018年3月12日 上午11:31:55
 *
 */
public class RedisOpr {

	private static Logger log = Logger.getLogger(RedisOpr.class);

	/**
	 * @Title: saveObject @Description: 儲存物件 @param key @param object @return
	 *         void @throws
	 */
	public static void saveObject(String key, Object object) {
		Jedis jedis = RedisUtil.getJedis();
		try {
			jedis.set(key.getBytes(), SerializeUtil.serialize(object));
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			RedisUtil.returnResource(jedis);
		}
	}

	/**
	 * @Title: set @Description: 儲存key值 @param key @param value @return void @throws
	 */
	public static void set(String key, String value) {
		Jedis jedis = RedisUtil.getJedis();
		try {
			jedis.set(key, value);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			RedisUtil.returnResource(jedis);
		}
	}

	/**
	 * @Title: @Description: 獲取key值 @param key @return void @throws
	 */
	public static String get(String key) {
		Jedis jedis = RedisUtil.getJedis();
		try {
			return jedis.get(key);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			RedisUtil.returnResource(jedis);
		}
		return null;
	}

	/**
	 * @Title: getObject @Description: 獲取物件 @param key @param object @return
	 *         void @throws
	 */
	public static Object getObject(String key) {
		Jedis jedis = RedisUtil.getJedis();
		try {
			byte[] object = jedis.get(key.getBytes());
			if (object == null) {
				return null;
			}
			return SerializeUtil.unserialize(object);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			RedisUtil.returnResource(jedis);
		}
		return null;
	}

	/**
	 * @Title: lpush @Description: 向連結串列末尾新增資料 @param key @param value @return
	 *         void @throws
	 */
	public static void lpush(String key, String value) {
		Jedis jedis = RedisUtil.getJedis();
		try {
			jedis.lpush(key, value);
		} catch (Exception e) {
			log.error(e.getMessage());
		} finally {
			RedisUtil.returnResource(jedis);
		}
	}

	/**
	 * @Title: rpush @Description: 向連結串列末位新增資料 @param key @param value @return
	 *         void @throws
	 */
	public static void rpushObject(String key, Object object) {
		Jedis jedis = RedisUtil.getJedis();
		try {
			jedis.rpush(key.getBytes(), SerializeUtil.serialize(object));
		} catch (Exception e) {
			log.error(e.getMessage());
		} finally {
			RedisUtil.returnResource(jedis);
		}
	}

	/**
	 * @Title: rpush @Description: 向連結串列末位新增資料 @param key @param value @return
	 *         void @throws
	 */
	public static void rpush(String key, String value) {
		Jedis jedis = RedisUtil.getJedis();
		try {
			jedis.rpush(key, value);
		} catch (Exception e) {
			log.error(e.getMessage());
		} finally {
			RedisUtil.returnResource(jedis);
		}
	}

	/**
	 * @Title: llen @Description: 獲得連結串列長度 @param key @return long @throws
	 */
	public static long llen(String key) {
		Jedis jedis = RedisUtil.getJedis();
		try {
			return jedis.llen(key.getBytes());
		} catch (Exception e) {
			log.error(e.getMessage());
		} finally {
			RedisUtil.returnResource(jedis);
		}
		return 0;
	}

	/**
	 * @Title: removeObject @Description: 刪除key @param key @return void @throws
	 */
	public static void removeObject(String key) {
		Jedis jedis = RedisUtil.getJedis();
		try {
			jedis.del(key.getBytes());
		} catch (Exception e) {
			log.error("error:" + e.getMessage());
		} finally {
			RedisUtil.returnResource(jedis);
		}
	}

	/**
	 * @Title: rPop @Description: 取出並刪除List最後一個元素 @param key @return String @throws
	 */
	public static String rPop(String key) {
		Jedis jedis = RedisUtil.getJedis();
		try {
			String object = jedis.rpop(key);
			if (object == null) {
				return null;
			}
			return object;
		} catch (Exception e) {
			log.error("error:" + e.getMessage());
		} finally {
			RedisUtil.returnResource(jedis);
		}
		return null;
	}

	/**
	 * @Title: lPop @Description: 取出並刪除List第一個元素 @param key @return String @throws
	 */
	public static String lPop(String key) {
		Jedis jedis = RedisUtil.getJedis();
		try {
			String object = jedis.lpop(key);
			if (object == null) {
				return null;
			}
			return object;
		} catch (Exception e) {
			log.error("error:" + e.getMessage());
		} finally {
			RedisUtil.returnResource(jedis);
		}
		return null;
	}

	/**
	 * @Title: isExistsKey @Description: 判斷key是否存在 @param key @return
	 *         boolean @throws
	 */
	public static boolean isExistsKey(String key) {
		Jedis jedis = RedisUtil.getJedis();
		try {
			return jedis.exists(key);
		} catch (Exception e) {
			log.error("error:" + e.getMessage());
		} finally {
			RedisUtil.returnResource(jedis);
		}
		return false;
	}

	public static void hset(String key, String field, String value) {
		Jedis jedis = RedisUtil.getJedis();
		try {
			jedis.hset(key, field, value);
		} catch (Exception e) {
			log.error("error:" + e.getMessage());
		} finally {
			RedisUtil.returnResource(jedis);
		}
	}

	/**
	 * @Title: getRedisQueueObject @Description: 獲得告警佇列物件 @param key @return
	 *         List<Integer> @throws
	 */
	@SuppressWarnings("unchecked")
	public static List<Integer> getRedisQueueObject(String key) {
		Jedis jedis = RedisUtil.getJedis();
		try {
			byte[] object = jedis.get(key.getBytes());
			if (object == null) {
				return null;
			}
			return (List<Integer>) SerializeUtil.unserialize(object);
		} catch (Exception e) {
			log.error("error:" + e.getMessage());
		} finally {
			RedisUtil.returnResource(jedis);
		}
		return null;
	}

	/**
	 * @Title: getRedisWarnState @Description: TODO(這裡用一句話描述這個方法的作用) @param
	 *         key @param 獲得告警佇列狀態 @return Integer @throws
	 */
	public static Integer getRedisWarnState(String key) {
		Jedis jedis = RedisUtil.getJedis();
		try {
			byte[] object = jedis.get(key.getBytes());
			if (object == null) {
				return null;
			}
			return (Integer) SerializeUtil.unserialize(object);
		} catch (Exception e) {
			log.error("error:" + e.getMessage());
		} finally {
			RedisUtil.returnResource(jedis);
		}
		return null;
	}

	/**
	 * @Title: getAllKeyByPattern @Description: 通過正則表示式獲得key @param pattern @return
	 *         List<String> @throws
	 */
	public static Set<String> getAllKeyByPattern(String pattern) {
		Jedis jedis = RedisUtil.getJedis();
		try {
			return jedis.keys(pattern);
		} catch (Exception e) {
			log.error("error:" + e.getMessage());
		} finally {
			RedisUtil.returnResource(jedis);
		}
		return null;
	}

	/**
	 * @Title: getString @Description: redis獲得string @param key @return
	 *         String @throws
	 */
	public static String getString(String key) {
		Jedis jedis = RedisUtil.getJedis();
		try {
			byte[] object = jedis.get(key.getBytes());
			if (object == null) {
				return null;
			}
			return (String) SerializeUtil.unserialize(object);
		} catch (Exception e) {
			log.error("error:" + e.getMessage());
		} finally {
			RedisUtil.returnResource(jedis);
		}
		return null;
	}

	/**
	 * @Title: lrange @Description: 獲得連結串列指定範圍內的資料 @param key @param start @param
	 *         end @return List<byte[]> @throws
	 */
	public static List<byte[]> lrange(String key, long start, long end) {
		Jedis jedis = RedisUtil.getJedis();
		try {
			return jedis.lrange(key.getBytes(), start, end);
		} catch (Exception e) {
			log.error("error:" + e.getMessage());
		} finally {
			RedisUtil.returnResource(jedis);
		}
		return null;
	}

	/**
	 * @Title: lindex @Description: 根據索引獲得list資料 @param @param key @param @param
	 *         index @return byte[] @throws
	 */
	public static byte[] lindex(String key, long index) {
		Jedis jedis = RedisUtil.getJedis();
		try {
			return jedis.lindex(key.getBytes(), index);
		} catch (Exception e) {
			log.error("error:" + e.getMessage());
		} finally {
			RedisUtil.returnResource(jedis);
		}
		return null;
	}

}

RedisUtil:Redis初始化工具類

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * 
 * @ClassName: RedisUtil
 * @Description: TODO(redis初始化類)
 * @author zoe 
 * @date 2018年3月12日 上午11:32:17
 *
 */
public class RedisUtil {
	private static String ADDR = SystemProperties.getString("redis-ip");
	private static int PORT = SystemProperties.getInteger("redis-port");
	private static String PASSWORD = SystemProperties.getString("redis-pwd");
	private static String REDISPASSWORD = PASSWORD;
	private static int MAX_ACTIVE = 50;
	private static int MAX_IDLE = 10;
	private static int MAX_WAIT = 10000;
	private static int TIMEOUT = 10000;
	private static boolean TEST_ON_BORROW = true;
	private static JedisPool jedisPool = null;
	static {
		try {
			JedisPoolConfig config = new JedisPoolConfig();
			config.setMaxTotal(MAX_ACTIVE);
			config.setMaxIdle(MAX_IDLE);
			config.setMaxWaitMillis(MAX_WAIT);
			config.setTestOnBorrow(TEST_ON_BORROW);
			if (REDISPASSWORD == null || "".equals(REDISPASSWORD)) {
				jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT);
			} else {
				jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT, REDISPASSWORD);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public synchronized static Jedis getJedis() {
		try {
			if (jedisPool != null) {
				Jedis resource = jedisPool.getResource();
				return resource;
			} else {
				return null;
			}
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 釋放jedis資源
	 * 
	 * @param jedis
	 */
	public static void returnResource(final Jedis jedis) {
		if (jedis != null) {
			jedisPool.returnResource(jedis);
		}
	}
}

SerializeUtil :序列化工具類

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * 
 * @ClassName: SerializeUtil
 * @Description: TODO(序列化和反序列化)
 * @author zoe 
 * @date 2018年3月12日 上午11:35:26
 *
 */
public class SerializeUtil {
	public static byte[] serialize(Object object) {
		ObjectOutputStream oos = null;
		ByteArrayOutputStream baos = null;
		try {
			// 序列化
			baos = new ByteArrayOutputStream();
			oos = new ObjectOutputStream(baos);
			oos.writeObject(object);
			byte[] bytes = baos.toByteArray();
			return bytes;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static Object unserialize(byte[] bytes) {
		ByteArrayInputStream bais = null;
		try {
			// 反序列化
			bais = new ByteArrayInputStream(bytes);
			ObjectInputStream ois = new ObjectInputStream(bais);
			return ois.readObject();
		} catch (Exception e) {

		}
		return null;
	}
}