深入學習Redis(4):哨兵

前言

在 深入學習Redis(3):主從復制 中曾提到,Redis主從復制的作用有數據熱備、負載均衡、故障恢復等;但主從復制存在的一個問題是故障恢復無法自動化。本文將要介紹的哨兵,它基于Redis主從復制,主要作用便是解決主節點故障恢復的自動化問題,進一步提高系統的高可用性。

文章主要內容如下:首先介紹哨兵的作用和架構;然后講述哨兵系統的部署方法,以及通過客戶端訪問哨兵系統的方法;然后簡要說明哨兵實現的基本原理;最后給出關于哨兵實踐的一些建議。文章內容基于Redis 3.0版本。

系列文章

深入學習Redis(1):Redis內存模型

深入學習Redis(2):持久化

深入學習Redis(3):主從復制

深入學習Redis(4):哨兵

目錄

一、作用和架構

1.作用

2. 架構

二、部署

1. 部署主從節點

2. 部署哨兵節點

3. 演示故障轉移

4. 總結

三、客戶端訪問哨兵系統

1. 代碼示例

2. 客戶端原理

3. 總結

四、基本原理

1. 哨兵節點支持的命令

2. 基本原理

五、配置與實踐建議

1. 配置

2. 實踐建議

六、總結

一、作用和架構

1. 作用

在介紹哨兵之前,首先從宏觀角度回顧一下Redis實現高可用相關的技術。它們包括:持久化、復制、哨兵和集群,其主要作用和解決的問題是:

  • 持久化:持久化是最簡單的高可用方法(有時甚至不被歸為高可用的手段),主要作用是數據備份,即將數據存儲在硬盤,保證數據不會因進程退出而丟失。
  • 復制:復制是高可用Redis的基礎,哨兵和集群都是在復制基礎上實現高可用的。復制主要實現了數據的多機備份,以及對于讀操作的負載均衡和簡單的故障恢復。缺陷:故障恢復無法自動化;寫操作無法負載均衡;存儲能力受到單機的限制。
  • 哨兵:在復制的基礎上,哨兵實現了自動化的故障恢復。缺陷:寫操作無法負載均衡;存儲能力受到單機的限制。
  • 集群:通過集群,Redis解決了寫操作無法負載均衡,以及存儲能力受到單機限制的問題,實現了較為完善的高可用方案。

下面說回哨兵。

Redis Sentinel,即Redis哨兵,在Redis 2.8版本開始引入。哨兵的核心功能是主節點的自動故障轉移。下面是Redis官方文檔對于哨兵功能的描述:

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

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

這里對“客戶端”一詞在文章中的用法做一個說明:在前面的文章中,只要通過API訪問redis服務器,都會稱作客戶端,包括redis-cli、Java客戶端Jedis等;為了便于區分說明,本文中的客戶端并不包括redis-cli,而是比redis-cli更加復雜:redis-cli使用的是redis提供的底層接口,而客戶端則對這些接口、功能進行了封裝,以便充分利用哨兵的配置提供者和通知功能。

2. 架構

典型的哨兵架構圖如下所示:

它由兩部分組成,哨兵節點和數據節點:

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

二、部署

這一部分將部署一個簡單的哨兵系統,包含1個主節點、2個從節點和3個哨兵節點。方便起見:所有這些節點都部署在一臺機器上(局域網IP:192.168.92.128),使用端口號區分;節點的配置盡可能簡化。

1. 部署主從節點

哨兵系統中的主從節點,與普通的主從節點配置是一樣的,并不需要做任何額外配置。下面分別是主節點(port=6379)和2個從節點(port=6380/6381)的配置文件,配置都比較簡單,不再詳述。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#redis-6379.conf
port 6379
daemonize yes
logfile "6379.log"
dbfilename "dump-6379.rdb"
#redis-6380.conf
port 6380
daemonize yes
logfile "6380.log"
dbfilename "dump-6380.rdb"
slaveof 192.168.92.128 6379
#redis-6381.conf
port 6381
daemonize yes
logfile "6381.log"
dbfilename "dump-6381.rdb"
slaveof 192.168.92.128 6379

