自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Redis突然報錯,今晚又不能回家了...

原創(chuàng)
存儲 存儲軟件 開發(fā)工具 Redis
今天在容器環(huán)境發(fā)布服務(wù),我發(fā)誓我就加了一行日志,在點擊發(fā)布按鈕后,我悠閑地掏出泡著枸杞的保溫杯,準(zhǔn)備來一口老年人大保健......

【51CTO.com原創(chuàng)稿件】今天在容器環(huán)境發(fā)布服務(wù),我發(fā)誓我就加了一行日志,在點擊發(fā)布按鈕后,我悠閑地掏出泡著枸杞的保溫杯,準(zhǔn)備來一口老年人大保健......

[[340876]]

 

圖片來自 Pexels

正當(dāng)我一邊喝,一邊沉思今晚吃點啥的問題時,還沒等我想明白,報警系統(tǒng)把我的黃粱美夢震碎成一地雞毛。

我急忙去 Sentry 上查看上報錯誤日志,發(fā)現(xiàn)全都是:

  1. redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool 

我沒動過 Redis 啊......

[[340877]]

 

內(nèi)心激動的我無以言表,但是外表還是得表現(xiàn)鎮(zhèn)定,此時我必須的做出選擇:回滾or重啟。

我也不知道是從哪里來的蜜汁自信,我堅信這跟我沒關(guān)系,我不管,我就要重啟。

時間每一秒對于等待重啟過程中的我來說變得無比的慢,就像小時候犯了錯,在老師辦公室等待父母到來那種感覺。

重啟的過程中我繼續(xù)去看報錯日志,猛地發(fā)現(xiàn)一條:

 

什么鬼,誰打日志打成這樣?當(dāng)我點開準(zhǔn)備看看是哪位大俠打的日志的時候,我驚奇的發(fā)現(xiàn):

  1. *************************** 
  2. APPLICATION FAILED TO START 
  3. *************************** 
  4. ...... 
  5. ...... 

原來是服務(wù)沒起來。此刻我的內(nèi)心是凌亂的,無助的,彷徨不安的。服務(wù)沒起來,哪里來的 Redis 請求?

能解釋通的就是應(yīng)該是來自于定時任務(wù)刷新數(shù)據(jù)對 Redis 的請求。這里也說明另一個問題:雖然端口占用,但是服務(wù)其實還是發(fā)布起來了,不然不可能運行定時任務(wù)。

但是還有另一個問題,Redis 為什么報錯,且報錯的原因還是:

  1. java.lang.IllegalStateException: Pool not open 

Jedis 線程池未初始化。項目既然能去執(zhí)行定時任務(wù),為什么不去初始化 Redis 相關(guān)配置呢?想想都頭疼。這里可以給大家留個坑盡管猜。

我們今天的重點不是項目為啥沒起來,而是 Redis 那些年都報過哪些錯,讓你夜不能寐。以下錯誤都基于 Jedis 客戶端。

忘記添加白名單

之所以把這個放在第一位,是因為上線不規(guī)范,親人不能睡。

上線之前檢查所有的配置項,只要是測試環(huán)境做過的操作,一定要拿個小本本記下。

在現(xiàn)如今使用個啥啥都要授權(quán)的時代你咋能就忘了白名單這種東西呢!

[[340878]]

 

無法從連接池獲取到連接

如果連接池沒有可用 Jedis 連接,會等待 maxWaitMillis(毫秒),依然沒有獲取到可用 Jedis 連接,會拋出如下異常:

  1. redis.clients.jedis.exceptions.JedisException: Could not get a resource from the pool 
  2.     at redis.clients.util.Pool.getResource(Pool.java:51) 
  3.     at redis.clients.jedis.JedisPool.getResource(JedisPool.java:226) 
  4.     at com.yy.cs.base.redis.RedisClient.zrangeByScoreWithScores(RedisClient.java:2258) 
  5.   ...... 
  6. java.util.NoSuchElementException: Timeout waiting for idle object 
  7.     at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:448) 
  8.     at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:362) 
  9.     at redis.clients.util.Pool.getResource(Pool.java:49) 
  10.     at redis.clients.jedis.JedisPool.getResource(JedisPool.java:226) 
  11.   ...... 

其實出現(xiàn)這個問題,我們從兩個方面來探測一下原因:

  • 連接池配置有問題
  • 連接池沒問題,使用有問題

