- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) > 編程語(yǔ)言 >
- redis 集群批量操作實(shí)現
Redis集群是沒(méi)法執行批量操作命令的,如mget,pipeline等。這是因為redis將集群劃分為16383個(gè)哈希槽,不同的key會(huì )劃分到不同的槽中。但是,Jedis客戶(hù)端提供了計算key的slot方法,已經(jīng)slot和節點(diǎn)之間的映射關(guān)系,通過(guò)這兩個(gè)數據,就可以計算出每個(gè)key所在的節點(diǎn),然后使用pipeline獲取數據。具體代碼如下:
初始化 JedisCluster類(lèi)
@Configuration public class JedisClusterConfig { @Value("${spring.redis.cluster.nodes}") private String clusterNodes; @Value("${spring.redis.cache.commandTimeout}") private Integer commandTimeout; @Bean public JedisCluster getJedisCluster() { String[] serverArray = clusterNodes.split(","); Set<HostAndPort> nodes = new HashSet<>(); for (String ipPort : serverArray) { String[] ipPortPair = ipPort.split(":"); nodes.add(new HostAndPort(ipPortPair[0].trim(), Integer.valueOf(ipPortPair[1].trim()))); } return new JedisCluster(nodes, commandTimeout); } }
工具類(lèi) JedisClusterUtil
@Component public class JedisClusterUtil { @Autowired private JedisCluster jedisCluster; @Resource(name = "redisTemplate4Json") protected RedisTemplate<String, Object> redisTemplate; /** * ZSet批量查詢(xún) * @param keys * @return */ public List<Object> batchZRange(List<String> keys) { List<Object> resList = new ArrayList<>(); if (keys == null || keys.size() == 0) { return resList; } if (keys.size() == 1) { BoundZSetOperations<String, Object> operations = redisTemplate.boundZSetOps(keys.get(0)); Set<Object> set = operations.reverseRange(0, 0); resList.add(set.iterator().next()); return resList; } Map<JedisPool, List<String>> jedisPoolMap = getJedisPool(keys); List<String> keyList; JedisPool currentJedisPool = null; Pipeline currentPipeline; List<Object> res = new ArrayList<>(); Map<String, Object> resultMap = new HashMap<>(); //執行 for (Map.Entry<JedisPool, List<String>> entry : jedisPoolMap.entrySet()) { Jedis jedis = null; try { currentJedisPool = entry.getKey(); keyList = entry.getValue(); //獲取pipeline jedis = currentJedisPool.getResource(); currentPipeline = jedis.pipelined(); for (String key : keyList) { currentPipeline.zrevrange(key, 0, 0); } //從pipeline中獲取結果 res = currentPipeline.syncAndReturnAll(); currentPipeline.close(); for (int i = 0; i < keyList.size(); i++) { if (null == res.get(i)) { resultMap.put(keyList.get(i), null); } else { Set<Object> set = (Set<Object>) res.get(i); if (null == set || set.isEmpty()) { resultMap.put(keyList.get(i), null); } else { byte[] byteStr = set.iterator().next().toString().getBytes(); Object obj = redisTemplate.getDefaultSerializer().deserialize(byteStr); resultMap.put(keyList.get(i), obj); } } } } catch (Exception e) { e.printStackTrace(); } finally { returnResource(jedis, currentJedisPool); } } resList = sortList(keys, resultMap); return resList; } /** * Value批量查詢(xún) * @param keys * @return */ public List<Object> batchGet(List<String> keys){ List<Object> resList = new ArrayList<>(); if (keys == null || keys.size() == 0) { return resList; } if (keys.size() == 1) { BoundValueOperations<String, Object> operations = redisTemplate.boundValueOps(keys.get(0)); resList.add(operations.get()); return resList; } Map<JedisPool, List<String>> jedisPoolMap = getJedisPool(keys); List<String> keyList; JedisPool currentJedisPool = null; Pipeline currentPipeline; List<Object> res = new ArrayList<>(); Map<String, Object> resultMap = new HashMap<>(); for (Map.Entry<JedisPool, List<String>> entry : jedisPoolMap.entrySet()) { Jedis jedis = null; try { currentJedisPool = entry.getKey(); keyList = entry.getValue(); //獲取pipeline jedis = currentJedisPool.getResource(); currentPipeline = jedis.pipelined(); for (String key : keyList) { currentPipeline.get(key); } //從pipeline中獲取結果 res = currentPipeline.syncAndReturnAll(); currentPipeline.close(); for (int i = 0; i < keyList.size(); i++) { if (null == res.get(i)) { resultMap.put(keyList.get(i), null); } else { byte[] byteStr = keyList.get(i).toString().getBytes(); Object obj = redisTemplate.getDefaultSerializer().deserialize(byteStr); resultMap.put(keyList.get(i), obj); } } } catch (Exception e) { e.printStackTrace(); } finally { returnResource(jedis, currentJedisPool); } } resList = sortList(keys, resultMap); return resList; } private Map<JedisPool, List<String>> getJedisPool(List<String> keys){ //JedisCluster繼承了BinaryJedisCluster //BinaryJedisCluster的JedisClusterConnectionHandler屬性 //里面有JedisClusterInfoCache,根據這一條繼承鏈,可以獲取到JedisClusterInfoCache //從而獲取slot和JedisPool直接的映射 MetaObject metaObject = SystemMetaObject.forObject(jedisCluster); JedisClusterInfoCache cache = (JedisClusterInfoCache) metaObject.getValue("connectionHandler.cache"); //保存地址+端口和命令的映射 Map<JedisPool, List<String>> jedisPoolMap = new HashMap<>(); JedisPool currentJedisPool = null; List<String> keyList; for (String key : keys) { //計算哈希槽 int crc = JedisClusterCRC16.getSlot(key); //通過(guò)哈希槽獲取節點(diǎn)的連接 currentJedisPool = cache.getSlotPool(crc); //由于JedisPool作為value保存在JedisClusterInfoCache中的一個(gè)map對象中,每個(gè)節點(diǎn)的 //JedisPool在map的初始化階段就是確定的和唯一的,所以獲取到的每個(gè)節點(diǎn)的JedisPool都是一樣 //的,可以作為map的key if (jedisPoolMap.containsKey(currentJedisPool)) { jedisPoolMap.get(currentJedisPool).add(key); } else { keyList = new ArrayList<>(); keyList.add(key); jedisPoolMap.put(currentJedisPool, keyList); } } return jedisPoolMap; } private List<Object> sortList(List<String> keys, Map<String, Object> params) { List<Object> resultList = new ArrayList<>(); Iterator<String> it = keys.iterator(); while (it.hasNext()) { String key = it.next(); resultList.add(params.get(key)); } return resultList; } /** * 釋放jedis資源 * * @param jedis */ public void returnResource(Jedis jedis, JedisPool jedisPool) { if (jedis != null && jedisPool != null) { jedisPool.returnResource(jedis); } }
注意:一定要完成后釋放 jedis 資源 不然會(huì )造成卡死現象
到此這篇關(guān)于redis 集群批量操作實(shí)現的文章就介紹到這了,更多相關(guān)redis 集群批量操作內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。
Copyright ? 2009-2022 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 特網(wǎng)科技 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 百度云 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站