日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java中高级核心知识全面解析(3),美团Java面试算法题

發布時間:2023/12/14 java 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java中高级核心知识全面解析(3),美团Java面试算法题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
  • 主服務器?需要將自己生成的 RDB 文件 發送給從服務器,這個發送操作會?消耗?主服務器?大量的網絡資源 (帶寬和流量),并對主服務器響應命令請求的時間產生影響;
  • 接收到 RDB 文件的?從服務器?需要載入主服務器發來的 RBD 文件,并且在載入期間,從服務器會因為阻塞而沒辦法處理命令請求
  • 特別是當出現?斷線重復制?的情況是時,為了讓從服務器補足斷線時確實的那一小部分數據,卻要執行一次如此耗資源的?SYNC?命令,顯然是不合理的。

    ③、PSYNC 命令的引入

    所以在?Redis 2.8?中引入了?PSYNC?命令來代替?SYNC?,它具有兩種模式:

  • 全量復制: 用于初次復制或其他無法進行部分復制的情況,將主節點中的所有數據都發送給從節點,是一個非常重型的操作;
  • 部分復制: 用于網絡中斷等情況后的復制,只將?中斷期間主節點執行的寫命令?發送給從節點,與全量復制相比更加高效。需要注意?的是,如果網絡中斷時間過長,導致主節點沒有能夠完整地保存中斷期間執行的寫命令,則無法進行部分復制,仍使用全量復制;
  • 部分復制的原理主要是靠主從節點分別維護一個?復制偏移量,有了這個偏移量之后斷線重連之后一比較,之后就可以僅僅把從服務器斷線之后確實的這部分數據給補回來了。

    3.Redis Sentinel 哨兵

    上圖展示了一個典型的哨兵架構圖,它由兩部分組成,哨兵節點和數據節點:

    • 哨兵節點: 哨兵系統由一個或多個哨兵節點組成,哨兵節點是特殊的 Redis 節點,不存儲數據;
    • 數據節點: 主節點和從節點都是數據節點;

    在復制的基礎上,哨兵實現了 自動化的故障恢復 功能,下方是官方對于哨兵功能的描述:

    • 監控(Monitoring): 哨兵會不斷地檢查主節點和從節點是否運作正常。
    • 自動故障轉移(Automatic failover): 當?主節點?不能正常工作時,哨兵會開始?自動故障轉移操作,它會將失效主節點的其中一個?從節點升級為新的主節點,并讓其他從節點改為復制新的主節點。
    • 配置提供者(Configuration provider): 客戶端在初始化時,通過連接哨兵來獲得當前 Redis服務的主節點地址。
    • 通知(Notification): 哨兵可以將故障轉移的結果發送給客戶端。

    其中,監控和自動故障轉移功能,使得哨兵可以及時發現主節點故障并完成轉移。而配置提供者和通知功能,則需要在與客戶端的交互中才能體現。

    1)快速體驗

    ①、第一步:創建主從節點配置文件并啟動

    正確安裝好 Redis 之后,我們去到 Redis 的安裝目錄 (mac 默認在?/usr/local/?),找到?redis.conf文件復制三份分別命名為?redis-master.conf / redis-slave1.conf / redis-slave2.conf?,分別作為1?個主節點和2?個從節點的配置文件 (下圖演示了我本機的?redis.conf?文件的位置)

    打開可以看到這個?.conf?后綴的文件里面有很多說明的內容,全部刪除然后分別改成下面的樣子:

    #redis-master.conf port 6379 daemonize yes logfile "6379.log" dbfilename "dump-6379.rdb" #redis-slave1.conf port 6380 daemonize yes logfile "6380.log" dbfilename "dump-6380.rdb" slaveof 127.0.0.1 6379 #redis-slave2.conf port 6381 daemonize yes logfile "6381.log" dbfilename "dump-6381.rdb" slaveof 127.0.0.1 6379

    然后我們可以執行?redis-server <config file path>?來根據配置文件啟動不同的 Redis 實例,依次啟動主從節點:

    redis-server /usr/local/redis-5.0.3/redis-master.conf redis-server /usr/local/redis-5.0.3/redis-slave1.conf redis-server /usr/local/redis-5.0.3/redis-slave2.conf

    節點啟動后,我們執行?redis-cli?默認連接到我們端口為?6379?的主節點執行?info Replication?檢查一下主從狀態是否正常:(可以看到下方正確地顯示了兩個從節點)

    ②、第二步:創建哨兵節點配置文件并啟動

    按照上面同樣的方法,我們給哨兵節點也創建三個配置文件。(哨兵節點本質上是特殊的 Redis 節點,所以配置幾乎沒什么差別,只是在端口上做區分就好)

    # redis-sentinel-1.conf port 26379 daemonize yes logfile "26379.log" sentinel monitor mymaster 127.0.0.1 6379 2 # redis-sentinel-2.conf port 26380 daemonize yes logfile "26380.log" sentinel monitor mymaster 127.0.0.1 6379 2 # redis-sentinel-3.conf port 26381 daemonize yes logfile "26381.log" sentinel monitor mymaster 127.0.0.1 6379 2

    其中,?sentinel monitor mymaster 127.0.0.1 6379 2?配置的含義是:該哨兵節點監控?127.0.0.1:6379?這個主節點,該主節點的名稱是?mymaster?,最后的?2?的含義與主節點的故障判定有關:至少需要?2?個哨兵節點同意,才能判定主節點故障并進行故障轉移。

    執行下方命令將哨兵節點啟動起來:

    redis-server /usr/local/redis-5.0.3/redis-sentinel-1.conf --sentinel redis-server /usr/local/redis-5.0.3/redis-sentinel-2.conf --sentinel redis-server /usr/local/redis-5.0.3/redis-sentinel-3.conf --sentinel

    使用?redis-cil?工具連接哨兵節點,并執行?info Sentinel?命令來查看是否已經在監視主節點了:

    # 連接端口為 26379 的 Redis 節點 ? ~ redis-cli -p 26379 127.0.0.1:26379> info Sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3

    此時你打開剛才寫好的哨兵配置文件,你還會發現出現了一些變化:

    ③、第三步:演示故障轉移

    首先,我們使用?kill -9?命令來殺掉主節點,同時?在哨兵節點中執行?info Sentinel?命令來觀察故障節點的過程:

    ? ~ ps aux | grep 6379 longtao 74529 0.3 0.0 4346936 2132 ?? Ss 10:30上午 0:03.09 redis-server *:26379 [sentinel] longtao 73541 0.2 0.0 4348072 2292 ?? Ss 10:18上午 0:04.79 redis-server *:6379 longtao 75521 0.0 0.0 4286728 728 s008 S+ 10:39上午 0:00.00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git -- exclude-dir=.hg --exclude-dir=.svn 6379 longtao 74836 0.0 0.0 4289844 944 s006 S+ 10:32上午 0:00.01 redis-cli -p 26379 ? ~ kill -9 73541

    如果?剛殺掉瞬間?在哨兵節點中執行?info?命令來查看,會發現主節點還沒有切換過來,因為哨兵發現主節點故障并轉移需要一段時間:

    # 第一時間查看哨兵節點發現并未轉移,還在 6379 端口 127.0.0.1:26379> info Sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3

    一段時間之后你再執行?info?命令,查看,你就會發現主節點已經切換成了?6381?端口的從節點:

    # 過一段時間之后在執行,發現已經切換了 6381 端口 127.0.0.1:26379> info Sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=127.0.0.1:6381,slaves=2,sentinels=3

    但同時還可以發現,哨兵節點認為新的主節點仍然有兩個從節點 (上方 slaves=2),這是因為哨兵在將?6381?切換成主節點的同時,將?6379?節點置為其從節點。雖然?6379?從節點已經掛掉,但是由于?哨兵并不會對從節點進行客觀下線,因此認為該從節點一直存在。當?6379?節點重新啟動后,會自動變成6381?節點的從節點。

    另外,在故障轉移的階段,哨兵和主從節點的配置文件都會被改寫:

    • 對于主從節點: 主要是?slaveof?配置的變化,新的主節點沒有了?slaveof?配置,其從節點則slaveof?新的主節點。
    • 對于哨兵節點: 除了主從節點信息的變化,紀元(epoch) (記錄當前集群狀態的參數) 也會變化,紀元相關的參數都 +1 了。

    2)客戶端訪問哨兵系統代碼演示

    上面我們在?快速體驗?中主要感受到了服務端自己對于當前主從節點的自動化治理,下面我們以 Java 代碼為例,來演示一下客戶端如何訪問我們的哨兵系統:

    public static void testSentinel() throws Exception { String masterName = "mymaster"; Set<String> sentinels = new HashSet<>(); sentinels.add("127.0.0.1:26379"); sentinels.add("127.0.0.1:26380"); sentinels.add("127.0.0.1:26381"); // 初始化過程做了很多工作 JedisSentinelPool pool = new JedisSentinelPool(masterName, sentinels); Jedis jedis = pool.getResource(); jedis.set("key1", "value1"); pool.close(); }

    ①、客戶端原理

    Jedis 客戶端對哨兵提供了很好的支持。如上述代碼所示,我們只需要向 Jedis 提供哨兵節點集合和?masterName?,構造?JedisSentinelPool?對象,然后便可以像使用普通 Redis 連接池一樣來使用了:通過?pool.getResource()?獲取連接,執行具體的命令。

    在整個過程中,我們的代碼不需要顯式的指定主節點的地址,就可以連接到主節點;代碼中對故障轉移沒有任何體現,就可以在哨兵完成故障轉移后自動的切換主節點。之所以可以做到這一點,是因為在?JedisSentinelPool?的構造器中,進行了相關的工作;主要包括以下兩點:

  • 遍歷哨兵節點,獲取主節點信息: 遍歷哨兵節點,通過其中一個哨兵節點 +?masterName?獲得主節點的信息;該功能是通過調用哨兵節點的?sentinel get-master-addr-by-name?命令實現;
  • 增加對哨兵的監聽: 這樣當發生故障轉移時,客戶端便可以收到哨兵的通知,從而完成主節點的切換。具體做法是:利用 Redis 提供的?發布訂閱 功能,為每一個哨兵節點開啟一個單獨的線程,訂閱哨兵節點的 + switch-master 頻道,當收到消息時,重新初始化連接池。
  • 3)新的主服務器是怎樣被挑選出來的?

    故障轉移操作的第一步?要做的就是在已下線主服務器屬下的所有從服務器中,挑選出一個狀態良好、數據完整的從服務器,然后向這個從服務器發送?slaveof no one?命令,將這個從服務器轉換為主服務器。但是這個從服務器是怎么樣被挑選出來的呢?

    簡單來說 Sentinel 使用以下規則來選擇新的主服務器:

  • 在失效主服務器屬下的從服務器當中, 那些被標記為主觀下線、已斷線、或者最后一次回復 PING 命令的時間大于五秒鐘的從服務器都會被?淘汰
  • 在失效主服務器屬下的從服務器當中, 那些與失效主服務器連接斷開的時長超過 down-after 選項指定的時長十倍的從服務器都會被?淘汰
  • 在?經歷了以上兩輪淘汰之后?剩下來的從服務器中, 我們選出?復制偏移量(replication offset)最大?的那個?從服務器?作為新的主服務器;如果復制偏移量不可用,或者從服務器的復制偏移量相同,那么?帶有最小運行 ID?的那個從服務器成為新的主服務器。
  • 4.Redis 集群

    上圖 展示了?Redis Cluster?典型的架構圖,集群中的每一個 Redis 節點都?互相兩兩相連,客戶端任意直連?到集群中的?任意一臺,就可以對其他 Redis 節點進行?讀寫?的操作。

    1)基本原理

    Redis 集群中內置了?16384?個哈希槽。當客戶端連接到 Redis 集群之后,會同時得到一份關于這個?集群的配置信息,當客戶端具體對某一個?key?值進行操作時,會計算出它的一個 Hash 值,然后把結果對?16384?求余數,這樣每個key?都會對應一個編號在?0-16383?之間的哈希槽,Redis 會根據節點數量?大致均等?的將哈希槽映射到不同的節點。

    再結合集群的配置信息就能夠知道這個?key?值應該存儲在哪一個具體的 Redis 節點中,如果不屬于自己管,那么就會使用一個特殊的?MOVED?命令來進行一個跳轉,告訴客戶端去連接這個節點以獲取數據:

    GET x -MOVED 3999 127.0.0.1:6381

    MOVED?指令第一個參數?3999?是?key?對應的槽位編號,后面是目標節點地址,?MOVED?命令前面有一個減號,表示這是一個錯誤的消息。客戶端在收到?MOVED?指令后,就立即糾正本地的?槽位映射表,那么下一次再訪問?key?時就能夠到正確的地方去獲取了。

    2)集群的主要作用

  • 數據分區: 數據分區 (或稱數據分片) 是集群最核心的功能。集群將數據分散到多個節點,一方面突破了 Redis 單機內存大小的限制,存儲容量大大增加另一方面?每個主節點都可以對外提供讀服務和寫服務,大大提高了集群的響應能力。Redis 單機內存大小受限問題,在介紹持久化和主從復制時都有提及,例如,如果單機內存太大,?bgsave?和?bgrewriteaof?的?fork?操作可能導致主進程阻塞,主從環境下主機切換時可能導致從節點長時間無法提供服務,全量復制階段主節點的復制緩沖區可能溢出……
  • 高可用: 集群支持主從復制和主節點的?自動故障轉移?(與哨兵類似),當任一節點發生故障時,集群仍然可以對外提供服務。
  • 3)快速體驗

    ①、第一步:創建集群節點配置文件

    首先我們找一個地方創建一個名為?redis-cluster?的目錄:

    mkdir -p ~/Desktop/redis-cluster

    然后按照上面的方法,創建六個配置文件,分別命名為:redis_7000.conf?/?redis_7001.conf?…?redis_7005.conf,然后根據不同的端口號修改對應的端口值就好了:

    # 后臺執行 daemonize yes # 端口號 port 7000 # 為每一個集群節點指定一個 pid_file pidfile ~/Desktop/redis-cluster/redis_7000.pid # 啟動集群模式 cluster-enabled yes # 每一個集群節點都有一個配置文件,這個文件是不能手動編輯的。確保每一個集群節點的配置文件不通 cluster-config-file nodes-7000.conf # 集群節點的超時時間,單位:ms,超時后集群會認為該節點失敗 cluster-node-timeout 5000 # 最后將 appendonly 改成 yes(AOF 持久化) appendonly yes

    記得把對應上述配置文件中根端口對應的配置都修改掉 (port/ pidfile/ cluster-config-file)。

    ②、第二步:分別啟動 6 個 Redis 實例

    redis-server ~/Desktop/redis-cluster/redis_7000.conf redis-server ~/Desktop/redis-cluster/redis_7001.conf redis-server ~/Desktop/redis-cluster/redis_7002.conf redis-server ~/Desktop/redis-cluster/redis_7003.conf redis-server ~/Desktop/redis-cluster/redis_7004.conf redis-server ~/Desktop/redis-cluster/redis_7005.conf

    然后執行?ps -ef | grep redis?查看是否啟動成功:

    可以看到?6?個 Redis 節點都以集群的方式成功啟動了,但是現在每個節點還處于獨立的狀態,也就是說它們每一個都各自成了一個集群,還沒有互相聯系起來,我們需要手動地把他們之間建立起聯系。

    ③、第三步:建立集群

    執行下列命令:

    redis-cli --cluster create --cluster-replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
    • 這里稍微解釋一下這個?--replicas 1?的意思是:我們希望為集群中的每個主節點創建一個從節點。

    觀察控制臺輸出:

    看到?[OK]?的信息之后,就表示集群已經搭建成功了,可以看到,這里我們正確地創建了三主三從的集群。

    ④、第四步:驗證集群

    我們先使用?redic-cli?任意連接一個節點:

    redis-cli -c -h 127.0.0.1 -p 7000 127.0.0.1:7000>
    • -c?表示集群模式;-h?指定 ip 地址;?-p?指定端口。

    然后隨便 set 一些值觀察控制臺輸入:

    127.0.0.1:7000> SET name wmyskxz -> Redirected to slot [5798] located at 127.0.0.1:7001 OK 127.0.0.1:7001>

    可以看到這里 Redis 自動幫我們進行了Redirected操作跳轉到了7001這個實例上。

    我們再使用?cluster info?(查看集群信息) 和?cluster nodes?(查看節點列表) 來分別看看:(任意節點輸入均可)

    127.0.0.1:7001> CLUSTER INFO cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:6 cluster_my_epoch:2 cluster_stats_messages_ping_sent:1365 cluster_stats_messages_pong_sent:1358 cluster_stats_messages_meet_sent:4 cluster_stats_messages_sent:2727 cluster_stats_messages_ping_received:1357 cluster_stats_messages_pong_received:1369 cluster_stats_messages_meet_received:1 cluster_stats_messages_received:2727 127.0.0.1:7001> CLUSTER NODES 56a04742f36c6e84968cae871cd438935081e86f 127.0.0.1:7003@17003 slave 4ec8c022e9d546c9b51deb9d85f6cf867bf73db6 0 1584428884000 4 connected 4ec8c022e9d546c9b51deb9d85f6cf867bf73db6 127.0.0.1:7000@17000 master - 0 1584428884000 1 connected 0-5460 e2539c4398b8258d3f9ffa714bd778da107cb2cd 127.0.0.1:7005@17005 slave a3406db9ae7144d17eb7df5bffe8b70bb5dd06b8 0 1584428885222 6 connected d31cd1f423ab1e1849cac01ae927e4b6950f55d9 127.0.0.1:7004@17004 slave 236cefaa9cdc295bc60a5bd1aed6a7152d4f384d 0 1584428884209 5 connected 236cefaa9cdc295bc60a5bd1aed6a7152d4f384d 127.0.0.1:7001@17001 myself,master - 0 1584428882000 2 connected 5461-10922 a3406db9ae7144d17eb7df5bffe8b70bb5dd06b8 127.0.0.1:7002@17002 master - 0 1584428884000 3 connected 10923-16383 127.0.0.1:7001>

    5)數據分區方案簡析

    最后

    給大家送一個小福利

    資料附送高清腦圖,高清知識點講解教程,以及一些面試真題及答案解析。送給需要的提升技術、準備面試跳槽、自身職業規劃迷茫的朋友們。

    CodeChina開源項目:【一線大廠Java面試題解析+核心總結學習筆記+最新講解視頻】

    7.0.0.1:7002@17002 master - 0 1584428884000 3 connected 10923-16383
    127.0.0.1:7001>

    ### 5)數據分區方案簡析### 最后給大家送一個小福利[外鏈圖片轉存中...(img-chX9CJZ9-1630376720787)]資料附送高清腦圖,高清知識點講解教程,以及一些面試真題及答案解析。送給需要的提升技術、準備面試跳槽、自身職業規劃迷茫的朋友們。**[CodeChina開源項目:【一線大廠Java面試題解析+核心總結學習筆記+最新講解視頻】](https://codechina.csdn.net/m0_60958482/java-p7)**[外鏈圖片轉存中...(img-PiVa0CBj-1630376720788)]

    總結

    以上是生活随笔為你收集整理的Java中高级核心知识全面解析(3),美团Java面试算法题的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。