随便网站系统越来越大,各功能模块除了垂直切割以外,同时也得做集群处理,那么问题来了,在多线程情况下对于资源的竞争就需要一个统一的访问限制。
以选课系统为例子,集群中各节点对课程可选数量同时操作,这里就需要同步了,否则会导致最后选到的数量比可选的数量大,这里我们的分布式锁就派上用场了。
利用redis来实现每个节点对资源访问前都需要获取到许可 才能继续进行后续操作,这样就保证了数据的同步。
这里使用到了redis 的setnx命令,当且仅当 key 不存在,将 key 的值设为 value ,并返回1;若给定的 key 已经存在,则 SETNX 不做任何动作,并返回 0。
这样我们就可以利用key是否存在来进行能否获取资源的,当一个线程已经设置了key那么下一个线程继续去设置的时候会得到返回值0,这样说明锁已经被另外一个线程所获得。
参考网上资料写了个redis锁类如下:
public class RedisLock {
public static final Logger logger = LoggerFactory.getLogger(RedisLock.class);
/** 加锁标志 */
public static final String LOCKED = "TRUE";
/** 毫秒与毫微秒的换算单位 1毫秒 = 1000000毫微秒 */
public static final long MILLI_NANO_CONVERSION = 1000 * 1000L;
/** 默认超时时间(毫秒) */
public static final long DEFAULT_TIME_OUT = 1000;
public static final Random RANDOM = new Random();
/** 锁的超时时间(秒),过期删除 */
public static final int EXPIRE = 3 * 60;
/** 锁的超时时间(毫秒),对比*/
public static final long LOCK_DEFAULT_TIME_OUT = 60*1000L;
@Autowired
private JedisPool jedisPool;
/**
* 加锁 key:需要获取得key timeout:等待超时时间
* @Description
* @author peng.wang
* @param key
* @param timeout
* @return
*/
public boolean lock(String key,long timeout){
Jedis jedis = null;
long nano = System.nanoTime();
timeout *= MILLI_NANO_CONVERSION;
try {
jedis = this.jedisPool.getResource();
//获取锁成功 返回设置的value
while((System.nanoTime()-nano)