redis匯總筆記

語雀完整版:

https://www.yuque.com/g/mingrun/embiys/calwqx/collaborator/join?token=sLcLnqz5Rv8hOKEB&source=doc_collaborator# 《Redis筆記》

Redis

一般問題

  1. Redis內存模型(I/O多路模型)多路復用IO如何解釋
    • 為什么Redis要使用單線程?單線程為什么還如此之快?
      首先官方解釋說 redis是基于內存的操作,CPU不是redis的瓶頸,限制redis性能的應該是內存的大小和網絡寬帶。 另外 使用單線程能避免線程切換和競態消耗。
  1. 高級數據類型(注意bitmaps 在敏感詞過濾中的應用)
  1. 刪除策略
    • 定時刪除:創建一個定時器,時間一到立刻刪除,就是對cpu不太友好這樣
    • 惰性刪除:會在查詢的時候檢查是否過期如果過期則刪除。
    • 定期刪除:每隔一段時間檢查設置了過期時間Key,如果過期了則刪除(是上面兩種方案的折中)

上面的刪除機制有可能導致內存占滿,然后就要走redis的內存刪除機制,
另外還有以下情況會對過期鍵進行處理

    • 新生成RDB文件的時候 會檢查過期key,不會生成
    • 生成AOF的時候,會檢查過期key,如果過期了就會增加一個DEL指令,記錄一下、
    • 主庫過期會向從庫發送 DEL指令,記錄改鍵已經刪除
  1. Redis淘汰策略(也叫逐出算法,內存不夠時觸發,它和刪除策略 保證了redis中都是熱點數據)


    注:其中的lru是指淘汰最久未使用的,lfu是指淘汰使用次數最少的
  1. 緩存淘汰的三種策略
    • FIFO
      • 先進先出,可以定義一個雙向鏈表,如果添加數據時滿了,就從隊頭開始清理
    • LRU
      • 淘汰的是使用次數最少的,可以定義一個隊列,新來的放到隊尾,訪問一次就把它的引用計數+1 ,容量不夠的時候就從隊尾開始清理
    • LFU
      • 剛被訪問的數據放到隊頭,插入時容量不夠的話從隊尾開始淘汰
    • 上述算法自己如何實現?
  1. Key值命名規范

  1. Redis事務
    • 概述:redis事務就是 將多個命令包裝成一個整體,作為一個隊列,中間不會被打斷
    • 使用:開啟multi,結束exec
    • 注意點:中間執行失敗了,比如命令沒有敲對,是不會回滾的
  1. 生產問題
    • 緩存雪崩
      • 誘因:在一個較短的時間內,大量key過期失效,大量請求無法命中緩存
      • 解決:把過期時間設置的隨機一些
    • 緩存擊穿
      • 誘因:單個key過期了,然后大量請求到這個key上
      • 解決:
        • 過期時間設置長一些、二級緩存、把這個key對應的value先設置上一個值
        • 在getKey的時候,使用setnx加個分布式鎖,然后從數據庫里面把這個key的值讀出來,放到redis里面,然后再釋放鎖
    • 緩存穿透
      • 誘因:大量的請求沒有命中緩存,直接走數據庫了(遇到了攻擊)
      • 解決
        • 把這個key對應的value先設置上一個值,并設置上較短的過期時間
        • 布隆過濾器把所有可能存在的key放進去,如果請求過來key不存在就直接過濾掉(布隆過濾器由于哈希沖突,就是別的字段的值會把你的覆蓋掉,所以有不一定有,沒有的就一定沒有)
  1. Redis高可用
    • 主從模式:若master宕機需要手動配置slave轉為master,可以設置一主多從,主寫從讀,提高吞吐量
    • 哨兵模式,該模式下有一個哨兵監視master和slave,若master宕機可自動將slave轉為master,但是不能動態擴充;
    • cluster集群模式(3.x):對redis做水平擴展
  1. 數據分發到多個節點上需要用一定的算法來完成
    • 哈希取模:缺點是如果一個節點掛掉所有數據則需要重新計算,原有數據取不到而全部失效。
    • 哈希一致性哈希算法:就是一個數據環,然后服務器作為上面的節點,如果一個服務器掛了,就會順時針方向,走到下一個節點,這里的缺點也就是會造成熱點數據問題
    • 虛擬槽分區算法:

