安全組配置和選擇
由于Redis 3.0和Redis 4.0/5.0/6.0實例的部(bu)署模式(shi)不(bu)一(yi)樣(yang),DCS在控制訪問緩存實例的方式(shi)也(ye)不(bu)一(yi)樣(yang),差別如(ru)下(xia):
- Redis 3.0:通過配置安全組訪問規則控制,不支持白名單功能。安全組配置操作請參考本章節操作。
- Redis 4.0/5.0/6.0:不支持安全組,只支持通過白名單控制。
VPC內訪問Redis 3.0實例
客(ke)戶端只(zhi)能部署在(zai)與DCS緩存(cun)實例處于相同虛擬(ni)私有云(VPC)和相同子網的彈性云主機(ji)(ECS)上(shang)。
除了ECS、DCS緩存實(shi)(shi)例(li)必須處于相同VPC和(he)相同子網之外,還需要將安全組分別配置了正確的規則(ze),客戶(hu)端(duan)才能訪問(wen)DCS緩存實(shi)(shi)例(li)。
- 如果ECS、DCS緩存實例配置了相同的安全組,安全組創建后,默認包含組內網絡訪問不受限制的規則。
- 如果ECS、DCS緩存實例配置了不同的安全組,可參考如下配置方式:
說明
假(jia)設ECS、DCS緩存實例(li)分別配置了安全組:sg-ECS、sg-DCS。
假設DCS緩存實(shi)例服務端口為6379。
以下規(gui)則,遠端可(ke)使用安(an)全組,也可(ke)以使用具體的IP地(di)址。
a. 配置ECS所在安(an)全組。
ECS所在安全(quan)組(zu)需要增加(jia)(jia)出(chu)方向規則,以保證客戶端能正常訪問(wen)DCS緩存實例。如果出(chu)方向規則不受限,則不用添加(jia)(jia)。


b. 配(pei)置DCS緩(huan)存實例(li)所在安(an)全組。
DCS實例所在安全組需要增加入方向(xiang)規則,以保證能被客戶端訪問。