連接池配置

Jedis Pool 有如下參數(shù)可以配置:

 

①如何確定 maxTotal 呢?

最大連接數(shù)肯定不是越大越好,首先 Redis 服務(wù)端已經(jīng)配置了允許所有客戶端連接的最大連接數(shù),那么當(dāng)前連接 Redis 的所有節(jié)點的連接池加起來總數(shù)不能超過服務(wù)端的配置。

其次對于單個節(jié)點來說,需要考慮單機的 Redis QPS,假設(shè)同機房 Redis 90% 的操作耗時都在 1ms,那么 QPS 大約是 1000。

而業(yè)務(wù)系統(tǒng)期望 QPS 能達到 10000,那么理論上需要的連接數(shù)=10000/1000=10。

考慮到網(wǎng)絡(luò)抖動不可能每次操作都這么準(zhǔn)時,所以實際配置值應(yīng)該比當(dāng)前預(yù)估值大一些。

②maxIdle 和 minIdle 如何確定?

maxIdle 從默認值來看是等于 maxTotal。這么做的原因在于既然已經(jīng)分配了 maxTotal 個連接,如果 maxIdle

如果你的系統(tǒng)只是在高峰期才會達到 maxTotal 的量,那么你可以通過 minIdle 來控制低峰期最低有多少個連接的存活。

所以連接池參數(shù)的配置直接決定了你能否獲取連接以及獲取連接效率問題。

使用有問題

說到使用,真的就是仁者見仁智者也會犯錯,誰都不能保證他寫的代碼一次性考慮周全。

比如有這么一段代碼:

是不是沒有問題。再好好想想,這里從線程池中獲取了 Jedis 連接,用完了是不是要歸還?不然這個連接一直被某個人占用著,線程池慢慢連接數(shù)就被消耗完。

 

所以正確的寫法:

 

多個線程使用同一個 Jedis 連接

這種錯誤一般發(fā)生在新手身上會多一些。

 

這段代碼乍看是不是感覺良好,不過你跑起來了之后就知道有多痛苦:

  1. redis.clients.jedis.exceptions.JedisConnectionException: Unexpected end of stream. 
  2.     at redis.clients.util.RedisInputStream.ensureFill(RedisInputStream.java:199) 
  3.     at redis.clients.util.RedisInputStream.readByte(RedisInputStream.java:40) 
  4.     at redis.clients.jedis.Protocol.process(Protocol.java:151) 
  5. ...... 

這個報錯是不是讓你一頭霧水,不知所措。出現(xiàn)這種報錯是服務(wù)端無法分辨出一條完整的消息從哪里結(jié)束,正常情況下一個連接被一個線程使用,上面這種情況多個線程同時使用一個連接發(fā)送消息,那服務(wù)端可能就無法區(qū)分到底現(xiàn)在發(fā)送的消息是哪一條的。

類型轉(zhuǎn)換錯誤

這種錯誤雖然很低級,但是出現(xiàn)的幾率還不低。

  1. java.lang.ClassCastException: com.test.User cannot be cast to com.test.User 
  2.          at redis.clients.jedis.Connection.getBinaryMultiBulkReply(Connection.java:199) 
  3.          at redis.clients.jedis.Jedis.hgetAll(Jedis.java:851) 
  4.          at redis.clients.jedis.ShardedJedis.hgetAll(ShardedJedis.java:198) 

上面這個錯乍一看是不是很吃驚,為啥同一個類無法反序列化。因為開發(fā)這個功能的同學(xué)用了一個序列化框架 Kryo 先將 User 對象序列化后存儲到 Redis。

后來 User 對象增加了一個字段,而反序列化的 User 與新的 User 對象對不上導(dǎo)致無法反序列化。

客戶端讀寫超時

出現(xiàn)客戶端讀超時的原因很多,這種情況就要綜合來判斷。

  1. redis.clients.jedis.exceptions.JedisConnectionException: 
  2.     java.net.SocketTimeoutException: Read timed out 
  3.     ...... 