![image-20210601212630310](https://mrbucket-2.oss-cn-hangzhou.aliyuncs.com/typora/image-20210601212630310.png)

  1. 連接redis的java客戶端
    • jedis/jedisCluster
      • 全媒體用了jedisCluster,他使用條件注解開啟,以此來達到可配置化
@ConditionalOnProperty(name = {"spring.redis.config.cluster"}, havingValue = "true")

    • Spring提供的
    • redission(推薦)
  1. Redis底層數據結構
    • 列表(list)
      • 分兩種實現方式,壓縮列表和雙向循環列表
      • 壓縮列表
        • 壓縮指的是對內存的壓縮,要滿足以下兩個條件才會使用壓縮列表,否則就會使用雙向鏈表
          • 列表中保存的單個數據(有可能是字符串類型的)小于64字節:
          • 列表中數據個數少于512個。
        • 壓縮列表做的優化就是 因為數組的長度是固定的,字符串的長度不固定,放到這些數組里面就會造成浪費,所以就保存每個字符串的長度,去除空閑的空間

      • 雙向鏈表
    • 字典(hash)
      • 他也有兩種實現方式,壓縮列表和散列表
      • 壓縮列表:要使用壓縮列表需要滿足下面兩個條件
        • 字典中保存的鍵和值的大小都要小于64字節;
        • 字典中鍵值對的個數要小于512個。
      • 散列表:使用的MurmurHash2作為哈希函數,對于哈希沖突使用的是鏈表法來解決,對于動態因子,大于一時會觸發擴容兩倍,小于0.1時就會縮容
    • 集合(set)
      • 也有兩種實現,有序數組和散列表
      • 有序數組:要使用有序數組要滿足一下兩個條件
        • 存儲的數據都是整數;
        • 存儲的數據元素個數不超過512個。
      • 散列表
    • 有序集合(sortedset)
      • 也有兩種實現,壓縮列表和跳表
      • 壓縮列表:使用壓縮列表的條件如下:
        • 所有數據的大小都要小于64字節;
        • 元素個數要小于128個。
      • 跳表
  1. 數據持久化的兩種方式
    • 清楚原有的數據結構,直接將數據存儲到磁盤(redis采用的這個)
      • 優點未知(redis不經常重新加載數據從磁盤,就是隨機選一個方案)
        缺點是 比如對于散列表這種數據,恢復的時候就要重新計算散列值,如果數據量比較大就比較耗費時間
    • 保留原來的存儲格式
      • 可以解決上面的缺點

redis分布式鎖

單機實現

  1. 加鎖
    • 其中key設置本業務名稱,value設置成thradId,thradId的生成方式如下
//可以看出,這個就是在Thread中自增的,這樣干在集群的時候肯定不行
private static long threadSeqNumber;
private static synchronized long nextThreadID() {return ++threadSeqNumber;
}

    • 另外因為redis setnx和expire指令不是原子性的,所以采用如下方式進行設置,返回的結果是是否加鎖成功(非阻塞鎖),如果成功就繼續執行操作,如果失敗就設置循環獲取鎖,每次循環休眠一段時間
jedis.set(lockKey, Thread.currentThread().getId(), "nx", "ex", 100);

  1. 解鎖:要解決get 和del指令的原子性
// 解鎖的時候 get 指令和 del 指令不是原子性的,所以采用 LUA 腳本執行刪除 lockKey 的邏輯
// 解鎖的 LUA 腳本 lock.lua:if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end
public  boolean unLock(String lockKey, String threadId) {Jedis jedis = jedisPool.getResource();// 加載 LUA 腳本DefaultRedisScript<Number> script = new DefaultRedisScript<>();script.setScriptSource(new ResourceScriptSource(new ClassPathResource("lock.lua")));script.setResultType(Number.class);// 執行 LUA 腳本Object result = jedis.eval(script.getScriptAsString(), Collections.singletonList(lockKey), Collections.singletonList(threadId));if(UNLOCK_SUCCESS.equals(result)) {return true;}return false;
}

  1. 執行時間過長導致過期問題
    • 假如過期時間是30秒,A線程執行時間超過了30秒,導致鎖失效,B線程就進來了,解決這種情況就可以用守護線程為當前鎖續命
    • B線程進來后開始執行,這個時候如果A線程執行完畢了要刪除鎖,按照之前的寫法是直接刪除key,不校檢value,這就相當于在B還運行著的時候,A就直接把鎖給刪除了
  1. 集群鎖丟失問題
    • 假設加鎖加在了 master節點上,加完鎖master正好掛了,故障轉移之后slave變成了master,這個鎖就丟失了,這個問題可以用RedLock解決,而Redission就對RedLock做了一套實現,就是MultiLock,創建多個分組,每個分組可能是一個cluster、一個主從復制,然后加鎖和解鎖要在這上面大多數成功才行

redis集群版加鎖:Redisson

案例

  1. 代碼實現
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.8.1</version>
</dependency>

原理

  1. 找哪臺機器加鎖

    • 其中第一步就對應代碼RLock lock = redisson.getLock("anyLock");,主要就是通過RedissionLock類獲取鎖對象
    • 第二步是lock.lock();,底層先是對key獲取crc16值(不要跑,CRC沒這么難!(簡單易懂的CRC原理闡述) - SegmentFault 思否),讓后讓這個值對16384取模,然后就以此來鎖定一臺master
  1. 客戶端線程首次加鎖
    • 調用處 就是在上面的第二步流程中,具體實現為LUA腳本
      其中 KEYS[1]為上面設置的key值 "anyLock",
      ARGV[1]的值為internalLockLeaseTime=30 * 1000ms ,這個時間也是LockWatchdogTimeout
      ARGV[2]的值為ThreadId

    • 上面前三行LUA腳本解釋
      • 先判斷這個key存在不存在
      • 存在的話就設置值,相當于命令 hset anyLock UUID:ThreadId 1
      • 設置過期時間,pexpire anyLock 30000
    • 流程進度

  1. 加鎖成功后如何維持加鎖
    • 獲取鎖成功后會走下面的步驟

    • 接下來就會添加一個定時器,定時時間為 internalLockLeaseTime/3,也就是10秒鐘就去執行一次,執行的是下面這一段腳本


      主要就是判斷線程是否還持有該鎖,如果還持有就為該key續期30s,這樣就保證了只要這個key還在 就一直維持下去,這就是看門狗機制,其中的key值得是 'hexists', KEYS[1],ARGV[2]) == 1;
  1. 可重入鎖的加鎖機制
    • 依然是上面的LUA腳本,第二次加鎖會進入到第二個If分支,他判當前傳進來的key和線程id是否存在,存在的話就 加一(相當于 增加相同線程的持有次數,可重入鎖),加鎖成功后也會開啟一個watchDog線程
    • 當前的流程如下

  1. 其它線程重復加鎖阻塞
    • 其它線程過來時 會執行LUA腳本的最后一行,pttl anyLock,返回當前key的過期剩余時間 ttl
    • 然后在循環中,他就會等待ttl這么久的時間,然后再去獲取鎖
  1. 可重入鎖釋放場景
    • 客戶端宕機釋放
    • 客戶端調用 unlock方法主動釋放,底層執行的腳本如下,其中KEYS[1]=anyLock,
      ARGV[2]=30000,ARGV[3]=UUID:ThreadId

      • 其中直接可以看第8行,對重入鎖的次數減一,然后在判斷是否大于一,如果大于一就說明還不能解鎖,而且還會順便把過期時間 蓄滿,小于一就直接把key刪掉釋放鎖

  1. 嘗試獲取鎖超時
    • 上面都是對 lock.lock()方法的分析,他如果沒獲得鎖就會一直阻塞在那,不斷嘗試,而對于lock.tryLock(30, 10, TimeUnit.MILLISECONDS);則可以設置阻塞時間
    • 每個階段都會扣減時間,直到傳進來的 time扣到0以內,然后就可以返回加鎖失敗了
  1. 超時自動釋放鎖
    • 使用 lock.tryLock ?底層不會維持看門狗機制,直接到點就自動釋放鎖了

