分散式工具的一次小升級⏫
前言
之前在做 秒殺架構實踐 時有提到對 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 使用時就要清晰許多。
配合 Spring
Spring 很大的一個作用就是幫我們管理物件,所以像上文那些看似很複雜的物件都可以交由它來管理:
<!-- jedis 配置 -->
<bean id="JedispoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}"/>
<property name="maxTotal" value="${redis.maxTotal}"/>
<property name="maxWaitMillis" value="${redis.maxWait}"/>
<property name="testOnBorrow" value="${redis.testOnBorrow}"/>
<property name="testOnReturn" value="${redis.testOnBorrow}"/>
</bean>
<!-- redis伺服器中心 -->
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="poolConfig" ref="JedispoolConfig"/>
<property name="port" value="${redis.port}"/>
<property name="hostName" value="${redis.host}"/>
<property name="password" value="${redis.password}"/>
<property name="timeout" value="${redis.timeout}"></property>
</bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
</bean>
這個其實沒多少好說的,就算是換成 SpringBoot 也是建立 JedispoolConfig,connectionFactory,redisTemplate
這些 bean 即可。
總結
換為連線池之後再進行壓測自然沒有出現獲取不了 Redis 連線的異常(併發達到一定的量也會出錯)說明更新是很有必要的。
推薦有用到該元件的朋友都升級下,也歡迎提出 Issues 和 PR。
專案地址:
相關文章
- 記一次mysql小版本升級MySql
- 升級opatch工具
- 分散式的版本控制工具分散式
- 記一次版本升級遇到的坑
- 一次系統升級的過程
- Redis分散式鎖升級版RedLock及SpringBoot實現Redis分散式Spring Boot
- 記一次8小時驚心動魄的伺服器+網站升級伺服器網站
- 深圳農商行升級核心系統 打造分散式技術平臺分散式
- 分散式編譯工具分散式編譯
- 記一次macOS Mojave升級GCCMacGC
- 遷移式升級的測試
- react-router 升級小記React
- JDK升級問題小結JDK
- 效能躍升50%!解密自主研發的金融級分散式關聯式資料庫OceanBase 2.0解密分散式資料庫
- 【分散式計算】分散式日誌匯入工具-Flume分散式
- 資料庫升級和工具資料庫
- Git分散式版本控制工具Git分散式
- 遷移式升級的測試(二)
- 遷移式升級的測試(三)
- 遷移式升級的一點思考
- win10升級遮蔽工具怎麼使用_win10升級遮蔽工具如何操作Win10
- 記一次奇妙的 go-protobuf 包升級之旅Go
- 記一次uboot升級過程的兩個坑boot
- 【Oracle版本升級圖--小麥苗】Oracle
- React v16升級小記React
- 分散式鎖--Redis小試牛刀分散式Redis
- 分散式系統小筆記分散式筆記
- 分散式事務保姆級教程分散式
- POSTGRESQL 小版本升級失敗後的原因分析SQL
- 【經典揭祕】集中式架構怎麼升級為分散式架構?架構分散式
- 實戰訓練營:傳統分散式架構如何進行容器化升級分散式架構
- NMAP分散式掃描工具dnmap分散式
- 升級Monterey 12.x的朋友也可以用!Win式工作列工具uBar
- 在升級的時候使用VNC的小竅門VNC
- 【原始碼】Scrollsubplot:subplot函式的升級版原始碼函式
- MySQL升級WRITE_SET後的一次死鎖分析MySql
- 工程優化暨babel升級小記優化Babel
- async語法升級踩坑小記