背景:給大批量用戶分配賬號,用戶和賬號關(guān)系為一對一紊馏,支持tps150左右料饥。
解決方案:redis隊(duì)列存儲賬號,redis鎖(生成賬號)+多線程(處理分配邏輯)
代碼邏輯
//多線程生成賬號
threadPoolTaskExecutor.submit(() -> getInfo(redisCacheBatchNum));
//生成賬號邏輯
private void getInfoToRedisCache(Integer addNum) {
Long value = redisTemplate.opsForValue().increment(LOCK_KEY, 1);
redisTemplate.expire(LOCK_KEY, 10, TimeUnit.SECONDS);
if (value == 1) {
try {
Integer cacheSize = redisTemplate.opsForSet().size(REDIS_CACHE_KEY).intValue();
if (cacheSize < redisCacheNum) {
log.info("{}目前獲取鎖成功,當(dāng)前緩存數(shù)量為{}朱监,開始入隊(duì)",Thread.currentThread().getName(),cacheSize);
岸啡。。赫编。巡蘸。(生成賬號邏輯)
//將生成賬號放入到redis隊(duì)列中,注意set可以保證唯一性
resultList.stream().forEach(e -> redisTemplate.opsForSet().add(REDIS_CACHE_KEY, e));
}
} finally {
log.info("{}入隊(duì)結(jié)束釋放鎖",Thread.currentThread().getName());
redisTemplate.delete(LOCK_KEY);
}
}
}
//獲取redis隊(duì)列中賬號擂送,然后可以和用戶進(jìn)行綁定
redisTemplate.opsForSet().pop(REDIS_CACHE_KEY);
如果并發(fā)量小悦荒,數(shù)據(jù)壓力不大,可以給數(shù)據(jù)庫加行所嘹吨,具體實(shí)現(xiàn)可以在表中增加一個(gè)version字段搬味,每次更新或新增數(shù)據(jù)拿出上一次的version作為判斷條件,如果version不變version遞增,否則更新或新增失敗碰纬。