面試題

  1. 客戶端線程在底層是如何實現加鎖的?
    • 先定位master節點
      通過key計算出CRC16值,再CRC16值對16384取模得hash slot,通過這個hash slot定位rediscluster集群中的master節點
    • 加鎖
      加鎖邏輯底層是通過lua腳本來實現的,如果客戶端線程第?次去加鎖的話,會在key對應的hash
      數據結構中添加線程標識UUID:ThreadId 1,指定該線程當前對這個key加鎖?次了。
  1. 客戶端線程是如何維持加鎖的?
    當加鎖成功后,此時會對加鎖的結果設置?個監聽器,如果監聽到加鎖成功了,也就是返回的結果為空,此時就會在后臺通過watchdog看?狗機制、啟動?個后臺定時任務,每隔10s執??次,檢查如果key當前依然存在,就重置key的存活時間為30s。維持加鎖底層就是通過后臺這樣的?個線程定時刷新存活時間維持的。
  1. 相同客戶端線程是如何實現可重?加鎖的?
    第?次加鎖時,會往key對應的hash數據結構中設置 UUID:ThreadId 1,表示當前線程對key加鎖?次;
    如果相同線程來再次對這個key加鎖,只需要將UUID:ThreadId持有鎖的次數加1即可,就為:
    UUID:ThreadId 2 了,Redisson底層就是通過這樣的數據結構來表示重?加鎖的語義的。
  1. 其他線程加鎖失敗時,底層是如何實現阻塞的?
    線程加鎖失敗了,如果沒有設置獲取鎖超時時間,此時就會進??個while的死循環中,?直嘗試加
    鎖,直到加鎖成功才會返回。
  1. 客戶端宕機了,鎖是如何釋放的?
    客戶端宕機了,相應的watchdog后臺定時任務當然也就沒了,此時就?法對key進?定時續期,那
    么當指定存活時間過后,key就會?動失效,鎖當然也就?動釋放了。
  1. 客戶端如何主動釋放持有的鎖?
    客戶端主動釋放鎖,底層同樣也是通過執?lua腳本的?式實現的,如果判斷當前釋放鎖的key存在,并且在key的hash數據結構中、存在當前線程的加鎖信息,那么此時就會扣減當前線程對這個key的重?鎖次數。
    扣減線程的重?鎖次數之后,如果當前線程在這個key中的重?鎖次數為0,此時就會直接釋放鎖,如果當前線程在這個key中的重?鎖次數依然還?于0,此時就直接重置?下key的存活時間為30s。
  1. 客戶端嘗試獲取鎖超時的機制在底層是如何實現的?
    如果在加鎖時就指定了嘗試獲取鎖超時的時間,如果獲取鎖失敗,此時就不會??境的在while死循環中?直獲取鎖,?是根據你指定的獲取鎖超時時間,在這段時間范圍內,要是獲取不到鎖,就會標記為獲取鎖失敗,然后直接返回false。
  1. 客戶端鎖超時?動釋放機制在底層?是如何實現的?
    如果在加鎖時,指定了鎖超時時間,那么就算你獲取鎖成功了,也不會開啟watchdog的定時任務了,此時直接就將當前持有這把鎖的過期時間、設置為你指定的超時時間,那么當你指定的時間到了之后,key失效被刪除了,key對應的鎖相應也就?動釋放了。