配置完成后,依次啟動主節點和從節點:

1
2
3
redis-server redis-6379.conf
redis-server redis-6380.conf
redis-server redis-6381.conf

節點啟動后,連接主節點查看主從狀態是否正常,如下圖所示:

2. 部署哨兵節點

哨兵節點本質上是特殊的Redis節點。

3個哨兵節點的配置幾乎是完全一樣的,主要區別在于端口號的不同(26379/26380/26381),下面以26379節點為例介紹節點的配置和啟動方式;配置部分盡量簡化,更多配置會在后面介紹。

1
2
3
4
5
#sentinel-26379.conf
port 26379
daemonize yes
logfile "26379.log"
sentinel monitor mymaster 192.168.92.128 6379 2

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

哨兵節點的啟動有兩種方式,二者作用是完全相同的:

1
2
redis-sentinel sentinel-26379.conf
redis-server sentinel-26379.conf --sentinel

按照上述方式配置和啟動之后,整個哨兵系統就啟動完畢了。可以通過redis-cli連接哨兵節點進行驗證,如下圖所示:可以看出26379哨兵節點已經在監控mymaster主節點(即192.168.92.128:6379),并發現了其2個從節點和另外2個哨兵節點。

此時如果查看哨兵節點的配置文件,會發現一些變化,以26379為例:

其中,dir只是顯式聲明了數據和日志所在的目錄(在哨兵語境下只有日志);known-slave和known-sentinel顯示哨兵已經發現了從節點和其他哨兵;帶有epoch的參數與配置紀元有關(配置紀元是一個從0開始的計數器,每進行一次領導者哨兵選舉,都會+1;領導者哨兵選舉是故障轉移階段的一個操作,在后文原理部分會介紹)。

3. 演示故障轉移

哨兵的4個作用中,配置提供者和通知需要客戶端的配合,本文將在下一章介紹客戶端訪問哨兵系統的方法時詳細介紹。這一小節將演示當主節點發生故障時,哨兵的監控和自動故障轉移功能。

(1)首先,使用kill命令殺掉主節點:

(2)如果此時立即在哨兵節點中使用info Sentinel命令查看,會發現主節點還沒有切換過來,因為哨兵發現主節點故障并轉移,需要一段時間。

(3)一段時間以后,再次在哨兵節點中執行info Sentinel查看,發現主節點已經切換成6380節點。

但是同時可以發現,哨兵節點認為新的主節點仍然有2個從節點,這是因為哨兵在將6380切換成主節點的同時,將6379節點置為其從節點;雖然6379從節點已經掛掉,但是由于哨兵并不會對從節點進行客觀下線(其含義將在原理部分介紹),因此認為該從節點一直存在。當6379節點重新啟動后,會自動變成6380節點的從節點。下面驗證一下。

(4)重啟6379節點:可以看到6379節點成為了6380節點的從節點。

(5)在故障轉移階段,哨兵和主從節點的配置文件都會被改寫。

對于主從節點,主要是slaveof配置的變化:新的主節點沒有了slaveof配置,其從節點則slaveof新的主節點。

對于哨兵節點,除了主從節點信息的變化,紀元(epoch)也會變化,下圖中可以看到紀元相關的參數都+1了。

4. 總結

哨兵系統的搭建過程,有幾點需要注意:

(1)哨兵系統中的主從節點,與普通的主從節點并沒有什么區別,故障發現和轉移是由哨兵來控制和完成的。

(2)哨兵節點本質上是redis節點。

(3)每個哨兵節點,只需要配置監控主節點,便可以自動發現其他的哨兵節點和從節點。

(4)在哨兵節點啟動和故障轉移階段,各個節點的配置文件會被重寫(config rewrite)。

(5)本章的例子中,一個哨兵只監控了一個主節點;實際上,一個哨兵可以監控多個主節點,通過配置多條sentinel monitor即可實現。

三、客戶端訪問哨兵系統