出現(xiàn)這種情況的原因我們可以綜合分析:

  • 首先檢查讀寫超時時間是否設(shè)置的過短,如果確定設(shè)置的很短,調(diào)大一點觀察一下效果。
  • 其次檢查出現(xiàn)超時的命名是否本身執(zhí)行較大的存儲或者拉數(shù)據(jù)任務(wù)。如果數(shù)據(jù)量過大,那么就要考慮做業(yè)務(wù)拆分。
  • 前面這兩項如果還不能確定,那么就要檢查一下網(wǎng)絡(luò)問題,確定當(dāng)前業(yè)務(wù)主機和 Redis 服務(wù)器主機是否在同機房,機房質(zhì)量怎么樣。
  • 機房質(zhì)量如果還是沒問題,那能做的就是檢查當(dāng)前業(yè)務(wù)中 Redis 讀寫是否發(fā)生有可能發(fā)生阻塞,是否業(yè)務(wù)量大到這種程度,是否需要擴容。

大 Key 造成的 CPU 飆升

我們有個新項目中 Redis 主要存儲教師端的講義數(shù)據(jù)(濃縮講義非全部), QPS 達到了15k,但是通過監(jiān)控查看命中率特別低,僅 15% 左右。這說明有很多講義是沒有被看的,Cache 這樣使用是對內(nèi)存的極大浪費。

項目在上線中期就頻繁出現(xiàn) Redis 所在機器 CPU 使用率頻頻報警,單看這么低的命中率也很難想象到底是什么導(dǎo)致 CPU 超。后面觀察到報警時刻的 response 數(shù)據(jù)基本都在 15k-30 k 左右。

觀察了 Redis 的錯誤日志,有一些頁交換錯誤的日志。聯(lián)系起來看可以得出結(jié)論:Redis 獲取大對象時該對象首先被序列化到通信緩沖區(qū)中,然后寫入客戶端套接字,這個序列化是有成本的,涉及到隨機 I/O 讀寫。

另外 Redis 官方也不建議使用 Redis 存儲大數(shù)據(jù),雖然官方建議值是一個 value 最大值不能超過 512M,試想真的存儲一個 512M 的數(shù)據(jù)到緩存和到關(guān)系型數(shù)據(jù)庫的區(qū)別應(yīng)該不大,但是成本就完全不一樣。

Too Many Cluster Redirections

這個錯誤信息一般在 cluster 環(huán)境中出現(xiàn),主要原因還是單機出現(xiàn)了命令堆積。

  1. redis.clients.jedis.exceptions.JedisClusterMaxRedirectionsException: Too many Cluster redirections? 
  2. at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:97) 
  3. at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:152) 
  4. at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:131) 
  5. at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:152) 
  6. at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:131) 
  7. at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:152) 
  8. at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:131) 
  9. at redis.clients.jedis.JedisClusterCommand.run(JedisClusterCommand.java:30) 
  10. at redis.clients.jedis.JedisCluster.get(JedisCluster.java:81) 

Redis 是單線程處理請求的,如果一條命令執(zhí)行的特別慢(可能是網(wǎng)絡(luò)阻塞,可能是獲取數(shù)據(jù)量大),那么新到來的請求就會放在 TCP 隊列中等待執(zhí)行。但是等待執(zhí)行的命令數(shù)如果超過了設(shè)置的隊列大小,后面的請求就會被丟棄。

出現(xiàn)上面這個錯誤的原因是:

  • 集群環(huán)境中 client 先通過key 計算 slot,然后查詢 slot 對應(yīng)到哪個服務(wù)器,假設(shè)這個 slot 對應(yīng)到 server1,那么就去請求 server1。
  • 此時如果 server1 整由于執(zhí)行慢命令而被阻塞且 TCP 隊列也已滿,那么新來的請求就會直接被拒絕。
  • client 以為是 server1不可用,隨即請求另一個服務(wù)器 server2。server2 檢查到該 slot 由 server1 負責(zé)且 server1 心跳檢查正常,所以告訴 client 你還是去找 server1 吧。
  • client 又來請求 server1,但是 server1 此時還是阻塞中,又回到 3。當(dāng)請求的次數(shù)超過拒絕服務(wù)次數(shù)之后,就會拋出異常。

再次說明,大命令要不得。對于這種錯誤,最首要的就是要優(yōu)化存儲結(jié)構(gòu)或者獲取數(shù)據(jù)方式。其次,增加 TCP 隊列長度。再次,擴容也是可以解決的。

集群擴容之后找不到 Key

