前言
之前在做 秒殺架構實踐 時有提到對 distributed-redis-tool 的一次小升級,但是沒有細說。
其實主要原因是:
秒殺時我做壓測:由于集成了這個限流組件,并發又比較大,所以導致連接、斷開 Redis 非常頻繁。池化技術
最終導致獲取不了 Redis connection 的異常。
這就是一個典型的對稀缺資源使用不善導致的。
何為稀缺資源?常見的有:
線程
數據庫連接
網絡連接等
這些資源都有共同的特點:創建銷毀成本較高。
這里涉及到的 Redis 連接也屬于該類資源。
我們希望將這些稀有資源管理起來放到一個池子里,當需要時就從中獲取,用完就放回去,不夠用時就等待(或返回)。
這樣我們只需要初始化并維護好這個池子,就能避免頻繁的創建、銷毀這些資源(也有資源長期未使用需要縮容的情況)。
通常我們稱這項姿勢為池化技術,如常見的:
線程池
各種資源的連接池等。
為此我將使用到 Redis 的 分布式鎖、分布式限流 都升級為利用連接池來獲取 Redis 的連接。
這里以分布式鎖為例:
將使用的 api 修改為:
原有:
@Configuration public class RedisLockConfig { @Bean public RedisLock build(){ //Need to get Redis connection RedisLock redisLock = new RedisLock() ; HostAndPort hostAndPort = new HostAndPort("127.0.0.1",7000) ; JedisCluster jedisCluster = new JedisCluster(hostAndPort) ; RedisLock redisLock = new RedisLock.Builder(jedisCluster) .lockPrefix("lock_test") .sleepTime(100) .build(); return redisLock ; } }
現在:
@Configuration public class RedisLockConfig { private Logger logger = LoggerFactory.getLogger(RedisLockConfig.class); @Autowired private JedisConnectionFactory jedisConnectionFactory; @Bean public RedisLock build() { RedisLock redisLock = new RedisLock.Builder(jedisConnectionFactory,RedisToolsConstant.SINGLE) .lockPrefix("lock_") .sleepTime(100) .build(); return redisLock; } }
將以前的 Jedis 修改為 JedisConnectionFactory,后續的 Redis 連接就可通過這個對象獲取。
并且顯示的傳入使用 RedisCluster 還是單機的 Redis。
所以在真正操作 Redis 時需要修改:
public boolean tryLock(String key, String request) { //get connection Object connection = getConnection(); String result ; if (connection instanceof Jedis){ result = ((Jedis) connection).set(lockPrefix + key, request, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, 10 * TIME); ((Jedis) connection).close(); }else { result = ((JedisCluster) connection).set(lockPrefix + key, request, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, 10 * TIME); try { ((JedisCluster) connection).close(); } catch (IOException e) { logger.error("IOException",e); } } if (LOCK_MSG.equals(result)) { return true; } else { return false; } } //獲取連接 private Object getConnection() { Object connection ; if (type == RedisToolsConstant.SINGLE){ RedisConnection redisConnection = jedisConnectionFactory.getConnection(); connection = redisConnection.getNativeConnection(); }else { RedisClusterConnection clusterConnection = jedisConnectionFactory.getClusterConnection(); connection = clusterConnection.getNativeConnection() ; } return connection; }
最大的改變就是將原有操作 Redis 的對象(T extends JedisCommands)改為從連接池中獲取。
由于使用了 org.springframework.data.redis.connection.jedis.JedisConnectionFactory 作為 Redis 連接池。
所以需要再使用時構件好這個對象:
JedisPoolConfig config = new JedisPoolConfig(); config.setMaxIdle(10); config.setMaxTotal(300); config.setMaxWaitMillis(10000); config.setTestOnBorrow(true); config.setTestOnReturn(true); RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(); redisClusterConfiguration.addClusterNode(new RedisNode("10.19.13.51", 7000)); //單機 JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(config); //集群 //JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(redisClusterConfiguration) ; jedisConnectionFactory.setHostName("47.98.194.60"); jedisConnectionFactory.setPort(6379); jedisConnectionFactory.setPassword(""); jedisConnectionFactory.setTimeout(100000); jedisConnectionFactory.afterPropertiesSet(); //jedisConnectionFactory.setShardInfo(new JedisShardInfo("47.98.194.60", 6379)); //JedisCluster jedisCluster = new JedisCluster(hostAndPort); HostAndPort hostAndPort = new HostAndPort("10.19.13.51", 7000); JedisCluster jedisCluster = new JedisCluster(hostAndPort); redisLock = new RedisLock.Builder(jedisConnectionFactory, RedisToolsConstant.SINGLE) .lockPrefix("lock_") .sleepTime(100) .build();
看起比較麻煩,需要構建對象的較多。
但整合 Spring 使用時就要清晰許多。
配合 SpringSpring 很大的一個作用就是幫我們管理對象,所以像上文那些看似很復雜的對象都可以交由它來管理:
這個其實沒多少好說的,就算是換成 SpringBoot 也是創建 JedispoolConfig,connectionFactory,redisTemplate 這些 bean 即可。
總結換為連接池之后再進行壓測自然沒有出現獲取不了 Redis 連接的異常(并發達到一定的量也會出錯)說明更新是很有必要的。
推薦有用到該組件的朋友都升級下,也歡迎提出 Issues 和 PR。
項目地址:
https://github.com/crossoverJie/distributed-redis-tool
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/69694.html
摘要:在南京峰會上,阿里云產品宣布,包年包月實例租用費最高下調,存儲價格不變。本次阿里云宣布所有規格整體降價,平均降幅達到。阿里云表示,經過不斷的技術升級和資源優化,規模效應開始展現,這是今年持續大幅降價的基礎。4月26日,在2018云棲大會·南京峰會上,阿里云宣布新一輪的價格調整。此次調整包含了Elasticsearch、分析型數據庫、實人認證、開放搜索等多項產品,最高降幅達到50%。 ...
摘要:執行構造函數執行析構函數第一次完畢第二次完畢執行輸出執行構造函數第一次完畢執行構造函數執行析構函數第二次完畢執行析構函數終于逮到你了。。。這就導致了先執行構造函數,然后再執行析構函數。 class Test { protected $client; protected static $name; public function __construct() { ...
摘要:前言這段時間一直負責公司的小程序的開發,總結了一些小程序的開發心得,方便自己以后的查閱也方便同仁少踩點坑。文章底部的技巧類小程序的識別小程序二維碼功能,小程序的高斯模糊,都是自己填的坑。 前言:這段時間一直負責公司的小程序的開發,總結了一些小程序的開發心得,方便自己以后的查閱也方便同仁少踩點坑。文章底部的技巧類小程序的識別小程序二維碼功能,小程序的高斯模糊,都是自己填的坑。歡迎交流。 ...
閱讀 1830·2021-11-18 13:21
閱讀 1962·2021-10-18 13:30
閱讀 1548·2021-10-12 10:13
閱讀 918·2021-10-09 09:43
閱讀 5430·2021-09-22 15:13
閱讀 3591·2021-08-11 10:22
閱讀 945·2019-08-30 13:46
閱讀 3525·2019-08-30 13:21