上一小節演示了哨兵的兩大作用:監控和自動故障轉移,本小節則結合客戶端演示哨兵的另外兩個作用:配置提供者和通知。

1. 代碼示例

在介紹客戶端的原理之前,先以Java客戶端Jedis為例,演示一下使用方法:下面代碼可以連接我們剛剛搭建的哨兵系統,并進行各種讀寫操作(代碼中只演示如何連接哨兵,異常處理、資源關閉等未考慮)。

1
2
3
4
5
6
7
8
9
10
11
12
public static void testSentinel() throws Exception {
String masterName = "mymaster";
Set<String> sentinels = new HashSet<>();
sentinels.add("192.168.92.128:26379");
sentinels.add("192.168.92.128:26380");
sentinels.add("192.168.92.128:26381");
JedisSentinelPool pool = new JedisSentinelPool(masterName, sentinels); //初始化過程做了很多工作
Jedis jedis = pool.getResource();
jedis.set("key1", "value1");
pool.close();
}

2. 客戶端原理

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

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

(1)遍歷哨兵節點,獲取主節點信息:遍歷哨兵節點,通過其中一個哨兵節點+masterName獲得主節點的信息;該功能是通過調用哨兵節點的sentinel get-master-addr-by-name命令實現,該命令示例如下:

一旦獲得主節點信息,停止遍歷(因此一般來說遍歷到第一個哨兵節點,循環就停止了)。

(2)增加對哨兵的監聽:這樣當發生故障轉移時,客戶端便可以收到哨兵的通知,從而完成主節點的切換。具體做法是:利用redis提供的發布訂閱功能,為每一個哨兵節點開啟一個單獨的線程,訂閱哨兵節點的+switch-master頻道,當收到消息時,重新初始化連接池。

3. 總結

通過客戶端原理的介紹,可以加深對哨兵功能的理解:

(1)配置提供者:客戶端可以通過哨兵節點+masterName獲取主節點信息,在這里哨兵起到的作用就是配置提供者。

需要注意的是,哨兵只是配置提供者,而不是代理。二者的區別在于:如果是配置提供者,客戶端在通過哨兵獲得主節點信息后,會直接建立到主節點的連接,后續的請求(如set/get)會直接發向主節點;如果是代理,客戶端的每一次請求都會發向哨兵,哨兵再通過主節點處理請求。

舉一個例子可以很好的理解哨兵的作用是配置提供者,而不是代理。在前面部署的哨兵系統中,將哨兵節點的配置文件進行如下修改:

1
2
3
sentinel monitor mymaster 192.168.92.128 6379 2
改為
sentinel monitor mymaster 127.0.0.1 6379 2

然后,將前述客戶端代碼在局域網的另外一臺機器上運行,會發現客戶端無法連接主節點;這是因為哨兵作為配置提供者,客戶端通過它查詢到主節點的地址為127.0.0.1:6379,客戶端會向127.0.0.1:6379建立redis連接,自然無法連接。如果哨兵是代理,這個問題就不會出現了。

(2)通知:哨兵節點在故障轉移完成后,會將新的主節點信息發送給客戶端,以便客戶端及時切換主節點。

四、基本原理

前面介紹了哨兵部署、使用的基本方法,本部分介紹哨兵實現的基本原理。

1. 哨兵節點支持的命令

哨兵節點作為運行在特殊模式下的redis節點,其支持的命令與普通的redis節點不同。在運維中,我們可以通過這些命令查詢或修改哨兵系統;不過更重要的是,哨兵系統要實現故障發現、故障轉移等各種功能,離不開哨兵節點之間的通信,而通信的很大一部分是通過哨兵節點支持的命令來實現的。下面介紹哨兵節點支持的主要命令。

