| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423 |
- package com.ljsd.redis;
- import com.ljsd.util.BaseGlobal;
- import com.ljsd.util.TimeUtil;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import redis.clients.jedis.Jedis;
- import redis.clients.jedis.JedisPool;
- import redis.clients.jedis.JedisPoolConfig;
- import java.util.*;
- public class RedisUtil {
- private static final Logger LOGGER = LoggerFactory.getLogger(RedisUtil.class);
- private static int MAX_TRY_TIMES = 3; //最大尝试次数,保障获取/存储成功
- private static int FAILED_SLEEP = 2; //每次失败最大停顿时间
- private JedisPool jedisPool;//非切片连接池
- protected void init() {
- // 池基本配置
- JedisPoolConfig config = new JedisPoolConfig();
- Properties properties = BaseGlobal.getInstance().properties;
- config.setMaxTotal(Integer.parseInt(properties.getProperty("redis_maxTotal")));
- config.setMinIdle(Integer.parseInt(properties.getProperty("redis_minIdle")));
- config.setMaxWaitMillis(Integer.parseInt(properties.getProperty("redis_maxWaitMillis")));
- config.setMaxIdle(Integer.parseInt(properties.getProperty("redis_maxIdle")));
- config.setTestOnBorrow(Boolean.parseBoolean(properties.getProperty("redis_testOnBorrow")));
- if (properties.getProperty("redis_password") ==null || properties.getProperty("redis_password").isEmpty()){
- jedisPool = new JedisPool(config, properties.getProperty("redis_host"), Integer.parseInt(properties.getProperty("redis_port")),0);
- }else{
- jedisPool = new JedisPool(config, properties.getProperty("redis_host"), Integer.parseInt(properties.getProperty("redis_port")),0,properties.getProperty("redis_password"));
- }
- }
- /***************************************普通键值对操作***************************************/
- //设置键值
- protected void set(final String key, String value) throws Exception {
- for (int i = 0; i < MAX_TRY_TIMES; i++) {
- Jedis jedis = jedisPool.getResource();
- try {
- jedis.set(key, value);
- return;
- } catch (Exception e) {
- LOGGER.error("set->i={}: key={}, value={}", i, key, value, e);
- TimeUtil.sleep(FAILED_SLEEP);
- } finally {
- jedis.close();
- }
- }
- throw new Exception("RedisUtil::set exception");
- }
- //设置键值,带过期时间
- protected void setex(final String key, final int seconds, final String value) throws Exception {
- for (int i = 0; i < MAX_TRY_TIMES; i++) {
- Jedis jedis = jedisPool.getResource();
- try {
- jedis.setex(key, seconds, value);
- return;
- } catch (Exception e) {
- LOGGER.error("setex->i={},key={},value={},seconds={}", i, key, value, seconds, e);
- TimeUtil.sleep(FAILED_SLEEP);
- } finally {
- jedis.close();
- }
- }
- throw new Exception("RedisUtil::setex exception");
- }
- //取得键的值
- protected String get(final String key) throws Exception {
- for (int i = 0; i < MAX_TRY_TIMES; i++) {
- Jedis jedis = jedisPool.getResource();
- try {
- return jedis.get(key);
- } catch (Exception e) {
- LOGGER.error("get->i={},key={}", i, key, e);
- TimeUtil.sleep(FAILED_SLEEP);
- } finally {
- jedis.close();
- }
- }
- throw new Exception("RedisUtil::get exception");
- }
- //删除键值
- protected void del(String key) throws Exception {
- for (int i = 0; i < MAX_TRY_TIMES; i++) {
- Jedis jedis = jedisPool.getResource();
- try {
- jedis.del(key);
- return;
- } catch (Exception e) {
- LOGGER.error("del->i={},key={}", i, key, e);
- TimeUtil.sleep(FAILED_SLEEP);
- } finally {
- jedis.close();
- }
- }
- throw new Exception("RedisUtil::del exception");
- }
- //删除键值
- protected boolean exists(String key) throws Exception {
- for (int i = 0; i < MAX_TRY_TIMES; i++) {
- Jedis jedis = jedisPool.getResource();
- try {
- return jedis.exists(key);
- } catch (Exception e) {
- LOGGER.error("exists->i={},key={}", i, key, e);
- TimeUtil.sleep(FAILED_SLEEP);
- } finally {
- jedis.close();
- }
- }
- throw new Exception("RedisUtil::exists exception");
- }
- //设置过期时间
- protected Long expire(final String key, final int seconds) throws Exception {
- if (seconds <= 0) {
- return 0L;
- }
- for (int i = 0; i < MAX_TRY_TIMES; i++) {
- Jedis jedis = jedisPool.getResource();
- try {
- return jedis.expire(key, seconds);
- } catch (Exception e) {
- LOGGER.error("expire->i={},key={},seconds={}", i, key, seconds, e);
- TimeUtil.sleep(FAILED_SLEEP);
- } finally {
- jedis.close();
- }
- }
- throw new Exception("RedisUtil::del exception");
- }
- /***************************************以下是map操作***************************************/
- //添加redis map
- protected void hmset(final String key, final Map<String, String> hash, int seconds) throws Exception {
- int i;
- for (i = 0; i < MAX_TRY_TIMES; i++) {
- Jedis jedis = jedisPool.getResource();
- try {
- jedis.hmset(key, hash);
- break;
- } catch (Exception e) {
- LOGGER.error("hmset->i={},key={}", i, key, e);
- TimeUtil.sleep(FAILED_SLEEP);
- } finally {
- jedis.close();
- }
- }
- expire(key, seconds);
- if (i >= MAX_TRY_TIMES) {
- throw new Exception("RedisUtil::hmset exception");
- }
- }
- //取得主key下的所有子key
- protected Set<String> hkeys(final String key) throws Exception {
- for (int i = 0; i < MAX_TRY_TIMES; i++) {
- Jedis jedis = jedisPool.getResource();
- try {
- Set<String> keySet = jedis.hkeys(key);
- return keySet;
- } catch (Exception e) {
- LOGGER.error("hkeys->i={},key={}", i, key, e);
- TimeUtil.sleep(FAILED_SLEEP);
- } finally {
- jedis.close();
- }
- }
- throw new Exception("RedisUtil::hkeys exception");
- }
- //设置redis map一个键值 下的子key下的值
- protected void hset(final String key, final String field, final String value, int seconds) throws Exception {
- for (int i = 0; i < MAX_TRY_TIMES; i++) {
- Jedis jedis = jedisPool.getResource();
- try {
- jedis.hset(key, field, value);
- return;
- } catch (Exception e) {
- LOGGER.error("hset->i={},key={},field={},value={}", i, key, field, value, e);
- TimeUtil.sleep(FAILED_SLEEP);
- } finally {
- jedis.close();
- }
- }
- expire(key, seconds);
- throw new Exception("RedisUtil::hset exception");
- }
- //取redis map全部数据的直接方法
- protected Map<String, String> hgetAll(final String key) throws Exception {
- for (int i = 0; i < MAX_TRY_TIMES; i++) {
- Jedis jedis = jedisPool.getResource();
- try {
- return jedis.hgetAll(key);
- } catch (Exception e) {
- LOGGER.error("hgetAll->i={},key={}", i, key, e);
- TimeUtil.sleep(FAILED_SLEEP);
- } finally {
- jedis.close();
- }
- }
- throw new Exception("RedisUtil::hgetAll exception");
- }
- //获取redis map下一个key的值的直接方法
- protected List<String> hmget(final String key, final String... fields) throws Exception {
- for (int i = 0; i < MAX_TRY_TIMES; i++) {
- Jedis jedis = jedisPool.getResource();
- try {
- return jedis.hmget(key, fields);
- } catch (Exception e) {
- LOGGER.error("hmget->i={},key={}", i, key, e);
- TimeUtil.sleep(FAILED_SLEEP);
- } finally {
- jedis.close();
- }
- }
- throw new Exception("RedisUtil::hmget exception");
- }
- //删除子key
- protected void hdel(final String key, final String... fields) throws Exception {
- for (int i = 0; i < MAX_TRY_TIMES; i++) {
- Jedis jedis = jedisPool.getResource();
- try {
- jedis.hdel(key, fields);
- return;
- } catch (Exception e) {
- LOGGER.error("hdel->i={},key={},fields={}", i, key, fields, e);
- TimeUtil.sleep(FAILED_SLEEP);
- } finally {
- jedis.close();
- }
- }
- throw new Exception("RedisUtil::hdel exception");
- }
- /***************************************以下是list操作***************************************/
- //添加list数据
- protected long lpush(final String key, final int seconds, final String... strings) throws Exception {
- for (int i = 0; i < MAX_TRY_TIMES; i++) {
- Jedis jedis = jedisPool.getResource();
- try {
- return jedis.lpush(key, strings);
- } catch (Exception e) {
- LOGGER.error("lpush->i={},key={},value={}", i, key, e);
- TimeUtil.sleep(FAILED_SLEEP);
- } finally {
- jedis.close();
- }
- }
- expire(key, seconds);
- throw new Exception("RedisUtil::lpush exception");
- }
- protected void ltrim(final String key, final int start, final int end) throws Exception {
- for (int i = 0; i < MAX_TRY_TIMES; i++) {
- Jedis jedis = jedisPool.getResource();
- try {
- jedis.ltrim(key, start, end);
- return;
- } catch (Exception e) {
- LOGGER.error("lpush->i={},key={},value={}", i, key, e);
- TimeUtil.sleep(FAILED_SLEEP);
- } finally {
- jedis.close();
- }
- }
- throw new Exception("RedisUtil::ltrim exception");
- }
- //删除元素
- protected void lrem(final String key, final long count, final String value) throws Exception {
- for (int i = 0; i < MAX_TRY_TIMES; i++) {
- Jedis jedis = jedisPool.getResource();
- try {
- jedis.lrem(key, count, value);
- return;
- } catch (Exception e) {
- LOGGER.error("lrem->i={},key={},count={},value={}", i, key, count, value, e);
- TimeUtil.sleep(FAILED_SLEEP);
- } finally {
- jedis.close();
- }
- }
- throw new Exception("RedisUtil::lrem exception");
- }
- //移除最好的元素
- protected String rpop(final String key) throws Exception {
- for (int i = 0; i < MAX_TRY_TIMES; i++) {
- Jedis jedis = jedisPool.getResource();
- try {
- return jedis.rpop(key);
- } catch (Exception e) {
- LOGGER.error("rpop->i={},key={}", i, key, e);
- TimeUtil.sleep(FAILED_SLEEP);
- } finally {
- jedis.close();
- }
- }
- throw new Exception("RedisUtil::rpop exception");
- }
- //取得指定范围的元素
- protected List<String> lrange(final String key, final long start, final long end) throws Exception {
- for (int i = 0; i < MAX_TRY_TIMES; i++) {
- Jedis jedis = jedisPool.getResource();
- try {
- return jedis.lrange(key, start, end);
- } catch (Exception e) {
- LOGGER.error("lrange->i={},key={},start={},end={}", i, key, start, end, e);
- TimeUtil.sleep(FAILED_SLEEP);
- } finally {
- jedis.close();
- }
- }
- throw new Exception("RedisUtil::lrange exception");
- }
- //取得list的长度
- protected Long llen(final String key) throws Exception {
- for (int i = 0; i < MAX_TRY_TIMES; i++) {
- Jedis jedis = jedisPool.getResource();
- try {
- return jedis.llen(key);
- } catch (Exception e) {
- LOGGER.error("llen->i={},key={}", i, key, e);
- TimeUtil.sleep(FAILED_SLEEP);
- } finally {
- jedis.close();
- }
- }
- throw new Exception("RedisUtil::llen exception");
- }
- //自增
- protected Long incr(final String key) throws Exception {
- for (int i = 0; i < MAX_TRY_TIMES; i++) {
- Jedis jedis = jedisPool.getResource();
- try {
- return jedis.incr(key);
- } catch (Exception e) {
- LOGGER.error("incr->i={},key={}", i, key, e);
- TimeUtil.sleep(FAILED_SLEEP);
- } finally {
- jedis.close();
- }
- }
- throw new Exception("RedisUtil::incr exception");
- }
- private static final String LOCK_SUCCESS = "OK";
- private static final String SET_IF_NOT_EXIST = "NX";
- private static final String SET_WITH_EXPIRE_TIME = "PX";
- /**
- * 尝试获取分布式锁
- *
- * @param lockKey 锁
- * @param requestId 请求标识
- * @param expireTime 超期时间,理论上应该比较短,一次请求在500毫秒内即可完成,因此过期时间不应大于1秒
- * @return 是否获取成功
- */
- protected boolean tryGetDistributedLock(String lockKey, String requestId, int expireTime) throws Exception {
- for (int i = 0; i < MAX_TRY_TIMES; i++) {
- Jedis jedis = jedisPool.getResource();
- try {
- String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
- if (LOCK_SUCCESS.equals(result)) {
- return true;
- }
- LOGGER.error("tryGetDistributedLock->i={},key={};failed", i, lockKey);
- TimeUtil.sleep(200); //理论上锁冲突的几率很小,如果连续三次加锁失败,直接抛出异常
- } catch (Exception e) {
- LOGGER.error("tryGetDistributedLock->i={},key={}", i, lockKey, e);
- TimeUtil.sleep(FAILED_SLEEP);
- } finally {
- jedis.close();
- }
- }
- throw new Exception("RedisUtil::tryGetDistributedLock exception");
- }
- private static final Long RELEASE_SUCCESS = 1L;
- /**
- * 释放分布式锁
- *
- * @param lockKey 锁
- * @param requestId 请求标识
- * @return 是否释放成功
- */
- protected boolean releaseDistributedLock(String lockKey, String requestId) throws Exception {
- for (int i = 0; i < MAX_TRY_TIMES; i++) {
- Jedis jedis = jedisPool.getResource();
- try {
- String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
- Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
- if (RELEASE_SUCCESS.equals(result)) {
- return true;
- }
- return false; //解锁失败,等待过期自动解锁即可
- } catch (Exception e) {
- LOGGER.error("releaseDistributedLock->i={},key={}", i, lockKey, e);
- TimeUtil.sleep(FAILED_SLEEP);
- } finally {
- jedis.close();
- }
- }
- throw new Exception("RedisUtil::releaseDistributedLock exception");
- }
- }
|