介(jie)紹使(shi)(shi)用(yong)同一VPC內彈性云主機ECS上的(de)Jedis連接Redis實(shi)例的(de)方(fang)(fang)法。更多的(de)客戶端的(de)使(shi)(shi)用(yong)方(fang)(fang)法請參考(kao)。
在(zai)(zai)springboot類型的(de)項目中,spring-data-redis中已提供了(le)對、的(de)集成(cheng)適(shi)配。另外(wai),在(zai)(zai)springboot1.x中默(mo)認(ren)集成(cheng)的(de)是jedis,springboot2.x中改為了(le)lettuce,因此在(zai)(zai)springboot2.x及更(geng)高版本中想集成(cheng)使用(yong)jedis,需要(yao)對已集成(cheng)的(de)lettuce組(zu)件依賴進行排(pai)包
前提條件
- 已成功申請Redis實例,且狀態為“運行中”。
- 查看并獲取待連接Redis實例的IP地址和端口。
具體步驟請參見查看實例信息。
- 已創建彈性云主機,創建彈性云主機的方法,請參見《彈性云主機用戶指南》。
- 如果彈性云主機為Linux系統,該彈性云主機必須已經安裝java編譯環境。
Pom配置
<!-- 引入spring-data-redis組件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<!--spring boot 2.0之后默認lettuce客戶端, 使用jedis時需要排包-->
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 引入jedis依賴包 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.6.0</version>
</dependency>
基于application.properties配置
- 單機、主備、讀寫分離、Proxy集群實例配置
#redis host
spring.redis.host=<host>
#redis 端口號
spring.redis.port=<port>
#redis 數據庫下標
spring.redis.database=0
#redis 密碼
spring.redis.password=<password>
#redis 讀寫超時
spring.redis.timeout=2000
#是否開啟連接池
spring.redis.jedis.pool.enabled=true
#連接池的最小連接數
spring.redis.jedis.pool.min-idle=50
#連接池的最大空閑連接數
spring.redis.jedis.pool.max-idle=200
#連接池的最大連接數
spring.redis.jedis.pool.max-active=200
#連接池耗盡后獲取連接的最大等待時間,默認-1表示一直等待
spring.redis.jedis.pool.max-wait=3000
#空閑連接逐出的檢測周期,默認為60S
spring.redis.jedis.pool.time-between-eviction-runs=60S
- Cluster集群實例配置
#redis cluster節點連接信息
spring.redis.cluster.nodes=<ip:port>,<ip:port>,<ip:port>
#redis cluster密碼
spring.redis.password=<password>
#redis cluster訪問最大重定向次數
spring.redis.cluster.max-redirects=3
#redis 讀寫超時
spring.redis.timeout=2000
#是否開啟連接池
spring.redis.jedis.pool.enabled=true
#連接池的最小連接數
spring.redis.jedis.pool.min-idle=50
#連接池的最大空閑連接數
spring.redis.jedis.pool.max-idle=200
#連接池的最大連接數
spring.redis.jedis.pool.max-active=200
#連接池耗盡后獲取連接的最大等待時間,默認-1表示一直等待
spring.redis.jedis.pool.max-wait=3000
#空閑連接逐出的檢測周期,默認為60S
spring.redis.jedis.pool.time-between-eviction-runs=60S
基于Bean方式配置
- 單機、主備、讀寫分離、Proxy集群實例配置
import java.time.Duration; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.jedis.JedisClientConfiguration; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import redis.clients.jedis.JedisPoolConfig; @Configuration public class RedisConfiguration { @Value("${redis.host}") private String redisHost; @Value("${redis.port:6379}") private Integer redisPort = 6379; @Value("${redis.database:0}") private Integer redisDatabase = 0; @Value("${redis.password:}") private String redisPassword; @Value("${redis.connect.timeout:3000}") private Integer redisConnectTimeout = 3000; @Value("${redis.read.timeout:2000}") private Integer redisReadTimeout = 2000; @Value("${redis.pool.minSize:50}") private Integer redisPoolMinSize = 50; @Value("${redis.pool.maxSize:200}") private Integer redisPoolMaxSize = 200; @Value("${redis.pool.maxWaitMillis:3000}") private Integer redisPoolMaxWaitMillis = 3000; @Value("${redis.pool.softMinEvictableIdleTimeMillis:1800000}") private Integer redisPoolSoftMinEvictableIdleTimeMillis = 30 * 60 * 1000; @Value("${redis.pool.timeBetweenEvictionRunsMillis:60000}") private Integer redisPoolBetweenEvictionRunsMillis = 60 * 1000; @Bean public RedisConnectionFactory redisConnectionFactory(JedisClientConfiguration clientConfiguration) { RedisStandaloneConfiguration standaloneConfiguration = new RedisStandaloneConfiguration(); standaloneConfiguration.setHostName(redisHost); standaloneConfiguration.setPort(redisPort); standaloneConfiguration.setDatabase(redisDatabase); standaloneConfiguration.setPassword(redisPassword); return new JedisConnectionFactory(standaloneConfiguration, clientConfiguration); } @Bean public JedisClientConfiguration clientConfiguration() { JedisClientConfiguration clientConfiguration = JedisClientConfiguration.builder() .connectTimeout(Duration.ofMillis(redisConnectTimeout)) .readTimeout(Duration.ofMillis(redisReadTimeout)) .usePooling().poolConfig(redisPoolConfig()) .build(); return clientConfiguration; } private JedisPoolConfig redisPoolConfig() { JedisPoolConfig poolConfig = new JedisPoolConfig(); //連接池的最小連接數 poolConfig.setMinIdle(redisPoolMinSize); //連接池的最大空閑連接數 poolConfig.setMaxIdle(redisPoolMaxSize); //連接池的最大連接數 poolConfig.setMaxTotal(redisPoolMaxSize); //連接池耗盡后是否需要等待,默認true表示等待。當值為true時,setMaxWait才會生效 poolConfig.setBlockWhenExhausted(true); //連接池耗盡后獲取連接的最大等待時間,默認-1表示一直等待 poolConfig.setMaxWaitMillis(redisPoolMaxWaitMillis); //創建連接時校驗有效性(ping),默認false poolConfig.setTestOnCreate(false); //獲取連接時校驗有效性(ping),默認false,業務量大時建議設置為false減少開銷 poolConfig.setTestOnBorrow(true); //歸還連接時校驗有效性(ping),默認false,業務量大時建議設置為false減少開銷 poolConfig.setTestOnReturn(false); //是否開啟空閑連接檢測,如為false,則不剔除空閑連接 poolConfig.setTestWhileIdle(true); //連接空閑多久后逐出,空閑時間>該值,并且空閑連接>最大空閑數時直接逐出 poolConfig.setSoftMinEvictableIdleTimeMillis(redisPoolSoftMinEvictableIdleTimeMillis); //關閉根據MinEvictableIdleTimeMillis判斷逐出 poolConfig.setMinEvictableIdleTimeMillis(-1); //空閑連接逐出的檢測周期,默認為60S poolConfig.setTimeBetweenEvictionRunsMillis(redisPoolBetweenEvictionRunsMillis); return poolConfig; } } - Cluster集群實例配置
import java.time.Duration; import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisClusterConfiguration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisNode; import org.springframework.data.redis.connection.jedis.JedisClientConfiguration; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import redis.clients.jedis.JedisPoolConfig; @Configuration public class RedisConfiguration { @Value("${redis.cluster.nodes}") private String redisClusterNodes; @Value("${redis.password:}") private String redisPassword; @Value("${redis.connect.timeout:3000}") private Integer redisConnectTimeout = 3000; @Value("${redis.read.timeout:2000}") private Integer redisReadTimeout = 2000; @Value("${redis.pool.minSize:50}") private Integer redisPoolMinSize = 50; @Value("${redis.pool.maxSize:200}") private Integer redisPoolMaxSize = 200; @Value("${redis.pool.maxWaitMillis:3000}") private Integer redisPoolMaxWaitMillis = 3000; @Value("${redis.pool.softMinEvictableIdleTimeMillis:1800000}") private Integer redisPoolSoftMinEvictableIdleTimeMillis = 30 * 60 * 1000; @Value("${redis.pool.timeBetweenEvictionRunsMillis:60000}") private Integer redisPoolBetweenEvictionRunsMillis = 60 * 1000; @Bean public RedisConnectionFactory redisConnectionFactory(JedisClientConfiguration clientConfiguration) { RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration(); List<RedisNode> clusterNodes = new ArrayList<>(); for (String clusterNodeStr : redisClusterNodes.split(",")) { String[] nodeInfo = clusterNodeStr.split(":"); clusterNodes.add(new RedisNode(nodeInfo[0], Integer.valueOf(nodeInfo[1]))); } clusterConfiguration.setClusterNodes(clusterNodes); clusterConfiguration.setPassword(redisPassword); clusterConfiguration.setMaxRedirects(3); return new JedisConnectionFactory(clusterConfiguration, clientConfiguration); } @Bean public JedisClientConfiguration clientConfiguration() { JedisClientConfiguration clientConfiguration = JedisClientConfiguration.builder() .connectTimeout(Duration.ofMillis(redisConnectTimeout)) .readTimeout(Duration.ofMillis(redisReadTimeout)) .usePooling().poolConfig(redisPoolConfig()) .build(); return clientConfiguration; } private JedisPoolConfig redisPoolConfig() { JedisPoolConfig poolConfig = new JedisPoolConfig(); //連接池的最小連接數 poolConfig.setMinIdle(redisPoolMinSize); //連接池的最大空閑連接數 poolConfig.setMaxIdle(redisPoolMaxSize); //連接池的最大連接數 poolConfig.setMaxTotal(redisPoolMaxSize); //連接池耗盡后是否需要等待,默認true表示等待。當值為true時,setMaxWait才會生效 poolConfig.setBlockWhenExhausted(true); //連接池耗盡后最大等待時間,默認-1表示一直等待 poolConfig.setMaxWaitMillis(redisPoolMaxWaitMillis); //創建連接時校驗有效性(ping),默認false poolConfig.setTestOnCreate(false); //獲取連接時校驗有效性(ping),默認false,業務量大時建議設置為false減少開銷 poolConfig.setTestOnBorrow(true); //歸還連接時校驗有效性(ping),默認false,業務量大時建議設置為false減少開銷 poolConfig.setTestOnReturn(false); //是否開啟空閑連接檢測,如為false,則不剔除空閑連接 poolConfig.setTestWhileIdle(true); //連接空閑多久后逐出,當空閑時間>該值,并且空閑連接>最大空閑數時直接逐出 poolConfig.setSoftMinEvictableIdleTimeMillis(redisPoolSoftMinEvictableIdleTimeMillis); //關閉根據MinEvictableIdleTimeMillis判斷逐出 poolConfig.setMinEvictableIdleTimeMillis(-1); //空閑連接逐出的檢測周期,默認為60s poolConfig.setTimeBetweenEvictionRunsMillis(redisPoolBetweenEvictionRunsMillis); return poolConfig; } }
參數明細
RedisStandaloneConfiguration參數
| 參數 | 默認值 | 說明 |
|---|---|---|
| hostName | localhost | 連接Redis實例的IP地址 |
| port | 6379 | 連接端口號 |
| database | 0 | 數據庫下標,默認0 |
| password | - | 連接密碼 |
RedisClusterConfiguration參(can)數(shu)
| 參數 | 說明 |
|---|---|
| clusterNodes | cluster節點連接信息,需IP、Port |
| maxRedirects | cluster訪問最大重定向次數 |
| password | 連接密碼 |
JedisPoolConfig參數
| 參數 | 默認值 | 說明 |
|---|---|---|
| minIdle | - | 連接池的最小連接數 |
| maxIdle | - | 連接池的最大空閑連接數 |
| maxTotal | - | 連接池的最大連接數 |
| blockWhenExhausted | true | 連接池耗盡后是否需要等待,默認true表示等待,false表示不等待。當值為true時,設置maxWaitMillis才會生效 |
| maxWaitMillis | -1 | 連接池耗盡后獲取連接的最大等待時間,單位:毫秒。默認-1表示一直等待 |
| testOnCreate | false | 創建連接時校驗有效性(ping),false:不校驗,true:校驗。 |
| testOnBorrow | false | 獲取連接時校驗有效性(ping),false:不校驗,true:校驗。業務量大時建議設置為false減少開銷 |
| testOnReturn | false | 歸還連接時校驗有效性(ping),false:不校驗,true:校驗。業務量大時建議設置為false減少開銷 |
| testWhileIdle | false | 是否開啟空閑連接檢測,如為false,則不剔除空閑連接,建議值:true |
| softMinEvictableIdleTimeMillis | 1800000 | 連接空閑多久后逐出,(空閑時間>該值 && 空閑連接>最大空閑數)時直接逐出,單位:毫秒 |
| minEvictableIdleTimeMillis | 60000 | 根據minEvictableIdleTimeMillis時間判斷逐出,單位:毫秒。建議值:-1,表示關閉該策略,改用softMinEvictableIdleTimeMillis策略 |
| timeBetweenEvictionRunsMillis | 60000 | 空閑連接逐出的檢測周期,單位:毫秒 |
JedisClientConfiguration參(can)數
| 參數 | 默認值 | 說明 |
|---|---|---|
| connectTimeout | 2000 | 連接超時時間,單位:毫秒 |
| readTimeout | 2000 | 請求等待響應的超時時間,單位:毫秒 |
| poolConfig | - | 池化配置,具體請參見JedisPoolConfig |
DCS實例配置建議
- 連接池配置
說明以下計算方式只適用于一般業務場景,建議根據業務情況做適當調整適配。
連(lian)接(jie)池(chi)的大(da)小(xiao)沒有絕(jue)對的標(biao)準,建議根據(ju)業務流量進行(xing)合理配(pei)置,一般連(lian)接(jie)池(chi)大(da)小(xiao)的參數計算(suan)公(gong)式如(ru)下:
最小(xiao)連(lian)接數=(單機(ji)訪(fang)問Redis QPS)/(1000ms / 單命令平均耗時)
最大連接數=(單機(ji)訪(fang)問Redis QPS)/(1000ms / 單命令平(ping)均耗(hao)時)* 150%
舉(ju)例:某個(ge)業(ye)務(wu)應用的QPS為(wei)10000左右,每(mei)個(ge)請求需(xu)訪(fang)問(wen)Redis10次(ci),即(ji)每(mei)秒對Redis的訪(fang)問(wen)次(ci)數為(wei)100000次(ci),同時該業(ye)務(wu)應用有10臺機器,計算如下(xia):
單機訪問Redis QPS = 100000 / 10 = 10000
單命令(ling)平均(jun)耗時(shi) = 20ms(Redis處理單命令(ling)耗時(shi)為(wei)5-10ms,遇到(dao)網絡抖(dou)動(dong)按(an)照(zhao)15-20ms來估算(suan))
最小連接數 =(10000)/(1000ms / 20ms)= 200
最大連接數 =(10000)/(1000ms / 20ms)* 150% = 300