(1)基礎查詢:通過這些命令,可以查詢哨兵系統的拓撲結構、節點信息、配置信息等。

  • info sentinel:獲取監控的所有主節點的基本信息
  • sentinel masters:獲取監控的所有主節點的詳細信息
  • sentinel master mymaster:獲取監控的主節點mymaster的詳細信息
  • sentinel slaves mymaster:獲取監控的主節點mymaster的從節點的詳細信息
  • sentinel sentinels mymaster:獲取監控的主節點mymaster的哨兵節點的詳細信息
  • sentinel get-master-addr-by-name mymaster:獲取監控的主節點mymaster的地址信息,前文已有介紹
  • sentinel is-master-down-by-addr:哨兵節點之間可以通過該命令詢問主節點是否下線,從而對是否客觀下線做出判斷

(2)增加/移除對主節點的監控

sentinel monitor mymaster2 192.168.92.128 16379 2:與部署哨兵節點時配置文件中的sentinel monitor功能完全一樣,不再詳述

sentinel remove mymaster2:取消當前哨兵節點對主節點mymaster2的監控

(3)強制故障轉移

sentinel failover mymaster:該命令可以強制對mymaster執行故障轉移,即便當前的主節點運行完好;例如,如果當前主節點所在機器即將報廢,便可以提前通過failover命令進行故障轉移。

2. 基本原理

關于哨兵的原理,關鍵是了解以下幾個概念。

(1)定時任務:每個哨兵節點維護了3個定時任務。定時任務的功能分別如下:通過向主從節點發送info命令獲取最新的主從結構;通過發布訂閱功能獲取其他哨兵節點的信息;通過向其他節點發送ping命令進行心跳檢測,判斷是否下線。

(2)主觀下線:在心跳檢測的定時任務中,如果其他節點超過一定時間沒有回復,哨兵節點就會將其進行主觀下線。顧名思義,主觀下線的意思是一個哨兵節點“主觀地”判斷下線;與主觀下線相對應的是客觀下線。

(3)客觀下線:哨兵節點在對主節點進行主觀下線后,會通過sentinel is-master-down-by-addr命令詢問其他哨兵節點該主節點的狀態;如果判斷主節點下線的哨兵數量達到一定數值,則對該主節點進行客觀下線。

需要特別注意的是,客觀下線是主節點才有的概念;如果從節點和哨兵節點發生故障,被哨兵主觀下線后,不會再有后續的客觀下線和故障轉移操作。

(4)選舉領導者哨兵節點:當主節點被判斷客觀下線以后,各個哨兵節點會進行協商,選舉出一個領導者哨兵節點,并由該領導者節點對其進行故障轉移操作。

監視該主節點的所有哨兵都有可能被選為領導者,選舉使用的算法是Raft算法;Raft算法的基本思路是先到先得:即在一輪選舉中,哨兵A向B發送成為領導者的申請,如果B沒有同意過其他哨兵,則會同意A成為領導者。選舉的具體過程這里不做詳細描述,一般來說,哨兵選擇的過程很快,誰先完成客觀下線,一般就能成為領導者。

(5)故障轉移:選舉出的領導者哨兵,開始進行故障轉移操作,該操作大體可以分為3個步驟:

  • 在從節點中選擇新的主節點:選擇的原則是,首先過濾掉不健康的從節點;然后選擇優先級最高的從節點(由slave-priority指定);如果優先級無法區分,則選擇復制偏移量最大的從節點;如果仍無法區分,則選擇runid最小的從節點。
  • 更新主從狀態:通過slaveof no one命令,讓選出來的從節點成為主節點;并通過slaveof命令讓其他節點成為其從節點。
  • 將已經下線的主節點(即6379)設置為新的主節點的從節點,當6379重新上線后,它會成為新的主節點的從節點。

通過上述幾個關鍵概念,可以基本了解哨兵的工作原理。為了更形象的說明,下圖展示了領導者哨兵節點的日志,包括從節點啟動到完成故障轉移。

五、配置與實踐建議

1. 配置

下面介紹與哨兵相關的幾個配置。

(1) sentinel monitor {masterName} {masterIp} {masterPort} {quorum}

sentinel monitor是哨兵最核心的配置,在前文講述部署哨兵節點時已說明,其中:masterName指定了主節點名稱,masterIp和masterPort指定了主節點地址,quorum是判斷主節點客觀下線的哨兵數量閾值:當判定主節點下線的哨兵數量達到quorum時,對主節點進行客觀下線。建議取值為哨兵數量的一半加1。

