分布式工具的一次小升級?

006tNc79ly1fs2s4f0jf4j31g80ytn6i.jpg

前言

之前在做 秒殺架構實踐 時有提到對 distributed-redis-tool 的一次小升級,但是沒有細說。

其實主要原因是:

秒殺時我做壓測:由于集成了這個限流組件,并發又比較大,所以導致連接、斷開 Redis 非常頻繁。
最終導致獲取不了 Redis connection 的異常。

池化技術

這就是一個典型的對稀缺資源使用不善導致的。

何為稀缺資源?常見的有:

  • 線程
  • 數據庫連接
  • 網絡連接等

這些資源都有共同的特點:創建銷毀成本較高

這里涉及到的 Redis 連接也屬于該類資源。

我們希望將這些稀有資源管理起來放到一個池子里,當需要時就從中獲取,用完就放回去,不夠用時就等待(或返回)。

這樣我們只需要初始化并維護好這個池子,就能避免頻繁的創建、銷毀這些資源(也有資源長期未使用需要縮容的情況)。

通常我們稱這項姿勢為池化技術,如常見的:

  • 線程池
  • 各種資源的連接池等。

為此我將使用到 Redis 的 分布式鎖、分布式限流 都升級為利用連接池來獲取 Redis 的連接。

這里以分布式鎖為例:

將使用的 api 修改為:

原有:

@Configuration
public class RedisLockConfig {@Beanpublic 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);@Autowiredprivate JedisConnectionFactory jedisConnectionFactory;@Beanpublic 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 connectionObject 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。

項目地址:

https://github.com/crossoverJie/distributed-redis-tool

轉載于:https://www.cnblogs.com/crossoverJie/p/9385900.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/249850.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/249850.shtml
英文地址,請注明出處:http://en.pswp.cn/news/249850.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

淺談vue $mount()

Vue 的$mount()為手動掛載&#xff0c;在項目中可用于延時掛載&#xff08;例如在掛載之前要進行一些其他操作、判斷等&#xff09;&#xff0c;之后要手動掛載上。new Vue時&#xff0c;el和$mount并沒有本質上的不同。 具體見代碼&#xff1a; 順便附上vue渲染機制流程圖&a…

小三角

