Redis实现分布式锁
Posted weilz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis实现分布式锁相关的知识,希望对你有一定的参考价值。
写一个定时任务,然后把demo放在三台机器上,定时推送信息,客户端保证只能接收到一条
1、IBaseRedisDao
public interface IBaseRedisDao public String get(String key); public Boolean set(String key, String value); public Long delete(String key); public Boolean exists(final String key); public Boolean expire(String key, Long expireTime); public Boolean setnx(final String key, final String value); public Void setrange(final String key, final String value, final Long offset);
2、BaseRedisDao
import javax.annotation.Resource; import org.springframework.dao.DataAccessException; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.stereotype.Component; @Component public class BaseRedisDao implements IBaseRedisDao @Resource(name = "redisTemplate") private RedisTemplate<String, Object> redisTemplate; /** * 字符串类型:通过key值获取对应的value对象 * * @param key * @return */ @Override public String get(final String key) return redisTemplate.execute(new RedisCallback<String>() @Override public String doInRedis(RedisConnection redisConnection) throws DataAccessException RedisSerializer<String> serializer = getRedisSerializer(); byte keys[] = serializer.serialize(key); byte values[] = redisConnection.get(keys); if (values == null) return null; String value = serializer.deserialize(values); return value; ); /** * 字符串类型:存入key-value对象,如果key存在,那么默认更新value * * @param key * @param value * @return */ @Override public Boolean set(final String key, final String value) return redisTemplate.execute(new RedisCallback<Boolean>() @Override public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException RedisSerializer<String> serializer = getRedisSerializer(); byte keys[] = serializer.serialize(key); byte values[] = serializer.serialize(value); redisConnection.set(keys, values); return true; ); /** * 字符串类型:通过key删除对应的key和value * * @param key * @return */ @Override public Long delete(final String key) return redisTemplate.execute(new RedisCallback<Long>() @Override public Long doInRedis(RedisConnection redisConnection) throws DataAccessException RedisSerializer<String> redisSerializer = getRedisSerializer(); byte keys[] = redisSerializer.serialize(key); return redisConnection.del(keys); ); /** * 字符串类型:通过key判断对象是否存在 * * @param key * @return */ @Override public Boolean exists(final String key) return redisTemplate.execute(new RedisCallback<Boolean>() @Override public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException byte keys[] = getRedisSerializer().serialize(key); return redisConnection.exists(keys); ); /** * 字符串类型:设置key对应的超时时间 * * @param key * @param expireTime * @return */ @Override public Boolean expire(final String key, final Long expireTime) return redisTemplate.execute(new RedisCallback<Boolean>() @Override public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException byte keys[] = getRedisSerializer().serialize(key); return redisConnection.expire(keys, expireTime); ); /** * 字符串类型:根据key设置value值,如果key中的value存在,那么返回false * * @param key * @param value * @return */ @Override public Boolean setnx(final String key, final String value) return redisTemplate.execute(new RedisCallback<Boolean>() @Override public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException byte keys[] = getRedisSerializer().serialize(key); byte values[] = getRedisSerializer().serialize(value); return redisConnection.setNX(keys, values); ); /** * 字符串类型: 覆盖key对应的string的一部分,从指定的offset开始,覆盖value的长度。 * 如果offset比当前key对应string还长,那么这个string后面就补0以达到offset。 * 不存在的keys被认为是空字符串,所以这个命令可以确保key有一个足够大的字符串,能在offset处设置value。 * * @param key * @param value * @param offset * @return */ @Override public Void setrange(final String key, final String value, final Long offset) return redisTemplate.execute(new RedisCallback<Void>() @Override public Void doInRedis(RedisConnection redisConnection) throws DataAccessException byte keys[] = getRedisSerializer().serialize(key); byte values[] = getRedisSerializer().serialize(value); redisConnection.setRange(keys, values, offset); return null; ); /** * 获取主库的redis模板 * * @return */ protected RedisTemplate<String, Object> getRedisTemplate() return redisTemplate; /** * 获取主库的字符串序列化对象 * * @return */ protected RedisSerializer<String> getRedisSerializer() RedisSerializer<String> redisSerializer = getRedisTemplate().getStringSerializer(); return redisSerializer;
3、SpringContextUtils
import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; @Component public class SpringContextUtils implements ApplicationContextAware private static ApplicationContext context; @Override public void setApplicationContext(ApplicationContext context) throws BeansException SpringContextUtils.context = context; public static ApplicationContext getContext() return context;
4、RedisUtilLockSimple
import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.asiainfo.bchz.common.redis.IBaseRedisDao; import com.asiainfo.bchz.web.common.base.SpringContextUtils; public class RedisUtilLockSimple implements Lock private static final Logger logger = LoggerFactory.getLogger(RedisUtilLockSimple.class); private IBaseRedisDao baseRedisDao; // 锁的有效时间(s) public static final long EXPIRE = 30; // 锁标志对应的key; private String key; // state flag private volatile boolean isLocked = false; public RedisUtilLockSimple(String key) try this.key=key; baseRedisDao = (IBaseRedisDao)SpringContextUtils.getContext().getBean("baseRedisDao"); catch (Exception e) e.printStackTrace(); @Override public void lock() if (baseRedisDao.setnx(key, key)) baseRedisDao.expire(key, EXPIRE); isLocked = true; @Override public void unlock() if (isLocked) baseRedisDao.delete(key); @Override public void lockInterruptibly() throws InterruptedException // TODO Auto-generated method stub @Override public boolean tryLock() // TODO Auto-generated method stub return false; @Override public boolean tryLock(long time, TimeUnit unit) throws InterruptedException // TODO Auto-generated method stub return false; @Override public Condition newCondition() // TODO Auto-generated method stub return null; public boolean isLocked() return isLocked;
5、infoSchedule(信息推送实现)
@Component public class infoSchedule /** * 信息推送 */ @Scheduled(cron = "0 0 8 * * ?") public void infoPushTask() throws ParseException RedisUtilLockSimple redisUtilLockSimple = null; try redisUtilLockSimple = new RedisUtilLockSimple("--类路径--"); redisUtilLockSimple.lock(); if (redisUtilLockSimple.isLocked()) logger.info("信息推送开始 ========================================="); /** * 推送信息的一些demo **/ finally // 任何情况下都要释放锁 redisUtilLockSimple.unlock();
以上是关于Redis实现分布式锁的主要内容,如果未能解决你的问题,请参考以下文章