(2) sentinel down-after-milliseconds {masterName} {time}

sentinel down-after-milliseconds與主觀下線的判斷有關:哨兵使用ping命令對其他節點進行心跳檢測,如果其他節點超過down-after-milliseconds配置的時間沒有回復,哨兵就會將其進行主觀下線。該配置對主節點、從節點和哨兵節點的主觀下線判定都有效。

down-after-milliseconds的默認值是30000,即30s;可以根據不同的網絡環境和應用要求來調整:值越大,對主觀下線的判定會越寬松,好處是誤判的可能性小,壞處是故障發現和故障轉移的時間變長,客戶端等待的時間也會變長。例如,如果應用對可用性要求較高,則可以將值適當調小,當故障發生時盡快完成轉移;如果網絡環境相對較差,可以適當提高該閾值,避免頻繁誤判。

(3) sentinel parallel-syncs {masterName} {number}

sentinel parallel-syncs與故障轉移之后從節點的復制有關:它規定了每次向新的主節點發起復制操作的從節點個數。例如,假設主節點切換完成之后,有3個從節點要向新的主節點發起復制;如果parallel-syncs=1,則從節點會一個一個開始復制;如果parallel-syncs=3,則3個從節點會一起開始復制。

parallel-syncs取值越大,從節點完成復制的時間越快,但是對主節點的網絡負載、硬盤負載造成的壓力也越大;應根據實際情況設置。例如,如果主節點的負載較低,而從節點對服務可用的要求較高,可以適量增加parallel-syncs取值。parallel-syncs的默認值是1。

(4) sentinel failover-timeout {masterName} {time}

sentinel failover-timeout與故障轉移超時的判斷有關,但是該參數不是用來判斷整個故障轉移階段的超時,而是其幾個子階段的超時,例如如果主節點晉升從節點時間超過timeout,或從節點向新的主節點發起復制操作的時間(不包括復制數據的時間)超過timeout,都會導致故障轉移超時失敗。

failover-timeout的默認值是180000,即180s;如果超時,則下一次該值會變為原來的2倍。

(5)除上述幾個參數外,還有一些其他參數,如安全驗證相關的參數,這里不做介紹。

2. 實踐建議

(1)哨兵節點的數量應不止一個,一方面增加哨兵節點的冗余,避免哨兵本身成為高可用的瓶頸;另一方面減少對下線的誤判。此外,這些不同的哨兵節點應部署在不同的物理機上。

(2)哨兵節點的數量應該是奇數,便于哨兵通過投票做出“決策”:領導者選舉的決策、客觀下線的決策等。

(3)各個哨兵節點的配置應一致,包括硬件、參數等;此外,所有節點都應該使用ntp或類似服務,保證時間準確、一致。

(4)哨兵的配置提供者和通知客戶端功能,需要客戶端的支持才能實現,如前文所說的Jedis;如果開發者使用的庫未提供相應支持,則可能需要開發者自己實現。

(5)當哨兵系統中的節點在docker(或其他可能進行端口映射的軟件)中部署時,應特別注意端口映射可能會導致哨兵系統無法正常工作,因為哨兵的工作基于與其他節點的通信,而docker的端口映射可能導致哨兵無法連接到其他節點。例如,哨兵之間互相發現,依賴于它們對外宣稱的IP和port,如果某個哨兵A部署在做了端口映射的docker中,那么其他哨兵使用A宣稱的port無法連接到A。

六、總結

本文首先介紹了哨兵的作用:監控、故障轉移、配置提供者和通知;然后講述了哨兵系統的部署方法,以及通過客戶端訪問哨兵系統的方法;再然后簡要說明了哨兵實現的基本原理;最后給出了關于哨兵實踐的一些建議。

