4.1 redis 鎖(如分佈式事務鎖實現)
分佈式事務主要解決的就是同一時間只有一個線程在修改共享資源。所以redis的setnx 加上時間設置完全可以實現分佈式事務的問題。(注意控制鎖的顆粒度:如 共享資源 綁定的是uid 還是requestId )
代碼實現:
# 主要邏輯根據實際業務需求public class RedisLock { private final static Logger LOGGER = LoggerFactory.getLogger(RedisLock.class); private CacheService cacheService; /** * 加鎖 * * @param key * @param value 當前時間+超時時間 * @return */ public boolean lock(String key, String value) { if (cacheService.opsForValue().setIfAbsent(key, value)) { return true; } String currentValue = cacheService.opsForValue().get(key); //如果鎖過期 解決死鎖 if (StringUtils.isNotBlank(currentValue) && Long.parseLong(currentValue) < System.currentTimeMillis()) { //獲取上一個鎖的時間,鎖過期後,GETSET將原來的鎖替換成新鎖 String oldValue = cacheService.opsForValue().getAndSet(key, value); if (StringUtils.isNotBlank(oldValue) && oldValue.equals(currentValue)) { return true; } } return false; } /** * 解鎖 * * @param key * @param value */ public void unlock(String key, String value) { try { String currentValue = cacheService.opsForValue().get(key); if (StringUtils.isNotBlank(currentValue) && currentValue.equals(value)) { cacheService.opsForValue().getOperations().delete(key); } } catch (Exception e) { LOGGER.error("【redis分佈式鎖】解鎖異常, {}", e); } } public void setCacheService(CacheService cacheService) { this.cacheService = cacheService; }
注意:
1、操作完成後需要將鎖釋放。
2、出現異常要及時將鎖釋放。(如果顆粒度比較大,不釋放鎖別人都得不到操作權限)。
3、注意顆粒度的選擇,綁定的是uid還是requestId。權限過大會影響別的線程操作使用。權限過小容易損耗性能。
4.2 redis的隊列(生產/消費模式)
實際場景 :
發紅包 ---->將紅包散列成小紅包---->放入隊列 。
搶紅包時 ---->檢查用戶權限---->檢查紅包庫存---> 從隊列中彈出小紅包。
(Redis的單線程操作,完全可以控制紅包的小併發問題)。如果要更大併發可以直接將請求放入
MQ 進行異步處理。
4.3 redis session服務器(存儲用戶信息)
常見的session服務器,實現分佈式的基礎,實現session共享,實現跨服務,減輕服務端的壓力。
4.4 redis 做數據排行榜(熱數據分離)
常見需求TOP10/TOP100排行榜。實現原理可以使用Redis中的有序集合SortSet 完美的實現動態排行榜。(或者可以把熱數據直接放入Redis,如:實時美元的匯率,波動不定的價格等)。
4.5、保持變動頻率較高的數據,如:計數器(網站訪問量),點贊/收藏 等。
4.6、redis的訂閱發佈模式SUB/PUB。如:網站站內信/實時公告。當然也會有更好的別的中間件替代,這裡只是舉例子。
訂閱--->訂閱成功--->監聽 。 發佈消息message1 。此時訂閱該channel的client端都可以接收到消息。
閱讀更多 代碼vs生活 的文章