現(xiàn)在有如下集群,6 臺主節(jié)點,6 臺從節(jié)點:

  • redis-master001~redis-master006
  • redis-slave001~redis-slave006

之前 Redis 集群的 16384 個槽均勻分配在 6 臺主節(jié)點中,每個節(jié)點 2730 個槽。

現(xiàn)在線上主節(jié)點數(shù)已經(jīng)出現(xiàn)到達容量閾值,需要增加 3 主 3 從。

為保證擴容后,槽依然均勻分布,需要將之前 6 臺的每臺機器上遷移出 910 個槽,方案如下:

 

分配完之后,每臺節(jié)點 1820 個 slot。遷移完數(shù)據(jù)之后,開始報如下異常:

  1.  Exception in thread "main" redis.clients.jedis.exceptions.JedisMovedDataException: MOVED 1539 34.55.8.12:6379 
  2. at redis.clients.jedis.Protocol.processError(Protocol.java:93) 
  3. at redis.clients.jedis.Protocol.process(Protocol.java:122) 
  4. at redis.clients.jedis.Protocol.read(Protocol.java:191) 
  5. at redis.clients.jedis.Connection.getOne(Connection.java:258) 
  6. at redis.clients.jedis.ShardedJedisPipeline.sync(ShardedJedisPipeline.java:44) 
  7. at org.hu.e63.MovieLens21MPipeline.push(MovieLens21MPipeline.java:47) 
  8. at org.hu.e63.MovieLens21MPipeline.main(MovieLens21MPipeline.java:53 

報這種錯誤肯定就是 slot 遷移之后找不到了。

我們看一下代碼:

之所以這種方式會出問題還是在于我們沒有明白 Redis Cluster 的工作原理。

 

Key 通過 Hash 被均勻的分配到 16384 個槽中,不同的機器被分配了不同的槽,那么我們使用的 API 是不是也要支持去計算當(dāng)前 Key 要被落地到哪個槽。

你可以去看看 Pipelined 的源碼它支持計算槽嗎。動腦子想想 Pipelined 這種批量操作也不太適合集群工作。

所以我們用錯了 API。如果在集群模式下要使用 JedisCluster API,示例代碼如下:

  1. JedisPoolConfig config = new JedisPoolConfig(); 
  2. //可用連接實例的最大數(shù)目,默認為8; 
  3. //如果賦值為-1,則表示不限制,如果pool已經(jīng)分配了maxActive個jedis實例,則此時pool的狀態(tài)為exhausted(耗盡) 
  4. private  Integer MAX_TOTAL = 1024; 
  5. //控制一個pool最多有多少個狀態(tài)為idle(空閑)的jedis實例,默認值是8 
  6. private  Integer MAX_IDLE = 200; 
  7. //等待可用連接的最大時間,單位是毫秒,默認值為-1,表示永不超時。 
  8. //如果超過等待時間,則直接拋出JedisConnectionException 
  9. private  Integer MAX_WAIT_MILLIS = 10000; 
  10. //在borrow(用)一個jedis實例時,是否提前進行validate(驗證)操作; 
  11. //如果為true,則得到的jedis實例均是可用的 
  12. private  Boolean TEST_ON_BORROW = true
  13. //在空閑時檢查有效性, 默認false 
  14. private  Boolean TEST_WHILE_IDLE = true
  15. //是否進行有效性檢查 
  16. private  Boolean TEST_ON_RETURN = true
  17. config.setMaxTotal(MAX_TOTAL); 
  18. config.setMaxIdle(MAX_IDLE); 
  19. config.setMaxWaitMillis(MAX_WAIT_MILLIS); 
  20. config.setTestOnBorrow(TEST_ON_BORROW); 
  21. config.setTestWhileIdle(TEST_WHILE_IDLE); 
  22. config.setTestOnReturn(TEST_ON_RETURN); 
  23. Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>(); 
  24. jedisClusterNode.add(new HostAndPort("192.168.0.31", 6380)); 
  25. jedisClusterNode.add(new HostAndPort("192.168.0.32", 6380)); 
  26. jedisClusterNode.add(new HostAndPort("192.168.0.33", 6380)); 
  27. jedisClusterNode.add(new HostAndPort("192.168.0.34", 6380)); 
  28. jedisClusterNode.add(new HostAndPort("192.168.0.35", 6380)); 
  29. JedisCluster jedis = new JedisCluster(jedisClusterNode, 1000, 1000, 5, config); 

以上介紹了看似平常實則在日常開發(fā)中只要一不注意就會發(fā)生的錯誤。出錯了先別慌,保留日志現(xiàn)場,如果一眼能看出問題就修復(fù),如果不能就趕緊回滾,不然再過一會就是一級事故你的年終獎估計就沒了。

Redis 正確使用小技巧

①正確設(shè)置過期時間

把這個放在第一位是因為這里實在是有太多坑。

如果你不設(shè)置過期時間,那么你的 Redis 就成了垃圾堆,假以時日你領(lǐng)導(dǎo)看到了告警,再看一下你的代碼,估計你可能就 “沒了”!

如果你設(shè)置了過期時間,但是又設(shè)置了特別長,比如兩個月,那么帶來的問題就是極有可能你的數(shù)據(jù)不一致問題會變得特別棘手。

[[340879]]

 

我就遇到過這種,用戶信息緩存中包含了除基本信息外的各種附加屬性,這些屬性又是隨時會變的,在有變化的時候通知緩存進行更新,但是這些附加信息是在各個微服務(wù)中,服務(wù)之間調(diào)用總會有失敗的時候,只要發(fā)生那就是緩存與數(shù)據(jù)不一致之日。

但是緩存又是 2 個月過期一次,遇到這種情況你能怎么辦,只能手動刪除緩存,重新去拉數(shù)據(jù)。

所以過期時間設(shè)置是很有技巧性的。

②批量操作使用 Pipeline 或者 Lua 腳本

使用 Pipeline 或 Lua 腳本可以在一次請求中發(fā)送多條命令,通過分攤一次請求的網(wǎng)絡(luò)及系統(tǒng)延遲,從而可以極大的提高性能。

③大對象盡量使用序列化或者先壓縮再存儲

如果存儲的值是對象類型,可以選擇使用序列化工具比如 protobuf,Kyro。對于比較大的文本存儲,如果真的有這種需求,可以考慮先壓縮再存儲,比如使用 snappy 或者 lzf 算法。

④Redis 服務(wù)器部署盡量與業(yè)務(wù)機器同機房

如果你的業(yè)務(wù)對延遲比較敏感,那么盡量申請與當(dāng)前業(yè)務(wù)機房同地區(qū)的 Redis 機器。同機房 Ping 值可能在 0.02ms,而跨機房能達到 20ms。當(dāng)然如果業(yè)務(wù)量小或者對延遲的要求沒有那么高這個問題可以忽略。

Redis 服務(wù)器內(nèi)存分配策略的選擇:

首先我們使用 info 命令來查看一下當(dāng)前內(nèi)存分配中都有哪些指標(biāo):

  1. info 
  2. $2962 
  3. # Memory 
  4. used_memory:325288168          
  5. used_memory_human:310.22M  #數(shù)據(jù)使用內(nèi)存 
  6. used_memory_rss:337371136 
  7. used_memory_rss_human:321.74M #總占用內(nèi)存 
  8. used_memory_peak:327635032 
  9. used_memory_peak_human:312.46M  #峰值內(nèi)存 
  10. used_memory_peak_perc:99.28% 
  11. used_memory_overhead:293842654 
  12. used_memory_startup:765712 
  13. used_memory_dataset:31445514 
  14. used_memory_dataset_perc:9.69% 
  15. total_system_memory:67551408128 
  16. total_system_memory_human:62.91G   # 操作系統(tǒng)內(nèi)存 
  17. used_memory_lua:43008 
  18. used_memory_lua_human:42.00K 
  19. maxmemory:2147483648 
  20. maxmemory_human:2.00G 
  21. maxmemory_policy:allkeys-lru    # 內(nèi)存超限時的釋放空間策略 
  22. mem_fragmentation_ratio:1.04    # 內(nèi)存碎片率(used_memory_rss / used_memory) 
  23. mem_allocator:jemalloc-4.0.3    # 內(nèi)存分配器 
  24. active_defrag_running:0 
  25. lazyfree_pending_objects:0 

上面我截取了 Memory 信息。根據(jù)參數(shù):mem_allocator 能看到當(dāng)前使用的內(nèi)存分配器是 jemalloc。

Redis 支持三種內(nèi)存分配器:tcmalloc,jemalloc 和 libc(ptmalloc)。

在存儲小數(shù)據(jù)的場景下,使用 jemalloc 與 tcmalloc 可以顯著的降低內(nèi)存的碎片率。

根據(jù)這里的評測:

  1. https://matt.sh/redis-quicklist 

保存 200 個列表,每個列表有 100 萬的數(shù)字,使用 jemalloc 的碎片率為 3%,共使用 12.1GB 內(nèi)存,而使用 libc 時,碎片率為 33%,使用了 17.7GB 內(nèi)存。

但是保存大對象時 libc 分配器要稍有優(yōu)勢,例如保存 3000 個列表,每個列表里保存 800 個大小為 2.5k 的條目,jemalloc 的碎片率為 3%,占用 8.4G,而 libc 為 1%,占用 8GB。

現(xiàn)在有一個問題:當(dāng)我們從 Redis 中刪除數(shù)據(jù)的時候,這一部分被釋放的內(nèi)存空間會立刻還給操作系統(tǒng)嗎?

比如有一個占用內(nèi)存空間(used_memory_rss)10G 的 Redis 實例,我們有一個大 Key 現(xiàn)在不使用需要刪除數(shù)據(jù),大約刪了 2G 的空間。那么理論上占用內(nèi)存空間應(yīng)該是 8G。

如果你使用 libc 內(nèi)存分配器的話,這時候的占用空間還是 10G。這是因為 malloc() 方法的實現(xiàn)機制問題,因為刪除掉的數(shù)據(jù)可能與其他正常數(shù)據(jù)在同一個內(nèi)存分頁中,因此這些分頁就無法被釋放掉。

當(dāng)然這些內(nèi)存并不會浪費掉,當(dāng)有新數(shù)據(jù)寫入的時候,Redis 會重用這部分空閑空間。

如果此時觀察 Redis 的內(nèi)存使用情況,就會發(fā)現(xiàn) used_memory_rss 基本保持不變,但是 used_memory 會不斷增長。

小結(jié)

今天給大家分享 Redis 使用過程中可能會遇到的問題,也是我們稍不留神就會遇到的坑。

很多問題在測試環(huán)境我們就能遇到并解決,也有一些問題是上了生產(chǎn)之后才發(fā)生的,需要你臨時判斷該怎么做。

總之別慌,你遇到的這些問題都是前人曾經(jīng)走過的路,只要仔細看日志都是有解決方案的。

作者:楊越

簡介:目前就職廣州歡聚時代,專注音視頻服務(wù)端技術(shù),對音視頻編解碼技術(shù)有深入研究。日常主要研究怎么造輪子和維護已經(jīng)造過的輪子,深耕直播類 APP 多年,對垂直直播玩法和應(yīng)用有廣泛的應(yīng)用經(jīng)驗,學(xué)習(xí)技術(shù)不局限于技術(shù),歡迎大家一起交流。

【51CTO原創(chuàng)稿件,合作站點轉(zhuǎn)載請注明原文作者和出處為51CTO.com】

 

責(zé)任編輯:武曉燕 來源: 51CTO技術(shù)棧
相關(guān)推薦

2020-10-15 07:24:52

Windows

2018-05-07 16:21:12

?,斕?/a>

2020-12-23 20:00:00

微信支付寶移動應(yīng)用

2020-08-19 13:17:28

2018-04-13 04:43:17

物聯(lián)網(wǎng)互聯(lián)網(wǎng)技術(shù)

2021-07-29 09:47:06

IDEA 項目maven

2013-02-22 11:01:52

路由器無線路由器飛魚星

2010-06-18 10:13:17

虛擬機消失

2020-07-03 15:10:35

Java Rust 開發(fā)

2013-03-14 13:49:31

Hotmail郵件服務(wù)器

2015-01-05 09:59:42

2020-02-24 11:02:37

斷網(wǎng)網(wǎng)絡(luò)故障

2021-04-06 06:23:18

MVCC并發(fā)事務(wù)

2018-03-28 09:02:50

智慧金融

2022-01-23 22:25:54

微信回家

2015-03-31 17:47:26

智慧購

2018-02-07 07:00:09

2018-03-28 12:33:21

滴滴高德地圖平臺

2022-02-23 22:01:23

SpringAOP模式

2022-02-21 08:41:50

Redis
點贊
收藏

51CTO技術(shù)棧公眾號