在主從復制的基礎上,哨兵引入了主節點的自動故障轉移,進一步提高了Redis的高可用性;但是哨兵的缺陷同樣很明顯:哨兵無法對從節點進行自動故障轉移,在讀寫分離場景下,從節點故障會導致讀服務不可用,需要我們對從節點做額外的監控、切換操作。

此外,哨兵仍然沒有解決寫操作無法負載均衡、及存儲能力受到單機限制的問題;這些問題的解決需要使用集群,我將在后面的文章中介紹,歡迎關注。


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

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

相關文章

1805. 字符串中不同整數的數目

1805. 字符串中不同整數的數目 給你一個字符串 word &#xff0c;該字符串由數字和小寫英文字母組成。 請你用空格替換每個不是數字的字符。例如&#xff0c;“a123bc34d8ef34” 將會變成 " 123 34 8 34" 。注意&#xff0c;剩下的這些整數為&#xff08;相鄰彼此至…

經天測繪測量工具包_公共土地測量系統

經天測繪測量工具包部分-鄉鎮第一師 (Sections — First Divisions of Townships) The PLSS Townships are typically divided into 36 Sections (nominally one mile on a side), but in the national standard this feature is called the first division because Townships …

洛谷 P4012 深海機器人問題【費用流】

題目鏈接&#xff1a;https://www.luogu.org/problemnew/show/P4012 洛谷 P4012 深海機器人問題 輸入輸出樣例 輸入樣例#1&#xff1a; 1 1 2 2 1 2 3 4 5 6 7 2 8 10 9 3 2 0 0 2 2 2 輸出樣例#1&#xff1a; 42 說明 題解&#xff1a;建圖方法如下&#xff1a; 對于矩陣中的每…

day5 模擬用戶登錄

_user "yangtuo" _passwd "123456"# passd_authentication False #flag 標志位for i in range(3): #for 語句后面可以跟else&#xff0c;但是不能跟elifusername input("Username:")password input("Password:")if username _use…

opencv實現對象跟蹤_如何使用opencv跟蹤對象的距離和角度

opencv實現對象跟蹤介紹 (Introduction) Tracking the distance and angle of an object has many practical uses, especially in robotics. This tutorial explains how to get an accurate distance and angle measurement, even when the target is at a strong angle from…

spring cloud 入門系列七:基于Git存儲的分布式配置中心--Spring Cloud Config

我們前面接觸到的spring cloud組件都是基于Netflix的組件進行實現的&#xff0c;這次我們來看下spring cloud 團隊自己創建的一個全新項目&#xff1a;Spring Cloud Config.它用來為分布式系統中的基礎設施和微服務提供集中化的外部配置支持&#xff0c;分為服務端和客戶端兩個…

458. 可憐的小豬

458. 可憐的小豬 有 buckets 桶液體&#xff0c;其中 正好 有一桶含有毒藥&#xff0c;其余裝的都是水。它們從外觀看起來都一樣。為了弄清楚哪只水桶含有毒藥&#xff0c;你可以喂一些豬喝&#xff0c;通過觀察豬是否會死進行判斷。不幸的是&#xff0c;你只有 minutesToTest…

熊貓數據集_大熊貓數據框的5個基本操作

熊貓數據集Tips and Tricks for Data Science數據科學技巧與竅門 Pandas is a powerful and easy-to-use software library written in the Python programming language, and is used for data manipulation and analysis.Pandas是使用Python編程語言編寫的功能強大且易于使用…

圖嵌入綜述 (arxiv 1709.07604) 譯文五、六、七

應用 圖嵌入有益于各種圖分析應用&#xff0c;因為向量表示可以在時間和空間上高效處理。 在本節中&#xff0c;我們將圖嵌入的應用分類為節點相關&#xff0c;邊相關和圖相關。 節點相關應用 節點分類 節點分類是基于從標記節點習得的規則&#xff0c;為圖中的每個節點分配類標…

聊聊自動化測試框架

無論是在自動化測試實踐&#xff0c;還是日常交流中&#xff0c;經常聽到一個詞&#xff1a;框架。之前學習自動化測試的過程中&#xff0c;一直對“框架”這個詞知其然不知其所以然。 最近看了很多自動化相關的資料&#xff0c;加上自己的一些實踐&#xff0c;算是對“框架”有…