面試題

  1. Redis為什么是單線程,單線程是如何處理并發請求的
    • Redis的性能瓶頸就是內存 和網絡帶寬,所以順利成章就單線程了(這里的單線程指處理網絡請求的時候,其它模塊還是多線程的)
    • 單線程是如何處理的
      • 如果使用阻塞 I/O的話,從讀數據到處理數據 都是阻塞的,這期間不能處理其它讀寫請求
      • 所以redis使用的是I/O多路復用,可以解決一個線程處理多個連接的問題(使用 select、poll、epoll函數庫)
      • 使用 Reactor多路復用線程模型,就是redis有一個I/O多路復用模塊,用來監聽事件的發生,有如下兩種,如果多路復用器監聽到了一個 文件事件的話就會交給文件事件分發器,文件事件分發器再交給具體的 處理器
文件事件:Redis 客戶端通過 socket 與 Redis 服務器連接,例如 get 命令請求就是一個文件事件;
時間事件:Redis 服務器周期或者定期執行的事件,例如定期的 RDB 持久化命令就是一個時間事件。

  1. 如何保證redis和數據庫的一致性
    • 方案一:先更新數據庫在更新刪除緩存
      • 為什么要刪除緩存而不是更新?
        如果更新的頻率大于讀的頻率,那就直接刪除掉,讀的時候再更新進緩存,效率更高
      • 刪除放到 更新緩存前
        在刪除的過程中,會有其它請求讀數據庫,發現命中不了又返回緩存
      • 有什么缺點
        服務器需要同時連接 Redis 和 database,需要大量的連接資源導致連接數過多。
    • 方案二:更新數據庫同時消息隊列異步更新 Redis
      • 就是使用隊列,讓更新數據庫和更新緩存解耦
      • 缺點
        消息亂序可能會導致更新錯誤,而且又加了mq
    • 方案三:訂閱BinLog更新redis
      • 從bingLog解析出更新操作,然后在更新緩存,適合db壓力小的場景
  1. Sort set 的數據結構
    • 它是用跳表實現的,對于插、刪、查這幾個操作 他和紅黑樹的時間復雜度是一樣的, 就是根據范圍查,比如[20,30],它可以從底層鏈表 只需要找到第一個值 就可以順著差了,效率較高

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

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