{border-color: transparent;border-right-color: #e5e5e5;border-width: 7px;margin-top: -7px;right: 100%;top: 20px;border: solid transparent;content: " ";height: 0;width: 0;position: absolute;pointer-events: none; }轉載于:https://www.cnblogs.com/smz…

Laravel日志查看器 -- log-viewer擴展

1.修改laravel配置文件. config\app.php log>daily 2.在項目目錄中composer命令安裝擴展&#xff1a;composer require arcanedev/log-viewer 3.安裝成功后&#xff0c;需要在config\app.php 的providers陣列中注冊服務 Arcanedev\LogViewer\LogViewerServiceProvider::clas…

論一個程序員的自我修養-從一張圖片說起

故事起源 本來今天想寫.NET Core實戰之CMS系統第十五篇文章的。哈&#xff0c;奈何今天在新生命人脈群里面看到石頭哥分享的一張圖片&#xff0c;然后大家就議論了起來&#xff0c;不過我看的很懵逼&#xff0c;這圖什么意思啊&#xff1f;當一個朋友講述了這個圖片背后的故事的…

vue實例屬性之el,template,render

一、el&#xff0c;template&#xff0c;render屬性優先性 當Vue選項對象中有render渲染函數時&#xff0c;Vue構造函數將直接使用渲染函數渲染DOM樹&#xff0c;當選項對象中沒有render渲染函數時&#xff0c;Vue構造函數首先通過將template模板編譯生成渲染函數&#xff0c;然…

mysql8的坑

plugin caching_sha2_password could not be loaded 我在mac上用Sequel Pro連數據庫的時候&#xff0c;會報出以上錯誤&#xff0c;這是應為8.0.11把身份認證插件改成了 caching_sha2_password &#xff0c;而客戶端沒法使用此插件。 這是我們只要用命令行進去mysql&#xff0c…

c/c++ 繼承與多態 文本查詢的小例子(非智能指針版本)

問題&#xff1a;在上一篇繼承與多態 文本查詢的小例子&#xff08;智能指針版本&#xff09;在Query類里使用的是智能指針&#xff0c;只把智能指針換成普通的指針&#xff0c;并不添加拷貝構造方法&#xff0c;會發生什么呢&#xff1f; 執行時&#xff0c;代碼崩掉。 分析下…

day19_生成器

20180730 初次上傳 20180731 更新&#xff0c;4、列表生成式&#xff0c;以及部分注釋 #!/usr/bin/env python # -*- coding:utf-8 -*-# ********************day19_生成器 ******************* # ********************day19_生成器 ******************* # *******************…

HTML渲染過程詳解

由于本人對http協議以及dns對url的解析問題并不了解&#xff0c;所以這里之探討url請求加載到瀏覽器端時&#xff0c;瀏覽器對html的解析到呈現過程&#xff0c;后來經過幾位道友分享&#xff0c;整理了一下url解析的過程&#xff0c;如下&#xff1a; 用戶輸入url地址&#x…

grid布局

CSS Grid 布局CSS 中最強大的布局系統。與 flexbox 的一維布局系統不同&#xff0c;CSS Grid 布局是一個二維布局系統&#xff0c;也就意味著它可以同時處理列和行。通過將 CSS 規則應用于 父元素 (成為 Grid Container 網格容器)和其 子元素&#xff08;成為 Grid Items 網格項…

vue之router-view組件的使用

開發的時候有時候會遇到一種情況&#xff0c;比如 &#xff1a;點擊這個鏈接跳轉到其他組件的情況&#xff0c;通常會跳轉到新的頁面&#xff0c;蛋是&#xff0c;我們不想跳轉到新頁面&#xff0c;只在當前頁面切換著顯示&#xff0c;那么就要涉及到路由的嵌套了&#xff0c;也…

go 學習Printf

package main import "fmt" import "os" type point struct {x, y int } func main() { //Go 為常規 Go 值的格式化設計提供了多種打印方式。例如&#xff0c;這里打印了 point 結構體的一個實例。p : point{1, 2}fmt.Printf("%v\n", p) // {1 2…

博客園使用latex編輯公式

如何開啟數學公式編輯功能 開啟方法見下鏈接https://www.cnblogs.com/cmt/p/3279312.html 功能 支持數學公式塊支持文中數學公式DEMO $$ f(n) \begin{cases}\frac{n}{2}, & \text{if $n$ is even} \\3n1, & \text{if $n$ is odd}\end{cases} $$ 以上的代碼產生如下的公…

console.dir有很多瀏覽器,系統的兼容性問題,不要隨便用!

console.dir有很多瀏覽器&#xff0c;系統的兼容性問題&#xff0c;不要隨便用&#xff01; 要使用console.log();轉載于:https://www.cnblogs.com/bluestear/p/9400356.html

go 區分指針

先看一段代碼 先放一段代碼&#xff0c;人工運行一下&#xff0c;看看自己能做對幾題&#xff1f; package mainimport "fmt"func main() {var a int 1 var b *int &a var c **int &b var x int *b fmt.Println("a ",a) fmt.Println("&a…

ajax和axios、fetch的區別

1.jQuery ajax $.ajax({type: POST,url: url,data: data,dataType: dataType,success: function () {},error: function () {} });傳統 Ajax 指的是 XMLHttpRequest&#xff08;XHR&#xff09;&#xff0c; 最早出現的發送后端請求技術&#xff0c;隸屬于原始js中&#xff0c…

函數函數sigaction、signal

函數函數sigaction 1. 函數sigaction原型&#xff1a; int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); 分析&#xff1a; 參數 signum &#xff1a;要捕獲的信號。參數act&#xff1a;truct sigaction 結構體&#xff0c;后面具體講解傳入…

使用SQL Server連接xml接口,讀取并解析數據

--數據源格式&#xff0c;放到任意程序中部署接口即可--<Data xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd"http://www.w3.org/2001/XMLSchema"> --<Peoples> --<People> --<Name>張三</Name> --<S…

mac 卸載編輯器卸不干凈

Configuration~/Library/Preferences/Caches~/Library/Caches/Plugins~/Library/Application Support/Logs~/Library/Logs/轉載于:https://www.cnblogs.com/smzd/p/10114540.html

vue中使用axios最詳細教程

前提條件&#xff1a;vue-cli 項目 安裝&#xff1a; npm npm 在main.js導入&#xff1a; // 引入axios&#xff0c;并加到原型鏈中 import axios from axios; Vue.prototype.$axios axios; import QS from qs Vue.prototype.qs QS;封裝好的axios,拿走不送&#xff1a;&am…