注意緩存實例的入方(fang)向規則中,遠端地址(zhi)建(jian)議使用與(yu)子網同(tong)網段的IP地址(zhi)。
慎用“0.0.0.0/0”,避免(mian)綁定(ding)相(xiang)同安(an)全組的彈性云主(zhu)機遭受Redis漏洞攻擊。
DCS實例支持公網訪問嗎?
不支(zhi)持在(zai)DCS實例(li)綁定(ding)彈性IP進行公網(wang)訪(fang)問(wen)的(de)方式。您必(bi)須通過(guo)同一虛擬私有云下的(de)彈性云主機來訪(fang)問(wen)緩(huan)(huan)存(cun)實例(li),以確保緩(huan)(huan)存(cun)數據(ju)的(de)安全。
DCS實例是否支持跨VPC訪問?
跨VPC訪問(wen),即客(ke)戶端和實例(li)是否在(zai)同(tong)一(yi)個VPC。
一(yi)般情況下(xia),不同(tong)VPC間網絡(luo)不互通,不在同(tong)一(yi)VPC下(xia)的彈性云主(zhu)機無法訪問DCS緩存實例(li)。
對于(yu)單機(ji)和主備(bei)類型的DCS緩存實(shi)例,可以通過創建VPC對等連接,將兩個VPC的網絡打通,實(shi)現跨VPC訪問(wen)DCS緩存實(shi)例。
用戶通過VPC對(dui)等訪問DCS緩存實例(li)時,除了滿足VPC對(dui)等網跨VPC訪問的約(yue)束之(zhi)外(wai),還存在(zai)如下約(yue)束:
- 當創建實例時使用了172.16.0.0/12~24網段時,客戶端不能在192.168.1.0/24、192.168.2.0/24、192.168.3.0/24網段。
- 當創建實例時使用了192.168.0.0/16~24網段時,客戶端不能在172.31.1.0/24、172.31.2.0/24、172.31.3.0/24網段。
- 當創建實例時使用了10.0.0.0/8~24網段時,客戶端不能在172.31.1.0/24、172.31.2.0/24、172.31.3.0/24網段。
關于創建和使用VPC對等連(lian)接,請參(can)考《虛擬私有(you)云(yun) 用戶指南》的(de)“對等連(lian)接”章節。
注意DCS Redis集群實(shi)例不支持跨VPC訪問,比(bi)如(ru)不(bu)能通過建立VPC對等連接的(de)方(fang)式,從一個VPC去訪問另一個(ge)VPC的集群實例。
Redis連接時報錯:“(error) NOAUTH Authentication required”。
報錯信息是(shi)指實例設置(zhi)了免密訪問(wen)。連接時不(bu)輸入密碼(ma),即可(ke)避免上述錯誤。
客戶Http的Server端關閉導致Redis訪問失敗
原因分(fen)析:客戶(hu)端(duan)使用(yong)長連(lian)接(jie),或者連(lian)接(jie)池,用(yong)完后關閉與DCS實例的連(lian)接(jie),再次使用(yong)時,出現報錯。
解決方案:使用長連(lian)接或連(lian)接池,用完后不要關閉連(lian)接;如(ru)果發現連(lian)接中斷(duan),請重新建連(lian)。
客戶端出現概率性超時錯誤
針對低概率(lv)超時錯誤(wu),是(shi)Redis使用(yong)的(de)正常現(xian)象(xiang)。Redis使用(yong)受到網絡(luo)傳輸、客戶端(duan)設置(zhi)超時時間等因素(su)影響,可能(neng)出(chu)現(xian)單個請求(qiu)超時問題。
建議客戶(hu)業務(wu)編(bian)碼時,具備重試操作(zuo),提(ti)升業務(wu)的可靠性(xing),避免低概率的單次(ci)請求失敗(bai)時業務(wu)失敗(bai)。
當出現了(le)連(lian)接超時(shi)問題時(shi),可以(yi)優先檢查Redis是否開(kai)啟(qi)了(le)aof持久化功能,這(zhe)需要(yao)根(gen)據業務需求,決(jue)定是否開(kai)啟(qi),防止出現阻(zu)塞(sai),連(lian)接不(bu)上的情況。
如果出現超(chao)時錯誤概率(lv)頻繁,請聯(lian)系(xi)服務(wu)運維(wei)。
使用Jedis連接池報錯如何處理?
在使(shi)用Jedis連接池JedisPool模式下,比(bi)較常見(jian)的報錯如下:
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
首先確認DCS緩存實例(li)是正常運行中狀態,然后按以下步驟進行排查。
步驟 1 網絡
- 核對IP地址配置
檢(jian)查jedis客戶(hu)端配置(zhi)的ip地址是否與DCS緩(huan)存實例(li)配置(zhi)的子(zi)網地址一致。
- 測試網絡
在(zai)客戶端使用ping和Telnet小工具測(ce)試網(wang)絡。
? 如果ping不通:
VPC內訪問(wen)Redis 3.0實例(li)時,要求(qiu)客戶端與DCS緩存實例(li)的VPC相同,安(an)全組相同或者DCS緩存實例(li)的安(an)全組放開了(le)6379端口訪問(wen)。
? 如果IP地址可以ping通(tong),telnet對(dui)應的端口不通(tong),則嘗(chang)試(shi)重(zhong)啟實例,如重(zhong)啟后仍未恢復,請聯系技術支持。
步驟 2 檢查連接(jie)數(shu)是否超限
查看已(yi)建立(li)的網絡連(lian)接(jie)數是否超(chao)過JedisPool 配置的上限(xian)。如果(guo)連(lian)接(jie)數接(jie)近配置的上限(xian)值,則(ze)建議重啟服務觀(guan)察(cha)。如果(guo)明顯沒有接(jie)近,排除連(lian)接(jie)數超(chao)限(xian)可能。
Unix/Linux系(xi)統使(shi)用**:**
netstat -an | grep 6379 | grep ESTABLISHED | wc -l
Windows系(xi)統使用:
netstat -an | find "6379" | find "ESTABLISHED" /C
步驟(zou) 3 檢查JedisPool連(lian)接池(chi)代碼
如果連接數接近配置的(de)上(shang)限,請分析是業務(wu)并發原因,或是沒(mei)有正確使用JedisPool所致。
對于JedisPool連接池的操作,每次調用 jedisPool.getResource() 方法之后,需要調用 jedisPool.returnResource() 或者 jedis.close() 進行釋(shi)放,優先使用(yong)close()方法。
步驟 4 客(ke)戶端TIME_WAIT是否過多
通過ss -s查看time wait鏈接是否過多。