相關文章

STM32用PWM驅動步進電機

硬件介紹&#xff1a;連線&#xff1a;注意這里stp連的是pwm脈沖&#xff0c;dir連的是方向到時候代碼pwm波形就是從這里來的&#xff0c;具體接線根據你的代碼來注意要點&#xff1a;步進電機和舵機驅動是不一樣的&#xff0c;它是根據步長來移動的&#xff0c;所以要開一個中…

力扣25.7.10每日一題——重新安排會議得到最多空余時間 II

Description 今天這道題和昨天類似&#xff0c;只是允許順序變化。 Solution 把會議區間視作桌子&#xff0c;空余時間視作空位&#xff0c;我們要把一個桌子移到別的空位中。 初步想法是枚舉桌子&#xff0c;找一個長度大于等于桌子長度的空位移過去。看上去&#xff0c;找…

IP報文分片與重組原理及實現分析

IP報文分片與重組原理及實現分析 引用&#xff1a; ppp/net/packet/IPFragment.hppp/net/packet/IPFragment.cpp 1. IP分片原理 當IP數據包大小超過MTU&#xff08;最大傳輸單元&#xff09;時&#xff0c;路由器/主機將其分割為多個片段傳輸&#xff0c;每個片段包含&…

[python]在drf中使用drf_spectacular

安裝drf_spectacular 文檔 pypi鏈接:https://pypi.org/project/drf-spectacular/ 文檔鏈接:https://drf-spectacular.readthedocs.io/en/latest/readme.html 安裝步驟 在環境中添加 pip install drf-spectacular在setting的INSTALLED_APPS中添加 INSTALLED_APPS [# ALL…

【Datawhale AI 夏令營】 用AI做帶貨視頻評論分析(二)

5.預訓練模型跑分 回顧賽題 回顧賽題任務 挑戰與難點&#xff1a; 標注數據少 ——> 半監督學習 or 數據增強 聚類分析噪點影響嚴重 回顧Baseline 問題&#xff1a; TF-IDF無法捕捉以下語義。聚類分析粗糙&#xff0c;未評估聚類質量。 提升方案&#xff1a; 分類任務…

SPSSPRO:數據分析市場SaaS挑戰者的戰略分析

目錄 第一部分&#xff1a;執行摘要 第二部分&#xff1a;平臺解構&#xff1a;產品、架構與用戶體驗 2.1 SaaS范式轉移&#xff1a;架構與起源 2.2 功能能力&#xff1a;分析師的工具箱 2.3 “智能分析”的價值主張 第三部分&#xff1a;市場滲透與受眾細分 3.1 目標用戶…

低版本hive(1.2.1)UDF實現清除歷史分區數據

目標&#xff1a;通過UDF實現對表歷史數據清除 入參&#xff1a;表名、保留天數N 一、pom文件 <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.…

C++中頂層const與底層const

在C中&#xff0c;const關鍵字用于定義常量&#xff0c;但它在指針和引用上下文中會產生兩種不同的常量性&#xff1a;頂層const&#xff08;top-level const&#xff09;和底層const&#xff08;low-level const&#xff09;。理解它們的區別是避免編譯錯誤和提高代碼質量的關…

“SRP模型+”多技術融合在生態環境脆弱性評價模型構建、時空格局演變分析與RSEI指數生態質量評價

集成云端、桌面端等環境&#xff0c;結合遙感云計算、GIS空間分析&#xff0c;R語言統計分析的優勢&#xff0c;以分析生態環境脆弱性的時空演變為主線。通過本課程的學習&#xff0c;您將掌握&#xff1a;第一&#xff0c;收集各類指標數據&#xff0c;構建的“生態壓力度-生態…

算法學習筆記:17.蒙特卡洛算法 ——從原理到實戰,涵蓋 LeetCode 與考研 408 例題

