文章目錄
StackExchange 連線 Redis 出現 Timeout
同事反應出現大量 Redis 連線 Timeout 的錯誤,因為 Redis 上存放 Sessoion 跟許多 config cache 資料,如果 Redis 異常會嚴重影響線上服務,所以立馬需要進行除錯
首先使用 Redis-cli 確認服務仍正常執行中,接著執行了 Redis Benchmark 檢查 server 回應,數據並沒有發現異常,使用 Redis Desktop Manager 連線 Redis 資料也可以正常取得,推測 Redis server 本身應該是正常的
接著確認同事的使用情境後發現並非全面性出現 Redis timeout 只有存取幾個特定的 key 會出現問題。仔細檢查後發現:引起 timeout error 的 key 都有 size 較大的特徵,推測可能是資料量太大造成的
錯誤訊息
錯誤訊息
2017-06-28 18:04:56,025 [17] [ERROR] [RedisObjectStore`1] Inner exception number - 0 Timeout performing HGETALL faqscache:******.portal.bll.appdatamanager+cachedata, inst: 1, queue: 18, qu: 0, qs: 18, qc: 0, wr: 0, wq: 0, in: 0, ar: 0, clientName: TestAPP01, serverEndpoint: 127.0.0.1:8188, keyHashSlot: 3414, IOCP: (Busy=0,Free=1000,Min=2,Max=1000), WORKER: (Busy=6,Free=8185,Min=2,Max=8191) (Please take a look at this article for some common client-side issues that can cause timeouts: http://stackexchange.github.io/StackExchange.Redis/Timeouts) at StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[T](Message message, ResultProcessor`1 processor, ServerEndPoint server) at StackExchange.Redis.RedisBase.ExecuteSync[T](Message message, ResultProcessor`1 processor, ServerEndPoint server) at StackExchange.Redis.RedisDatabase.HashGetAll(RedisKey key, CommandFlags flags) at ******.Portal.BLL.Redis.RedisObjectStore`1.Get(String key) Main exception & its inner exception Log end
解決方式
- 修改資料同步 timeout 設定 - 放寬 syncTimeout 時間 (預設 1000 毫秒)
原始 redis 連線資訊
public static class RedisConnectionFactory { private static readonly Lazy<ConnectionMultiplexer> Connection; public static IServer RedisServer; static RedisConnectionFactory() { var connectionString = "127.0.0.1:6379,127.0.0.1:6380,password=password"; var options = ConfigurationOptions.Parse(connectionString); Connection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(options)); RedisServer = GetConnection.GetServer(options.EndPoints.First()); } public static ConnectionMultiplexer GetConnection => Connection.Value; public static IDatabase RedisDB => GetConnection.GetDatabase(); }
修改後
public static class RedisConnectionFactory { private static readonly Lazy<ConnectionMultiplexer> Connection; public static IServer RedisServer; static RedisConnectionFactory() { var connectionString = "127.0.0.1:6379,127.0.0.1:6380,password=password,syncTimeout =3000"; var options = ConfigurationOptions.Parse(connectionString); Connection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(options)); RedisServer = GetConnection.GetServer(options.EndPoints.First()); } public static ConnectionMultiplexer GetConnection => Connection.Value; public static IDatabase RedisDB => GetConnection.GetDatabase(); }
心得
放寬資料同步時間後,timeout 問題確實獲得解決,但還是建議同事從源頭端來縮小 redis 的資料量大小,一來減少 network 傳輸的 io ,二來可以增加 redis 回應速度
參考資訊
文章作者 Yowko Tsai
上次更新 2021-10-15
授權合約
本部落格 (Yowko's Notes) 所有的文章內容(包含圖片),任何轉載行為,必須通知並獲本部落格作者 (Yowko Tsai) 的同意始得轉載,且轉載皆須註明出處與作者。
Yowko's Notes 由 Yowko Tsai 製作,以創用CC 姓名標示-非商業性-相同方式分享 3.0 台灣 授權條款 釋出。