如果TIME_WAIT過(guo)多,可以調整內核參(can)數(/etc/sysctl.conf):
##當出現SYN等待隊列溢出時,啟用cookies來處理,可防范少量SYN攻擊
net.ipv4.tcp_syncookies = 1
##允許將TIME-WAIT sockets重新用于新的TCP連接
net.ipv4.tcp_tw_reuse = 1
##開啟TCP連接中TIME-WAIT sockets的快速回收
net.ipv4.tcp_tw_recycle = 1
##修改系統默認的TIMEOUT時間
net.ipv4.tcp_fin_timeout = 30
調整后重啟生效:/sbin/sysctl -p
步(bu)驟 5 無法解(jie)決問題
如(ru)果按照(zhao)以上(shang)原因排查之后還有問(wen)題,可以通過抓(zhua)包并將(jiang)異常時間點、異常信(xin)息以及抓(zhua)包文件(jian)發送給技術支(zhi)持協助分析(xi)。
抓包可(ke)使用tcpdump工具,命令(ling)如下:
tcpdump -i eth0 tcp and port 6379 -n -nn -s 74 -w dump.pcap
Windows系統下還可以安裝Wireshark工具抓包。
說明
網卡名請改成實(shi)際的網卡名稱。
客戶端訪問Redis實例出現“ERR unknown command”的原因是什么?
有以下可能原因:
- 命令拼寫不正確
如下圖所示,命令拼寫有誤,Redis實例返回“ERR unknown command”,刪除String的正確命令為 del 。


- 在低版本Redis實例運行高版本命令
如下圖所示(shi),在Redis3.0版本運(yun)行Redis5.0新增的Stream相關(guan)命令(ling),Redis實(shi)例返回命令(ling)出錯信息。


- 部分命令被禁用
DCS Redis實例接口與開源Redis在數據訪問方面完全兼容。但因易用性和安全性的原因,部分管理操作不能從Redis客戶端發起,具體禁用的命令清單,請參考Redis命令。
如何使用Redis-desktop-manager訪問Redis實例?
如下介紹通過內網使用Redis-desktop-manager訪問Redis實例的操作:
1.填寫DCS實例子網地(di)址(zhi),端口(kou)6379,以(yi)及相應密碼。
2.單(dan)擊左下角(jiao)“測試連接”。
提示成功后,說(shuo)明(ming)連接正(zheng)常。
通過內網使用(yong)Redis-desktop-manager訪(fang)問Redis實例

說明
使(shi)用(yong)Redis-desktop-manager訪問DCS集群(qun)實例時,執行redis命(ming)令(ling)是(shi)正常的(de),但是(shi)左側顯示異常,這個是(shi)因(yin)為DCS集群(qun)是(shi)基于codis架構,info命(ming)令(ling)的(de)輸出和(he)原生的(de)redis不一樣(yang)。
使用SpringCloud時出現ERR Unsupported CONFIG subcommand怎么辦?
DCS的Redis實例(li)(li)可以配(pei)合Spring_Session進行Session共享。DCS的Redis實例(li)(li)對接SpringCloud時,遇(yu)到如下錯(cuo)誤信(xin)息:
Spring Cloud報錯(cuo)信息


