java如何使用redis加鎖
java使用redis加鎖
編寫LockUtil工具類
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.connection.RedisStringCommands.SetOption; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.types.Expiration; import org.springframework.stereotype.Service; /** * LockUtil <br> * */ @Service public class LockUtil { @Autowired private RedisTemplate redisTemplate; @Autowired private StringRedisTemplate stringRedisTemplate; /** * @param lockKey 上鎖的key * @param lockSeconds 上鎖的秒數 * @return */ public boolean lock(String lockKey, int lockSeconds) { return (Boolean) redisTemplate.execute((RedisCallback) connection -> { byte[] key = lockKey.getBytes(); Boolean set = connection.set(key, key, Expiration.seconds(lockSeconds), SetOption.SET_IF_ABSENT); if (set == null) { return false; } return set; }); } public boolean isLock(String lockKey) { return stringRedisTemplate.opsForValue().get(lockKey)!=null; } public boolean clearLock(String lockKey){ return redisTemplate.delete(lockKey); } }
使用鎖
public abstract class AbstractTask { @Autowired private LockUtil lockUtil; /** * 獲取redis鎖的key * * @return */ protected abstract String getLockKey(); protected boolean lock() { return lockUtil.lock(getLockKey(), 120); } protected boolean lockManual() { return lockUtil.lock(getLockKey(), 299); } protected boolean clearLock() { return lockUtil.clearLock(getLockKey()); } }
@Component @Slf4j @RefreshScope public class FileCapacityCountTask extends AbstractTask{ @Autowired private FileCapacityCountService fileCapacityCountService; @Scheduled(cron = "${batch.verification.schedule.capacity}") public void task(){ if (!lock()) { log.info("本實例無需執行定時任務"); return; } fileCapacityCountService.fileCapacityCountTask(); } @Override protected String getLockKey() { String today = DateUtil.formatDate(new Date()); return FileCapacityCountTask.class.getSimpleName() + CommonConstant.APPLICATION_NAME + today; } }
redis鎖用法java代碼
由於redis是串行的,所以可以用redis實現鎖機制。
下方是java代碼
@Component @Slf4j public class RedisSingleLock { private final StringRedisTemplate redis; public SimpleDistributedLock(StringRedisTemplate redis) { this.redis = redis; } //這個方法,可以傳入key加鎖;多線程調用時,隻有1個能獲取鎖成功,其它線程則會進入循環,不停嘗試獲取鎖 public void lock(String key) { do { Boolean lockSuccess = redis.opsForValue().setIfAbsent(key, "1", 1, TimeUnit.DAYS); if (lockSuccess == null) { throw new IllegalStateException(); } if (!lockSuccess) { try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { log.error(e.getMessage(), e); } } else { break; } } while (true); } //這個方法,傳入key釋放鎖,當持有鎖的線程執行業務代碼完畢後調用,釋放這個鎖;上方某一個在lock方法中循環嘗試獲得鎖的線程可以獲得鎖,另外的線程則繼續循環等待 public void releaseLock(String key) { redis.delete(key); } //這個方法隻嘗試獲取一次鎖,返回獲取結果 public boolean tryLock(String key) { Boolean lockSuccess = redis.opsForValue().setIfAbsent(key, "1", 1, TimeUnit.DAYS); if (lockSuccess == null) { throw new IllegalStateException(); } return lockSuccess; } }
總結
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- 關於SpringBoot 使用 Redis 分佈式鎖解決並發問題
- SpringBoot基於Redis的分佈式鎖實現過程記錄
- springboot使用redis的詳細步驟
- Springboot/Springcloud項目集成redis進行存取的過程解析
- Redis唯一ID生成器的實現