在計算機科學和數學領域&#xff0c;蒙特卡洛算法&#xff08;Monte Carlo Algorithm&#xff09;以其獨特的隨機抽樣思想&#xff0c;成為解決復雜問題的有力工具。從圓周率的計算到金融風險評估&#xff0c;從物理模擬到人工智能&#xff0c;蒙特卡洛算法都發揮著不可替代的作…

Tortoise 設置

如何關閉 Windows 下 TortoiseGit 任務欄里窗口標題的分支顯示 一、引言 TortoiseGit 是一個專為團隊協作設計的 Git 圖形化客戶端&#xff0c;旨在解決版本控制中常見的問題&#xff0c;如沖突、回滾、歷史查看等。本文檔是 TortoiseGit 的使用手冊前言部分&#xff0c;旨在向…

[論文閱讀] 人工智能 + 軟件工程 | AI助力軟件可解釋性:從用戶評論到自動生成需求與解釋

AI助力軟件可解釋性&#xff1a;從用戶評論到自動生成需求與解釋 Automatic Generation of Explainability Requirements and Software Explanations From User ReviewsarXiv:2507.07344 Automatic Generation of Explainability Requirements and Software Explanations From …

C語言---自定義類型(上)(結構體類型)

結構體結構體的定義與聲明結構體其實和數組一樣&#xff0c;都是一些值的集合&#xff0c;只不過數組是一系類相同類型的值&#xff0c;而結構體里邊的成員可以是不同的數據類型。關于它的聲明&#xff0c;所用到的關鍵字是struct。聲明的語法如下&#xff1a;struct 結構體名{…

Java觀察者模式實現方式與測試方法

一、實現方式 自定義實現 通過手動定義Subject和Observer接口&#xff0c;實現一對多依賴關系&#xff1a; // 觀察者接口 public interface Observer {void update(float temp, float humidity, float pressure); } // 主題接口 public interface Subject {void registerObser…

leetGPU解題筆記(1)

1.題面 題目要求 向量加法 實現一個程序&#xff0c;在GPU上對兩個包含32位浮點數的向量執行逐元素加法。該程序應接受兩個長度相等的輸入向量&#xff0c;并生成一個包含它們和的輸出向量。 實現要求 禁止使用外部庫 solve函數簽名必須保持不變 最終結果必須存儲在向量C中 示例…

5. JVM 的方法區

1. JVM介紹和運行流程-CSDN博客 2. 什么是程序計數器-CSDN博客 3. java 堆和 JVM 內存結構-CSDN博客 4. 虛擬機棧-CSDN博客 5. JVM 的方法區-CSDN博客 6. JVM直接內存-CSDN博客 7. JVM類加載器與雙親委派模型-CSDN博客 8. JVM類裝載的執行過程-CSDN博客 9. JVM垃圾回收…

網絡安全的基本練習

一.docker搭建 1.安裝dockerapt-get install docker.io docker-compose2.編寫配置文件&#xff08;注意路徑正確&#xff09;vim /etc/systemd/system/docker.service.d/http-proxy.conf[Service] Environment"HTTP_PROXYhttp://科學上網訪問的ip:端口" Environment&…

380. O(1) 時間插入、刪除和獲取隨機元素

實現RandomizedSet 類&#xff1a; RandomizedSet() 初始化 RandomizedSet 對象 bool insert(int val) 當元素 val 不存在時&#xff0c;向集合中插入該項&#xff0c;并返回 true &#xff1b;否則&#xff0c;返回 false 。 bool remove(int val) 當元素 val 存在時&#xff…

【LeetCode Hot100 | 每日刷題】字母異位詞分組

題目鏈接&#xff1a;49. 字母異位詞分組 - 力扣&#xff08;LeetCode&#xff09; 題目&#xff1a; 給你一個字符串數組&#xff0c;請你將 字母異位詞 組合在一起。可以按任意順序返回結果列表。 示例 1: 輸入: strs ["eat", "tea", "tan"…

docker 安裝windows

目錄 下載地址&#xff1a; 使用教程&#xff1a; docker compose 查看版本 測試啟動 hello-world 報錯1 The system cannot find the file specified&#xff1a; 檢查 Docker Desktop 是否運行中 報錯2HF_ENDPOINT 1. 臨時解決方案&#xff08;當前終端會話有效&…