原因(yin)為出于安全考慮,DCS暫不支(zhi)持客戶端發(fa)起(qi)的CONFIG命令,需(xu)要(yao)按如(ru)下步(bu)驟進行操作:
- 通過管理控制臺修改Redis實例的配置參數notify-keyspace-event,將值指定為“Egx”。
- 在Spring框架的XML配置文件中,增加如下:
<util:constant
static-field="org.springframework.session.data.redis.config.ConfigureRedisAction.NO_OP"/>
- 修改Spring相關代碼,通過啟用ConfigureRedisAction.NO_OP這個bean組件,禁止通過客戶端調用CONFIG命令,避免報錯。
@Bean
public static ConfigureRedisAction configureRedisAction() {
return ConfigureRedisAction.NO_OP;
}
更多說明,可參考。
注意
僅Redis單(dan)機和主(zhu)備實例支(zhi)持(chi)Spring的(de)Session共(gong)享,Redis集群(qun)版不支(zhi)持(chi)。
連接實例必須使用密碼嗎?如何獲取密碼?
- Redis實例支持密碼模式和免密模式。Redis本身支持不設置密碼,客戶端可以直接連接Redis緩存服務并使用,但出于安全考慮,建議盡量選用密碼模式,通過密碼來鑒權驗證,提升安全性。若選用密碼模式,您需要在創建實例時自定義密碼。
- 如需修改Redis訪問方式、修改或重置密碼,請參考密碼管理。
Redis實例連接失敗的原因排查
初步排查:
- 檢查連接地址
連接地址可從管(guan)理控制(zhi)臺的實例詳(xiang)情頁面獲取。
- 檢查密碼
密碼輸入錯誤時,端口可以連(lian)接上,但鑒權(quan)認證失敗(bai)。
- 檢查端口
VPC內訪問,Redis實例端口(kou)默認(ren)為6379。
- 檢查帶寬是否使用超限
當(dang)實(shi)例使用帶寬達到實(shi)例規格上限,可能會(hui)導致部分Redis連接超時現象。
- 如果是Redis 3.0實例,檢查安全組的入方向規則
VPC內訪問時,如果(guo)Redis客(ke)戶端(duan)和Redis實例(li)綁定了不同的(de)安全組,則需要將Redis實例(li)的(de)入方向安全組放開6379端(duan)口。
具體請參考:安全組配置和選擇。
- 如果是Redis 4.0/5.0/6.0實例,檢查白名單配置
如(ru)果實例(li)開啟了白名單,在使(shi)用客戶端連(lian)接時,需要確(que)保(bao)客戶端IP在白名單內,如(ru)果不在白名單,會出(chu)現(xian)連(lian)接失敗(bai)。
客戶端IP如果有變化,需要將變化后的IP加入白名單。
- 檢查實例配置參數notify-keyspace-events
建議(yi)將notify-keyspace-events參數(shu)配置(zhi)為(wei)Egx。
進階排查
- Jedis連接池報錯
- 出現Read timed out或Could not get a resource from the pool
排(pai)查是否使用了keys命(ming)令(ling)(ling)(ling),keys命(ming)令(ling)(ling)(ling)會消(xiao)耗大量(liang)資源(yuan),造成Redis阻塞。建議使用scan命(ming)令(ling)(ling)(ling)替代(dai),且避免頻繁(fan)執行。
使用短連接訪問Redis出現“Cannot assign requested address”錯誤
問題描述
應用(yong)程序通過(guo)短連(lian)接訪(fang)問Redis實(shi)例(li)時(shi),報錯:Cannot assign requested address。
問題分析
出(chu)現這種(zhong)錯誤(wu)的(de)(de)應用(yong)程序使(shi)用(yong)的(de)(de)架構基本都(dou)是(shi)php-fpm加上phpredis,這種(zhong)架構在并發(fa)量較(jiao)大(da)的(de)(de)情況下(xia),處于(yu)TIME-WAIT狀態下(xia)的(de)(de)TCP連(lian)接數較(jiao)多,客戶端無法分配出(chu)新的(de)(de)端口,則會(hui)出(chu)現“Cannot assign requested address”問題。
處理方案
- 方案一:使用pconnect替換connect。
此方案的思路是用長連接(jie)替(ti)代(dai)短連接(jie),減(jian)少TCP連接(jie),同時(shi)可以避免每(mei)次請求(qiu)都會重新建(jian)立連接(jie)的問題(ti),減(jian)少延時(shi)。
之前連(lian)接Redis的代碼如下:
$redis->connect('${Hostname}',${Port});
$redis->auth('${Inst_Password}');
現使用(yong)pconnect替(ti)換connect,即使用(yong)persistent connection的方式連接(jie)。
$redis->pconnect('${Hostname}', ${Port}, 0, NULL, 0, 0, ['auth' => ['${Inst_Password}']]);
說明
示(shi)例中(zhong)的(de)連接參(can)數(shu)請(qing)根(gen)據業務(wu)實(shi)(shi)現情(qing)況修改,${Hostname}、${Port}和(he)${Inst_Password}為(wei)Redis實(shi)(shi)例的(de)連接地(di)址、端口號和(he)密碼(ma)。
PhpRedis應為5.3.0及以上版本,且(qie)建議使用這(zhe)種pconnect初始化方(fang)式(shi),避(bi)免斷連(lian)時出現no auth問題。
- 方案二:修改客戶端所在ECS實例的tcp_max_tw_buckets內核參數。
此方(fang)案的思路是直接復用(yong)處(chu)于TIME-WAIT狀態的端口(kou),但是如果ECS和后(hou)端服務之間有重傳,連(lian)接可能(neng)會失敗,所(suo)以建(jian)議使用(yong)pconnect的方(fang)案。
a. 連接(jie)客戶端所在ECS實例。
b. 執行以下命令(ling),查看ip_local_port_range和tcp_max_tw_buckets參數。
sysctl net.ipv4.tcp_max_tw_buckets net.ipv4.ip_local_port_range
系統顯示類似如下:
net.ipv4.tcp_max_tw_buckets = 262144
net.ipv4.ip_local_port_range = 32768 61000
c. 執行以下命令,修改tcp_max_tw_buckets參數,確保tcp_max_tw_buckets的值比ip_local_port_range范圍的值小。
sysctl -w net.ipv4.tcp_max_tw_buckets=10000
一般情況推薦(jian)使(shi)用方案(an)一,對于一些特定場(chang)景(業務代碼牽(qian)涉過(guo)多組件(jian)不易變更等場(chang)景),需要更快的滿足高并發(fa),可以使(shi)用方案(an)二
連接池選擇及Jedis連接池參數配置建議
Jedis連接池優勢
Lettuce客戶端(duan)及Jedis客戶端(duan)比較如(ru)下:
-
Lettuce:
- Lettuce客戶端沒有連接保活探測,錯誤連接存在連接池中會造成請求超時報錯。
- Lettuce客戶端未實現testOnBorrow等連接池檢測方法,無法在使用連接之前進行連接校驗。
-
Jedis:
- Jedis客戶端實現了testOnBorrow、testWhileIdle、testOnReturn等連接池校驗配置
- 開啟testOnBorrow在每次借用連接前都會進行連接校驗,可靠性最高,但是會影響性能(每次Redis請求前會進行探測)。
- testWhileIdle可以在連接空閑時進行連接檢測,合理配置閾值可以及時剔除連接池中的異常連接,防止使用異常連接造成業務報錯。
- 在空閑連接檢測之前,連接出現問題,可能會造成使用該連接的業務報錯,此處可以通過參數控制檢測間隔(timeBetweenEvictionRunsMillis)。
因(yin)此,Jedis客戶端在(zai)面對連接異(yi)常,網絡抖動(dong)等場景下的(de)異(yi)常處理和(he)檢測能力明顯強(qiang)于Lettuce,可靠(kao)性更強(qiang)。
Jedis連接池參數配置建議
| 參數 | 配置介紹 | 配置建議 |
|---|---|---|
| maxTotal | 最大連接,單位:個 | 根據Web容器的Http線程數來進行配置,估算單個Http請求中可能會并行進行的Redis調用次數,例如:Tomcat中的Connector內的maxConnections配置為150,每個Http請求可能會并行執行2個Redis請求,在此之上進行部分預留,則建議配置至少為:150 x 2 + 100= 400**限制條件:**單個Redis實例的最大連接數。maxTotal和客戶端節點數(CCE容器或業務VM數量)數值的乘積要小于單個Redis實例的最大連接數。例如:Redis主備實例配置maxClients為10000,單個客戶端maxTotal配置為500,則最大客戶端節點數量為20個。 |
| maxIdle | 最大空閑連接,單位:個 | 建議配置為maxTotal一致。 |
| minIdle | 最小空閑連接,單位:個 | 一般來說建議配置為maxTotal的X分之一,例如此處常規配置建議為:100。對于性能敏感的場景,防止經常連接數量抖動造成影響,也可以配置為與maxIdle一致,例如:400。 |
| maxWaitMillis | 最大獲取連接等待時間,單位:毫秒 | 獲取連接時最大的連接池等待時間,根據單次業務最長容忍的失敗時間減去執行命令的超時時間得到建議值。例如:Http最大容忍超時時間為15s,Redis請求的timeout設置為10s,則此處可以配置為5s。 |
| timeout | 命令執行超時時間,單位:毫秒 | 單次執行Redis命令最大可容忍的超時時間,根據業務程序的邏輯進行選擇,一般來說處于對網絡容錯等考慮至少建議配置為210ms以上。特殊的探測邏輯或者環境異常檢測等,可以適當調整達到秒級。 |
| minEvictableIdleTimeMillis | 空閑連接逐出時間,大于該值的空閑連接一直未被使用則會被釋放,單位:毫秒 | 如果希望系統不會經常對連接進行斷鏈重建,此處可以配置一個較大值(xx分鐘),或者此處配置為-1并且搭配空閑連接檢測進行定期檢測。 |
| timeBetweenEvictionRunsMillis | 空閑連接探測時間間隔,單位:毫秒 | 根據系統的空閑連接數量進行估算,例如系統的空閑連接探測時間配置為30s,則代表每隔30s會對連接進行探測,如果30s內發生異常的連接,經過探測后會進行連接排除。根據連接數的多少進行配置,如果連接數太大,配置時間太短,會造成請求資源浪費。對于幾百級別的連接,常規來說建議配置為30s,可以根據系統需要進行動態調整。 |
| testOnBorrow | 向資源池借用連接時是否做連接有效性檢測(ping),檢測到的無效連接將會被移除。 | 對于業務連接極端敏感的,并且性能可以接受的情況下,可以配置為True,一般來說建議配置為False,啟用連接空閑檢測。 |
| testWhileIdle | 是否在空閑資源監測時通過ping命令監測連接有效性,無效連接將被銷毀。 | True |
| testOnReturn | 向資源池歸還連接時是否做連接有效性檢測(ping),檢測到無效連接將會被移除。 | False |
| maxAttempts | 在JedisCluster模式下,您可以配置maxAttempts參數來定義失敗時的重試次數。 | 建議配置3-5之間,默認配置為5。根據業務接口最大超時時間和單次請求的timeout綜合配置,最大配置不建議超過10,否則會造成單次請求處理時間過長,接口請求阻塞。 |