1971. Find if Path Exists in Graph

1971. Find if Path Exists in Graph 有一個具有 n個頂點的 雙向 圖&#xff0c;其中每個頂點標記從 0 到 n - 1&#xff08;包含 0 和 n - 1&#xff09;。圖中的邊用一個二維整數數組 edges 表示&#xff0c;其中 edges[i] [ui, vi] 表示頂點 ui 和頂點 vi 之間的雙向邊。 …

移動磁盤文件或目錄損壞且無法讀取資料如何找回

文件或目錄損壞且無法讀取說明這個盤的文件系統結構損壞了。在平時如果數據不重要&#xff0c;那么可以直接格式化就能用了。但是有的時候里面的數據很重要&#xff0c;那么就必須先恢復出數據再格式化。具體恢復方法可以看正文了解&#xff08;不格式化的恢復方法&#xff09;…

python 平滑時間序列_時間序列平滑以實現更好的聚類

python 平滑時間序列In time series analysis, the presence of dirty and messy data can alter our reasonings and conclusions. This is true, especially in this domain, because the temporal dependency plays a crucial role when dealing with temporal sequences.在…

基于SmartQQ協議的QQ自動回復機器人-1

0. 本項目的原始代碼及我二次開發后的代碼 1. 軟件安裝:【myeclipse6.0 maven2】 0. https://blog.csdn.net/zgmzyr/article/details/6886440 1. https://blog.csdn.net/shuzhe66/article/details/45009175 2. https://www.cnblogs.com/whgk/p/7112560.html<mirror><…

1725. 可以形成最大正方形的矩形數目

1725. 可以形成最大正方形的矩形數目 給你一個數組 rectangles &#xff0c;其中 rectangles[i] [li, wi] 表示第 i 個矩形的長度為 li 、寬度為 wi 。 如果存在 k 同時滿足 k < li 和 k < wi &#xff0c;就可以將第 i 個矩形切成邊長為 k 的正方形。例如&#xff0c…

幫助學生改善學習方法_學生應該如何花費時間改善自己的幸福

幫助學生改善學習方法There have been numerous studies looking into the relationship between sleep, exercise, leisure, studying and happiness. The results were often quite like how we expected, though there have been debates about the relationship between sl…

Spring Boot 靜態資源訪問原理解析

一、前言 springboot配置靜態資源方式是多種多樣&#xff0c;接下來我會介紹其中幾種方式&#xff0c;并解析一下其中的原理。 二、使用properties屬性進行配置 應該說 spring.mvc.static-path-pattern 和 spring.resources.static-locations這兩屬性是成對使用的&#xff0c;如…

深挖“窄帶高清”的實現原理

過去幾年&#xff0c;又拍云一直在點播、直播等視頻應用方面潛心鉆研&#xff0c;取得了不俗的成果。我們結合點播、直播、短視頻等業務中的用戶場景&#xff0c;推出了“省帶寬、壓成本”系列文章&#xff0c;從編碼技術、網絡架構等角度出發&#xff0c;結合又拍云的產品成果…

學習總結5 - bootstrap學習記錄1__安裝

1.bootstrap是什么&#xff1f; 簡潔、直觀、強悍的前端開發框架&#xff0c;說白了就是給后端二把刀開發網頁用的&#xff0c;讓web開發更迅速、簡單。 復制代碼 2.如何使用&#xff1f; 如圖所示到bootstrap中文網進行下載 復制代碼 下載完成之后&#xff0c;如圖所示&#x…

519. 隨機翻轉矩陣

519. 隨機翻轉矩陣 給你一個 m x n 的二元矩陣 matrix &#xff0c;且所有值被初始化為 0 。請你設計一個算法&#xff0c;隨機選取一個滿足 matrix[i][j] 0 的下標 (i, j) &#xff0c;并將它的值變為 1 。所有滿足 matrix[i][j] 0 的下標 (i, j) 被選取的概率應當均等。 …