主頁 > 後端開發 > Kettle構建Hadoop ETL實踐(十):并行、集群與磁區

Kettle構建Hadoop ETL實踐(十):并行、集群與磁區

2020-12-10 17:54:42 後端開發

目錄

一、資料分發方式與多執行緒

1. 資料行分發

2. 記錄行合并

3. 記錄行再分發

4. 資料流水線

5. 多執行緒的問題

6. 作業中的并行執行

二、Carte子服務器

1. 創建Carte子服務器

2. 定義子服務器

3. 遠程執行

4. 監視子服務器

5. Carte安全

6. 服務

三、集群轉換

1. 定義一個靜態集群

2. 設計集群轉換

3. 執行和監控

4. 元資料轉換

5. 配置動態集群

四、資料庫磁區

1. 在資料庫連接中使用集群

2. 創建資料庫磁區schemas

3. 啟用資料庫磁區

4. 資料庫磁區示例

5. 集群轉換中的磁區

五、小結


本專題前面系列文章詳細說明了使用Kettle的轉換和作業,實作Hadoop上多維資料倉庫的ETL程序,通常Hadoop集群存盤的資料量是TB到PB,如果Kettle要處理如此多的資料,就必須考慮如何有效使用所有的計算資源,并在一定時間內獲取執行結果,

作為本專題的最后一篇文章,將深入介紹Kettle轉換和作業的垂直和水平擴展,垂直擴展是盡可能使用單臺服務器上的多個CPU核,水平擴展是盡可能使用多臺計算機,使它們并行計算,第一部分先介紹轉換內部的并行機制和多種垂直擴展方法,然后說明怎樣在子服務器集群環境下進行水平擴展,最后描述如何利用Kettle資料庫磁區進一步提高并行計算的性能,

一、資料分發方式與多執行緒

在“Kettle與Hadoop(一)Kettle簡介”中,我們知道了轉換的基本組成部分是步驟,而且各個步驟是并行執行的,現在將更深入解釋Kettle的多執行緒能力,以及應該如何通過這種能力垂直擴展一個轉換,

默認情況下,轉換中的每個步驟都在一個隔離的執行緒里并行執行,但可以為任何步驟增加執行緒數,我們也稱之為“拷貝”,這種方法能夠提高那些消耗大量CPU時間的轉換步驟的性能,來看一個簡單的例子,如圖10-1所示,“×2”的符號表示該步驟將有兩份拷貝同時運行,右鍵單擊步驟,選擇選單中的“改變開始復制的數量”,在彈出的對話框設定步驟執行緒數,

圖10-1 在多個拷貝下運行一個步驟

注意所有步驟拷貝只維護一份步驟的描述,也就是說,一個步驟僅是一個任務的定義,而一個步驟拷貝則表示一個實際執行任務的執行緒,

1. 資料行分發

Kettle轉換中,各步驟之間行集(row set)的發送有分發和復制兩種方式,我們用一個簡單的例子輔助說明,定義一個轉換,以t1表作為輸入,輸出到表t2和t3,t1表中有1-10十個整數,當創建第二個跳(hop)時,會彈出一個警告視窗,如圖10-2所示,

圖10-2 一個警告對話框

表輸入步驟將向兩個表輸出步驟發送資料行,此時可以選擇采用分發或復制兩種方式之一,預設為分發方式,分發方式執行后,t2、t3表的資料如下,

mysql> select * from t2;              mysql> select * from t3;
+------+                              +------+
| a    |                              | a    |
+------+                              +------+
|    1 |                              |    2 |
|    3 |                              |    4 |
|    5 |                              |    6 |
|    7 |                              |    8 |
|    9 |                              |   10 |
+------+                              +------+
5 rows in set (0.00 sec)              5 rows in set (0.00 sec)

本例中,“表輸入”步驟里的記錄發送給兩個“表輸出”步驟,默認情況下,分發作業使用輪詢方式進行,也就是第一表輸出步驟獲取第一條記錄,第一表輸出步驟獲取第二條記錄,如此回圈,直到沒有記錄分發為止,

復制方式是將全部資料行發送給所有輸出跳,例如同時往資料庫表和檔案里寫入資料,本例以復制方式執行后,t2、t3表都將具有t1表的全部10行資料,通常情況下每一條記錄僅僅處理一次,所以復制的情況用的比較少,下面看一下多執行緒分發的情況,圖10-3所示的轉換中,輸入單執行緒,兩個輸出,一個單執行緒、另一個兩執行緒,

圖10-3 兩個表輸出步驟一個單執行緒、另一個兩執行緒

轉換執行后,t2、t3表的資料如下,輸入執行緒輪詢分發,單執行緒輸出每次寫一行,兩執行緒輸出每次寫兩行,

mysql> select * from t2;              mysql> select * from t3;
+------+                              +------+
| a    |                              | a    |
+------+                              +------+
|    1 |                              |    3 |
|    4 |                              |    6 |
|    7 |                              |    2 |
|   10 |                              |    9 |
+------+                              |    5 |
4 rows in set (0.00 sec)              |    8 |
                                      +------+
                                      6 rows in set (0.00 sec)

圖10-4所示的轉換中,輸入單執行緒、兩個輸出均為兩執行緒,

圖10-4 兩個表輸出步驟均為兩執行緒

轉換執行后,t2、t3表的資料如下,輸入執行緒向兩個輸出步驟輪詢分發資料行,兩個輸出步驟每次寫兩行,

mysql> select * from t2;              mysql> select * from t3;
+------+                              +------+
| a    |                              | a    |
+------+                              +------+
|    2 |                              |    4 |
|    6 |                              |    3 |
|    1 |                              |    8 |
|   10 |                              |    7 |
|    5 |                              +------+
|    9 |                              4 rows in set (0.00 sec)
+------+
6 rows in set (0.00 sec)

2. 記錄行合并

前面例子都是表輸入步驟為單執行緒的情況,當有幾個步驟或者一個步驟的多份拷貝同時發送給單個步驟拷貝時,會發生記錄行合并,如圖10-5所示,

圖10-5 合并記錄行

轉換執行后,t2、t3表的資料如下,可以看到,每個輸入執行緒都以分發方式并行將資料行依次發給每個輸出跳,結果t2表資料為兩倍的單數、而t3表資料為兩倍的雙數,

mysql> select * from t2;              mysql> select * from t3;
+------+                              +------+
| a    |                              | a    |
+------+                              +------+
|    1 |                              |    2 |
|    3 |                              |    4 |
|    5 |                              |    6 |
|    7 |                              |    8 |
|    9 |                              |   10 |
|    1 |                              |    2 |
|    3 |                              |    4 |
|    5 |                              |    6 |
|    7 |                              |    8 |
|    9 |                              |   10 |
+------+                              +------+
10 rows in set (0.00 sec)             10 rows in set (0.00 sec)

從“表輸出”步驟來看,并不是依次從每個資料源逐條讀取資料行,如果這樣做會導致比較嚴重的性能問題,例如一個步驟輸送資料很慢,而另一個步驟輸送資料很快,實際上資料行都是從前面步驟批量讀取的,因此也不能保證從前面步驟的多個拷貝中讀取記錄的順序!

3. 記錄行再分發

記錄行再分發是指,X個步驟拷貝把記錄行發送給Y個步驟拷貝,如圖10-6所示,

圖10-6 記錄行再分發

在本例中,兩個表輸入步驟拷貝都把記錄行分發給四個目標表輸出步驟拷貝,這個結果等同于圖10-7的轉換,

圖10-7 記錄行再分發展開

從圖10-7可以看出,在表輸入和表輸出步驟之間有X*Y個行緩沖區,本例中兩個源步驟和八個目標步驟之間有16個緩沖區(箭頭),在設計轉換的時候要記住這一點,如果在轉換末端有很慢的步驟,這些快取都可能被填滿,這樣會增加記憶體消耗,默認情況下最大緩沖區的記錄行數是10000(可在轉換屬性雜項標簽頁中的“記錄集合里的記錄數”屬性進行設定),所以記憶體中能保存的記錄行總數是160000行,

轉換執行后,t2、t3表的資料如下,輸出為四執行緒,因此輸入的第一個執行緒將前四行發送到輸出1,然后將接著的四行發送到輸出2,然后再將接著的四行(此時只剩兩行)發送到輸出1,輸入的第二個執行緒也同樣執行這樣的程序,最終t2表兩個1、2、3、4、9、10,t3表有兩個5、6、7、8,

mysql> select * from t2;              mysql> select * from t3;
+------+                              +------+
| a    |                              | a    |
+------+                              +------+
|    2 |                              |    8 |
|    3 |                              |    7 |
|    4 |                              |    6 |
|   10 |                              |    7 |
|    3 |                              |    8 |
|    4 |                              |    5 |
|    1 |                              |    6 |
|    2 |                              |    5 |
|    9 |                              +------+
|    1 |                              8 rows in set (0.00 sec)
|   10 |
|    9 |
+------+
12 rows in set (0.00 sec)

由前面這些例子可以總結出分發方式下執行規律:每個輸入步驟執行緒執行相同的作業,即輪流向每個輸出步驟發送資料行,每次發送的行數等于相應輸出步驟的執行緒數,

4. 資料流水線

資料流水線是再分發的一種特例,在資料流水線里源步驟和目標步驟的拷貝數相等(X==Y),此時,前面步驟拷貝的記錄行不是分發到下面所有的步驟拷貝,實際上,由源步驟的拷貝產生的記錄行被發送到具有相同編號的目標步驟拷貝,圖10-8是這種轉換的例子,

圖10-8 資料流水線

在技術上,它等同于圖10-9的轉換,

圖10-9 資料流水線展開

轉換執行后,t2、t3表的資料與圖10-5所示轉換的執行結果相同,從現象看輸入輸出執行緒數相等時,結果如同X個獨立的單執行緒轉換,

分發和合并記錄的程序會產生一點性能開銷,通常情況下,最好讓連續步驟的拷貝數相等,這樣可以減少開銷,這種減少步驟開銷之間開銷的程序,也可形象地比喻為將資料放進游泳池的泳道,彼此之間不受干擾,

5. 多執行緒的問題

通過前面的學習,我們知道了一個多執行緒轉換中所有步驟拷貝都并行運行,接下來看這種執行模式可能產生的一些問題,以及如何解決這些問題,

(1)資料庫連接
如果多執行緒軟體處理資料庫連接,推薦的方法是在轉換執行的程序中為每個執行緒創建單一的連接,使得每個步驟拷貝都使用它們自己的事務或或者事務集,這也正式Kettle的默認配置,但有一個潛在的后果是,如果在同一轉換里使用同一個資料庫資源,如一個表或一個視圖,很容易產生條件競爭問題,

一個常見的錯誤場景,就是在前面的步驟里向一個關系資料庫表里寫入資料,在隨后的步驟里再讀取這些資料,因為這兩個步驟使用不同的資料庫連接,而且是不同的事務,不能確保第一個步驟寫入的資料,對其它正在執行讀操作的步驟可見,

解決這個問題的簡單方案是把這個轉換分成兩個不同的轉換,然后將資料保存在臨時表或檔案中,另外一個方案是強制讓所有步驟使用單一資料庫連接(僅一個事務),啟用轉換設定對話框“雜項”標簽頁中的“使用唯一連接”選項即可,該選項意味著Kettle里用到的每個命名資料庫都使用一個連接,直到轉換執行完河駁交事務或者回滾,也就是說在執行程序中完全沒有錯斡駁交,有任何錯誤就回滾,請注意,如果錯誤被錯誤處理步驟處理了,事務就不會回滾,使用這個選項的缺點是會降低轉換的性能,原因之一是可能產生較大的事務,另外如果所有步驟和資料庫的通信都由一個步驟的資料庫連接來完成,在服務器端也只有一個服務器行程來處理請求,

(2)執行的順序
由于所有步驟并行執行,所以轉換中的步驟沒有特定的執行順序,但是資料集成程序中仍然有些作業需要按某種順序執行,在大多數情況下,通過創建一個作業來解決這個問題,使任務可以按特定的順序執行,在Kettle轉換中,也有些步驟強制按某種順序執行,下面有幾個技巧,

  • “執行SQL腳本”步驟

如果想在轉換中的其它步驟開始前,先執行一段SQL腳本,可以使用“執行SQL腳本”步驟,正常模式下,這個步驟將在轉換的初始化階段執行SQL,就是說它優先于其它步驟執行,但是如果選中了這個步驟里的“執行每一行”選項,那么該步驟不會提前執行,而是按照在轉換中的順序執行,

  • “Blocking step”步驟

如果希望所有的資料行都達到某個步驟后,才開始執行一個操作,可以使用“Blocking step”步驟,該步驟的默認配置是丟棄最后一行以外的所有資料,然后把最后一行資料傳遞給下一個步驟,這條資料將觸發后面的步驟執行某個操作,這樣就能確保在后面步驟處理之前,所有資料行已經在前面步驟處理完,

6. 作業中的并行執行

默認情況下,作業中的作業項按順序執行,必須等待一個作業項執行完成后才開始執行下一個,然而,正如“https://wxy0327.blog.csdn.net/article/details/106348479#4.%20%E5%B9%B6%E8%A1%8C%E6%89%A7%E8%A1%8C”所述,在作業里也可以并行執行作業項,并行執行的情況下,一個作業項之后的多個作業項同時執行,由不同的執行緒啟動每個并行執行的作業項,例如,希望并行更新多張維度表,可以按照圖10-10的方式設計,選擇Start作業項右鍵選單中的“Run Next Entries in Parallel”選項即可,

圖10-10 并行更新多張維度表

二、Carte子服務器

子服務器是Kettle的組成模塊,用來遠程執行轉換和作業,物理上體現為Carte行程,Carte是一個輕量級的服務行程,可以支持遠程監控,并為轉換提供集群的能力,集群在下節介紹,子服務器是一個小型的HTTP服務器,也是集群的最小組成模塊,用它來接收遠程客戶端的命令,這些命令用于作業和轉換的部署、管理與監控,

正如“https://wxy0327.blog.csdn.net/article/details/107985148#%EF%BC%883%EF%BC%89Carte”所述,Carte程式用于子服務器遠程執行轉換和作業,啟動子服務器需要指定主機名或IP地址,以及Web服務的埠號,下面在Kettle 8.3版本上,通過一個具體的例子描述子服務器的配置、創建、使用和監控,示例環境如下:
172.16.1.102:創建Carte子服務器,
172.16.1.101:創建轉換,并在172.16.1.102上的子服務器上遠程執行,

1. 創建Carte子服務器

在172.16.1.102上執行下面的步驟創建子服務器,

(1)創建組態檔
在Kettle的早期版本里,通過命令列指定配置選項,隨著配置選項數目的增加,Kettle最近的版本使用XML格式的組態檔,例如創建如下內容的組態檔slave1.xml,描述一臺子服務器的所有屬性:

<slave_config>
  <max_log_lines>0</max_log_lines>
  <max_log_timeout_minutes>0</max_log_timeout_minutes>
  <object_timeout_minutes>5</object_timeout_minutes>
  
  <slaveserver>
    <name>server1</name>
    <hostname>172.16.1.102</hostname>
    <port>8181</port>
  </slaveserver>
</slave_config>

<slaveserver>節點里描述了子服務器的主機名和監聽埠,另外在組態檔里還可以配置子服務器的其它屬性,用于優化像Carte這樣長時間運行的服務器行程的記憶體使用,

  • max_log_lines:設定日志系統保存在記憶體中的最大日志行數,
  • max_log_timeout_minutes:設定保存在記憶體中的日志行的最大存活時間(分鐘),對于運行時間很長的轉換和作業,這是一個尤其重要的選項,防止子服務器記憶體溢位,
  • object_timeout_minutes:默認情況下,在子服務器的狀態報告中,可以看到所有轉換和作業,這個引數可以自動地從狀態報告串列中清除老的作業,

(2)啟動子服務器

./carte.sh ~/kettle_hadoop/slave1.xml

命令執行在控制臺輸出的最后資訊如下,表示子服務器已經啟動成功,

...
2020/12/03 09:32:32 - Carte - Installing timer to purge stale objects after 5 minutes.
2020/12/03 09:32:33 - Carte - 創建 web 服務監聽器 @ 地址: 172.16.1.102:8181

2. 定義子服務器

在172.16.1.101上定義上步創建的子服務器,Spoon左側的“主物件樹”標簽頁中,右鍵單擊“子服務器”樹節點,選擇“新建”,然后在彈出的新建對話框中,填入子服務器的具體屬性,如圖10-11所示,

圖10-11 定義子服務器

其中用戶名、密碼都是cluster,定義完子服務器后,可右鍵單擊“server1”樹節點,選擇“Share”共享該子服務器,以便被所有轉換和作業使用,

3. 遠程執行

在172.16.1.101上執行下面的步驟遠程執行轉換,

(1)新建運行配置
在Spoon左側的“主物件樹”標簽頁中,右鍵單擊“Run configurations”樹節點,選擇“New...”,在彈出對話框中配置運行屬性,如圖10-12所示,

圖10-12 配置運行屬性

選擇Pentaho作為運行轉換的引擎時,運行配置對話框的設定部分包含以下選項:

  • Local:選擇本地Pentaho引擎運行,
  • Slave server:選擇此選項可將轉換發送到遠程服務器或Carte群集,
  • Location:指定遠程服務器的位置,
  • Send resources to this server:遠程執行前會將轉換發送到子服務器,此選項是將轉換的相關資源,例如參考的其它檔案,也包含在發送到服務器的資訊中,

(2)遠程執行轉換
在執行轉換時彈出的“執行轉換”對話框里指定要運行轉換的遠程子服務器,如圖10-13中的server1,如果作業或轉換被另一個作業呼叫,可以在作業或轉換作業項的對話框里選擇一個遠程子服務器,此時作業或轉換作業項即可遠程執行,

圖10-13 選擇遠程子服務器

可見所謂遠程執行,只是將本地定義的轉換或作業的元資料及其相關資源傳到遠程子服務器上,然后再在子服務器上執行,轉換或作業中用到的物件,如資料庫連接等,必須在其運行的遠程子服務器的Kettle中已經定義,否則不能正常執行,

4. 監視子服務器

有幾種方法可以遠程監視子服務器,

  • Spoon:在Spoon樹形選單中右鍵單擊子服務器,選擇“Monitor”選項,就會在Spoon中出現一個監控界面,包含了所有運行在子服務器上的轉換和作業的串列,如圖10-14所示,
  • Web瀏覽器:打開一個瀏覽器視窗,輸入子服務器的地址,例如http://172.16.1.102:8181/,瀏覽器將顯示一個子服務器選單,通過這些選單項,可以監控子服務器,
  • PDI企業控制臺:這是PDI企業版的一部分,企業控制臺提供了監控和控制子服務器的功能,
  • 自定義的應用:每個子服務器都以URL方式提供服務,回傳的結果是XML格式的資料,可以通過它與子服務器通信,如果使用了Kettle的Java庫,還可以利用Kettle的XML介面來決議這些XML,
圖10-14 在Spoon中監視子服務器

除此之外,從子服務器在控制臺終端列印的日志,也可看到轉換或作業的執行資訊,

5. Carte安全

默認情況下Carte使用簡單的HTTP認證,在檔案pwd/kettle.pwd中定義了用戶名和密碼,Kettle默認的用戶名/密碼都是cluster,檔案中的密碼可以利用Kettle自帶的Encr工具來混淆,要生成一個Carte密碼檔案,使用-carte選項,像這個例子:

sh encr.sh -carte Password4Carte
OBF:1ox61v8s1yf41v2p1pyr1lfe1vgt1vg11lc41pvv1v1p1yf21v9u1oyc

使用文本編輯器,將回傳的字串追加到密碼檔案中用戶名的后面:

Someuser: OBF:1ox61v8s1yf41v2p1pyr1lfe1vgt1vg11lc41pvv1v1p1yf21v9u1oyc

OBF:前綴告訴Carte這個字串是被混淆的,如果不想混淆這個檔案中的密碼,也可以像下面這樣指定明文密碼:

Someuser:Password4Carte

需要注意的是,密碼是被混淆,而不是被加密,Kettle的encr演算法僅僅是讓密碼更難識別,但絕不是不能識別,如果一個軟體能讀取這個密碼,必須假設別的軟體也能讀取這個密碼,因此應該給這個密碼檔案一些合適的權限,阻止他人未經授權訪問kettle.pwd檔案,能降低密碼被破解的風險,

6. 服務

子服務器對外提供了一系列服務,表10-1列出了它定義的服務,這些服務位于Web服務的/kettle/的URI下面,在我們的例子里,就是http://172.16.1.102:8181/kettle/,所有服務都有xml=Y選項以回傳XML,客戶端就可以決議,表10-1還說明了服務使用的類(包org.pentaho.di.www),

服務名稱

描述

引數

Java

status

回傳所有轉換和作業的狀態

SlaveServerStatus

transStatus

回傳一個轉換的狀態并且列出所有步驟的狀態

name(轉換名稱)

from line(增量日志的開始記錄行)

SlaveServerTransStatus

prepareExecution

準備轉換,完成所有步驟的初始化作業

name(轉換名稱)

WebResult

startExec

執行轉換

name(轉換名稱)

WebResult

startTrans

一次性初始化和執行轉換,雖然方便,但是不適用在集群執行環境下,因為初始化需要在集群上同時執行

name(轉換名稱)

WebResult

pauseTrans

暫停或者恢復一個轉換

name(轉換名稱)

WebResult

stopTrans

終止一個轉換的執行

name(轉換名稱)

WebResult

addTrans

向子服務器中添加一個轉換,客戶端需要提交XML形式的轉換給Carte

TransConfiguration

WebResult

allocateSocket

在子服務器上分配一個服務器套接字,更多內容參考本篇后面的“集群轉換”

sniffStep

獲取一個正在運行的轉換中,經過某個步驟的所有資料行

trans(轉換名稱)

step(步驟名稱)

copy(步驟的拷貝號)

line(獲取行數)

type(輸入還是輸出)

<step-sniff>XML包含了一個RowMeta物件以及一組序列化的資料行

startJob

開始執行作業

name(作業名稱)

WebResult

stopJob

終止執行作業

name(作業名稱)

WebResult

addJob

向子服務器中添加一個作業,客戶端需要提交XML形式的作業給Carte

JobConfiguration

WebResult

jobStatus

獲取單個作業的狀態并列出作業下所有作業項的狀態

name(作業名稱)

from(增量日志的開始記錄行)

SlaveServerJobStatus

registerSlave

把一個子服務器注冊到主服務器上(參考“集群轉換”部分),需要客戶端把子服務器的XML提交給子服務器

SlaveServerDetection

WebResult(reply)

getSlaves

獲得主服務器下的所有子服務器的串列

<SlaveServerDetections>

節點下包含了幾個SlaveServerDetection節點

addExport

把匯出的.zip格式的作業或轉換,傳送給子服務器,檔案保存為服務器的臨時檔案,客戶端給Carte服務器提交zip檔案的內容,這個方法總是回傳XML

WebResult里包含了臨時檔案的URL

表10-1 子服務器服務

三、集群轉換

集群技術可以用來水平擴展轉換,使它們能以并行的方式運行在多臺服務器上,轉換的作業可以平均分到不同的服務器上,一個集群模式包括一個主服務器和多個子服務器,主服務器作為集群的控制器,只有在集群模式中,才有主服務器和子服務器的概念,作為控制器的Carte服務器就是主服務器,其它的Carte服務器就是子服務器,本節將介紹怎樣配置和執行一個轉換,讓其運行在多臺機器上,

集群模式也包含元資料,描述了主服務器和子服務器之間怎樣通信,在Carte服務器之間通過TCP/IP套接字傳遞資料,之所以選擇TCP/IP而不用Web Services作為資料交換的方式,是因為后者比較慢,而且會帶來不必要的性能開銷,

1. 定義一個靜態集群

在定義一個集群模式之前,需要先定義一些子服務器,參考上一節的方法,我們已經定義了三個子服務器,其中名為master是主服務器,這是通過在子服務器對話框中勾選“是主服務器嗎?”選項設定的,如圖10-15所示,除此之外不需要給Carte傳遞任何特別的引數,圖中的slave1、slave2為另外兩個子服務器,

圖10-15 構成Kettle集群的三個子服務器

定義完子服務器,右鍵單擊Spoon里的“Kettle集群schemas”節點,然后選擇“新建”選項,在配置視窗里設定集群模式的所有選項,至少選擇一個主服務器作為控制器并選擇一個或更多子服務器,如圖10-16所示,

圖10-16 集群schemas對話框

這里有幾個重要的選項,

  • 埠:在服務器之間傳遞資料的最小的TCP/IP埠號,這是一個起始埠號,如果你的集群轉換需要50個埠,從初始埠號到初始埠號+50之間的所有埠都會被使用,
  • Sockets快取大小:快取大小用來使子服務器之間通信更平滑,不要把這個值設定得太大,否則資料傳輸程序可能比較波動,
  • Sockets重繪間隔(rows):因為進行Socket通信時,傳遞的資料行可能保存在Socket的快取中,這里要設定一個重繪間隔,快取中的資料行積累到一定數量,轉換引擎就會執行flush操作,強制把資料推送給對方服務器,這個引數的大小,取決于子服務器之間的網路速度和延遲,
  • Sockets資料是否壓縮:設定子服務器之間傳輸的資料是否需要壓縮,對于相對較慢的網路(如10Mbps),可以設定這個選項,設定該選項會導致集群轉換變慢,因為壓縮和解壓資料流需要CPU時間,在網路不是瓶頸時,最好不啟用這個選項,
  • Dynamic cluster:如果設定了這個選項,Kettle會在主服務器上自動搜尋子服務器串列,來構建集群,

2. 設計集群轉換

設計一個集群轉換,需要先設計一個普通的轉換,在轉換里創建一個集群模式,然后選擇希望通過集群方式運行的步驟,右鍵單擊這個步驟,選擇集群,選擇完步驟要運行的集群模式后,轉換將變成如圖10-17所示的樣子,

圖10-17 一個集群轉換

這個轉換從表中讀取資料,然后排序,再將資料寫入一個文本檔案,執行集群轉換時,所有被定義成集群運行(在圖10-15中有“C×2”標志)的步驟都在這個集群的子服務器上運行,而那些沒有集群標識的步驟都在主服務器上運行,本例中“表輸入”和“排序記錄”兩個步驟會在兩個子服務器上并行執行,而“排序合并”和“文本檔案輸出”兩個步驟只在主服務器上執行,

注意在圖10-17中,“排序記錄”步驟使用了兩個不同的子服務器并行排序,所以就有兩組排好序的資料行依次回傳給主服務器,因為后面的步驟接收這兩組資料,所以還要在后面的步驟里把這兩組資料再排序,由“排序合并”步驟來完成這個作業,它從所有的輸入步驟中逐行讀取記錄,然后進行多路合并排序,沒有這個步驟,并行排序的結果是錯誤的,

如果轉換中至少要有一個步驟被指定運行在一個集群上,這個轉換才是一個集群轉換,為了除錯和開發,集群轉換可以在Spoon的執行對話框中以非集群的方法執行,在一個轉換中只能使用一個集群,

3. 執行和監控

執行下面的步驟執行集群轉換,

(1)新建運行配置
在Spoon左側的“主物件樹”標簽頁中,右鍵單擊“Run configurations”樹節點,選擇“New...”,在彈出對話框中配置運行屬性,如圖10-18所示,

圖10-18 配置集群運行屬性

與圖10-12所示的遠程執行設定,這里的Location選擇集群,并出現兩個新選項:

  • Log remote execution locally:顯示來自群集節點的日志,
  • Show transformations:顯示集群運行時生成的轉換,

(2)執行集群轉換
在執行轉換時彈出的“執行轉換”對話框里指定要運行轉換的集群運行配置,如本例中的cluster,然后啟動轉換,

在Spoon樹形選單中右鍵單擊“Kettle集群schemas”下的集群名稱,選擇彈出選單中的“Monitor all slave servers”,會在Spoon中出現一個所有主、子服務器的監控界面,每個服務器一個標簽頁,包含了所有運行在相應服務器上的轉換和作業串列,本例集群中的三個服務器顯示如圖10-19所示,

圖10-19 集群服務器監控頁面

最后輸出的文本檔案在master服務器上生成,與遠程執行一樣,各主、子Carte服務器在控制臺終端列印的日志,也可看到轉換或作業的執行資訊,

4. 元資料轉換

主服務器和子服務器運行的并不是一樣的轉換,在主服務器和子服務器上運行的轉換是由一個叫元資料轉換(Metadata Transformations)的翻譯流程產生的,在Spoon中設計的原始轉換的元資料,被切分成多個轉換,重新組織,再增加額外資訊,然后發送給目標子服務器,

關于元資料轉換,有以下三種型別的轉換:

  • 原始轉換:用戶在Spoon中設計的集群轉換,
  • 子服務器轉換:它源自原始轉換,運行在一個特定子服務器上的轉換,集群里的每個子服務器都會有一個子服務器轉換,
  • 主服務器轉換:它源自原始轉換,運行在主服務器上的轉換,

在圖10-17這個集群例子里,生成了兩個子服務器轉換和一個主服務器轉換,勾選集群運行配置中的“Show transformations”選項,將在集群轉換運行時顯示生成的轉換,圖10-20顯示了本例的主服務器轉換,圖10-21顯示了本例的子服務器轉換,

圖10-20 主服務器轉換

圖10-21 子服務器轉換

淺灰色編號的區域說明在步驟里有遠程輸入或輸出連接,稱之為遠程步驟(Remote Steps),在我們的例子里,有兩個子服務器把資料從“排序記錄”步驟發送到“排序合并”步驟,這意味著兩個“排序記錄”步驟都有一個遠程輸出步驟,并且“排序合并”步驟有兩個遠程輸入步驟,如果將滑鼠懸置到這個淺灰色的矩形內,將會獲取更多關于該遠程步驟的資訊,還有分配的埠號,如圖10-22所示,

圖10-22 遠程步驟上的提示資訊

(1)規則
可以想象,操作這些元資料轉換時,有很多可能性,以下幾個通用的規則,可以確保邏輯操作正確:

  • 如果一個步驟被配置成集群方式運行,它會被復制到一個子服務器轉換,
  • 如果一個步驟沒有被配置成集群運行,它會被復制到一個主服務器轉換,
  • 發送資料給一個集群步驟的步驟被定義為遠程輸出步驟(發送資料通過TCP/IP sockets),
  • 從一個集群步驟接收資料的步驟被定義為遠程輸入步驟(接收資料通過TCP/IP sockets),

下面的規則更復雜,因為它們處理集群里一些更加復雜的功能,

  • 多份拷貝的步驟也可以在集群方式下運行,在這種情況下,遠程輸入和輸出步驟將分發給不同的步驟拷貝,因為拷貝在遠程機器上運行,所以太多的步驟拷貝沒有意義,
  • 一般情況,集群轉換要盡量簡單,這樣更容易分析生成的轉換,
  • 當一個步驟要從特定的步驟里讀取資料(資訊步驟),在生成的轉換里使用“Socket Reader”和“Socket Writer”步驟來做這個作業,

(2)資料流水線
記得在本篇前面介紹多執行緒與資料分發時提到資料流水線或資料的泳道:在Carte服務器之間交換的資料越多,轉換就會越慢,理想情況下應該按照從頭到尾并行執行的方式來組織資料,例如,處理100個XML檔案會比處理一個單一的大檔案更容易,因為在多份檔案情況下資料能夠被并行讀取,

作為通用的規則,要使集群轉換獲取好的性能,應盡量讓轉換簡單,在同一子服務器上,盡可能在泳道里做更多的事情,以減少服務器之間的資料傳輸,

5. 配置動態集群

有兩種型別的Kettle集群,靜態集群有一個固定的模式,它指定一個主服務器和兩個或多個子服務器,而動態集群中僅需指定主服務器,子服務器則通過組態檔動態注冊到主服務器,以下步驟配置并執行一個一主兩從的動態集群轉換,

(1)創建主服務器組態檔master.xml

<slave_config>
  <max_log_lines>0</max_log_lines>
  <max_log_timeout_minutes>0</max_log_timeout_minutes>
  <object_timeout_minutes>5</object_timeout_minutes>
  
  <slaveserver>
    <name>master</name>
    <hostname>172.16.1.102</hostname>
    <port>8181</port>
    <username>cluster</username>
    <password>cluster</password>
    <master>Y</master>
  </slaveserver>
</slave_config>

(2)創建子服務器組態檔slave1.xml

<slave_config>
  <max_log_lines>0</max_log_lines>
  <max_log_timeout_minutes>0</max_log_timeout_minutes>
  <object_timeout_minutes>5</object_timeout_minutes>
  
  <masters>
    <slaveserver>
      <name>master</name>
      <hostname>172.16.1.102</hostname>
      <port>8181</port>
      <username>cluster</username>
      <password>cluster</password>
      <master>Y</master>
    </slaveserver>
  </masters>
 
  <report_to_masters>Y</report_to_masters>
 
  <slaveserver>
    <name>slave1</name>
    <hostname>172.16.1.103</hostname>
    <port>8181</port>
    <username>cluster</username>
    <password>cluster</password>
    <master>N</master>
  </slaveserver>
</slave_config>

masters節點定義一個或多個負載均衡Carte實體管理此子服務器,slaveserver節點包含有關此Carte子服務器實體的資訊,

(3)啟動主服務器

./carte.sh ~/kettle_hadoop/master.xml

(4)啟動子服務器

./carte.sh ~/kettle_hadoop/slave1.xml

(5)按照(2)(4)步驟創建并啟動第二個子服務器

(6)在Spoon新建一個動態集群,如圖10-23所示

圖10-23 建立動態集群

勾選“Dynamic cluster”選項表示配置動態集群,與靜態集群不同,子服務器串列中只加入了master,

(7)修改圖10-17所示的轉換,步驟選擇動態集群,如圖10-24所示

圖10-24 動態集群轉換

此時會看到“表輸入”和“排序記錄”步驟的左上角出現“C×N”標志,說明這些步驟將在集群的所有子服務器上運行,

(8)以集群方式執行轉換

四、資料庫磁區

磁區是一個非常籠統的術語,廣義地講是將資料拆分成多個部分,在資料集成和資料庫方面,磁區指拆分表或資料庫,表可以劃分成不同的“表磁區”(table partions),資料庫可以劃分成不同的片(shards),

除了資料庫外,也可以把文本或XML檔案磁區,例如按照每家商店或區域磁區,由于資料集成工具需要支持各種磁區技術,所以Kettle中的磁區被設計成與源資料和目標資料無關,

磁區是Kettle轉換引擎的核心,每當一個步驟把資料行使用“分發模式”發送給多個目標步驟時,實際就是在進行磁區,分發模式的磁區使用“輪詢”的方式,實際上這種方式并不比隨機發送好多少,它也不是本節要討論的一個磁區方法,

我們討論的Kettle磁區,是指Kettle可根據一個磁區規則把資料發送到某個特定步驟拷貝的能力,在Kettle里,一組給定的磁區集叫做磁區模式(partitioning schema),規則本身叫做磁區方法(partitioning method),磁區模式要么包含一組命名磁區串列,要么簡單地包含幾個磁區,磁區方法不是磁區模式的一部分,

下面介紹Kettle 8.3中資料庫磁區的使用,

1. 在資料庫連接中使用集群

在Kettle的資料庫連接對話框中,可定義資料庫磁區,如圖10-25所示,

圖10-25 資料庫連接中配置集群

在“集群”標簽,勾選“使用集群”,然后定義三個磁區,這里的磁區實際指的是資料庫實體,需要指定自定義的磁區ID,資料庫實體的主機名(IP)、埠、資料庫名、用戶名和密碼,定義磁區的目的是為了從某一個磁區甚至某一個物理資料庫讀取和寫入資料,一旦在資料庫連接里面定義了資料庫磁區,就可以基于這個資訊創建了一個磁區schema,

在“一般”標簽,只要指定連接名稱、連接型別和連接方式,在“設定”中都可以為空,如圖10-26所示,Kettle假定所有的磁區都是同一資料庫型別和連接型別,

圖10-26 使用集群的資料庫連接

定義好磁區后點擊“測驗”,結果如圖10-27所示,

圖10-27 測驗資料庫集群連接

2. 創建資料庫磁區schemas

在“主物件樹”的“資料庫磁區schemas”上點右鍵“新建”,在彈出視窗中輸入“磁區schema名稱”,然后點擊“匯入磁區”按鈕,如圖10-28所示,

圖10-28 配置資料庫磁區schemas

選擇上一步定義的資料庫連接mysql_only_shared,點“確定”按鈕后,如圖10-29所示,

圖10-29 匯入資料庫磁區

此時已經匯入了上一步定義的三個資料庫磁區,點擊“OK”保存,這樣就定義了一個名為shared_source的資料庫磁區schema,再用同樣的方法定義一個名為shared_target的資料庫磁區schema,所含磁區也從mysql_only_shared匯入,

至此,我們已經定義了一個包含三個磁區的資料庫連接,并將磁區資訊匯入到兩個資料庫磁區schema,如圖10-30所示,

圖10-30 兩個資料庫磁區模式

現在可以在任何步驟里面應用這兩個資料庫磁區schema(就是說使用這個磁區的資料庫連接),Kettle將為每個資料庫磁區產生一個步驟復制,并且它將連接物理資料庫,

3. 啟用資料庫磁區

點擊步驟右鍵,選擇“磁區...”選單項,此時會彈出一個對話框,選擇使用哪個磁區方法,如圖10-31所示,

圖10-31 選擇磁區方法

磁區方法可以是下面的一種:

  • None:不使用磁區,標準的“Distribute rows”(輪詢)或“Copy rows”(復制)規則被應用,
  • Mirror to all partitions:使用已定義的資料庫磁區schema中的所有磁區,
  • Remainder of division:Kettle標準的磁區方法,通過磁區編號除以磁區數目,產生的余數被用來決定記錄行將發往哪個磁區,例如在一個記錄行里,如果有 “73” 標識的用戶身份,而且有3個磁區定義,這樣這個記錄行屬于磁區1,編號30屬于磁區0,編號14屬于磁區2,需要指定基于磁區的欄位,

選擇“Mirror to all partitions”,在彈出視窗中選擇已定義的磁區schema,如圖10-32所示,

圖10-32 選擇磁區模式

經此一番設定后,該步驟就將以磁區方式執行,如圖10-33所示,

圖10-33 使用資料庫磁區的表輸入步驟

4. 資料庫磁區示例

(1)將三個mysql實體的資料匯入到另一個mysql實體
轉換如圖10-34所示,

圖10-34 表輸入使用磁區

“表輸入”步驟連接的是mysql_only_shared,因為是按磁區方式執行,實際讀取的是三個磁區的資料,表輸出使用的是一個標準的單實體資料庫連接,該轉換執行的邏輯為:

db1.t1 + db2.t1 + db3.t1 -> db4.t4

轉換執行的結果是將三個mysql實體的資料匯入到另一個mysql實體,如果將表輸入步驟連接到一個標準的單實體資料庫,雖然資料庫連接本身沒有使用集群,但依然會為每個磁區復制一份步驟,其結果等同于3執行緒的復制分發,

(2)將一個mysql實體的資料分發到三個mysql實體
轉換如圖10-35所示,

圖10-35 表輸出使用磁區

表輸出步驟連接的是mysql_only_shared,因為是按磁區方式執行,會向三個磁區中的表輸出資料,該轉換執行的邏輯為:

db4.t4 -> db1.t2
db4.t4 -> db2.t2
db4.t4 -> db3.t2

(3)將三個mysql實體的資料匯入到另三個mysql實體
轉換如圖10-36所示,

圖10-36 輸入輸出使用不同磁區

輸入步驟使用的是shared_source磁區schema,而輸出步驟使用的是shared_target磁區schema,該轉換執行的邏輯為:

db1.t1 + db2.t1 + db3.t1 -> db4.t2
db1.t1 + db2.t1 + db3.t1 -> db5.t2
db1.t1 + db2.t1 + db3.t1 -> db6.t2

(4)將三個mysql實體的資料匯入相同實體的不同表中
轉換還是如圖10-36所示,與前一個例子只有一點區別:輸入步驟與輸出步驟使用的是同一個磁區schema(shared_source),該轉換執行的邏輯為:

db1.t1 -> db1.t2
db2.t1 -> db2.t2
db3.t1 -> db3.t2

在資料庫連接中定義磁區時需要注意一點,磁區ID應該唯一,如果多個磁區ID相同,則所有具有相同ID的磁區都會連接到第一個具有該ID的磁區,例如,我們把mysql_only_shared的磁區定義改為如圖10-37所示,

圖10-37 磁區有相同ID

103與104兩個磁區的磁區ID都是2,然后重新匯入shared_source,并再次執行轉換,結果只會向103中插入資料,而104沒有執行任何操作,

從這個例子可以看到,Kettle里實作磁區很簡單:對于每個磁區步驟,Kettle會根據所選擇的磁區方法啟動多個步驟拷貝,如果定義了五個磁區,就會有五個步驟拷貝,磁區步驟的前一個步驟做重磁區的作業,當一個步驟里資料沒有磁區,這個步驟把資料發送給一個磁區步驟的時候,就是在做重磁區的作業,使用一種磁區模式磁區的步驟把資料發送給使用另一個磁區模式的步驟,也會做重新磁區的作業,

本節實體的具體表資料和轉換執行結果參見“Kettle資料庫連接中的集群與分片”,其它資料庫相關的步驟也和上面的例子類似,這樣多個資料庫可以并行處理,另外“Mirror to all partitions”磁區方法可以并行將同樣的資料寫入多種資料庫磁區,這樣在做資料庫查詢時,就可以把查詢表的資料同時復制到多個資料庫磁區中,而不用再建立多個資料庫連接,

5. 集群轉換中的磁區

如果在一個轉換里定義了很多磁區,轉換里的步驟拷貝數會急劇增長,為了解決這個問題,需要把磁區分散到集群中的子服務器中,

在轉換執行程序中,磁區平均分配給各個子服務器,如果使用靜態磁區串列的方式定義了一個磁區模式,在運行時,那些磁區將會被平均分配到子服務器上,這里有一個限制,磁區的數量必須大于或等于子服務器的數量,通常是子服務器的整數倍(slaves × 2、slaves × 3等),有一個解決磁區過多問題的簡單配置方法,就是指定每臺子服務器上的磁區數,這樣在運行時就可以動態創建磁區模式,不用事先指定磁區串列,

記住如果在集群轉換里使用了磁區步驟,資料需要跨子服務器重新磁區,這會導致相當多的資料通信,例如,有10臺子服務器的一個集群,步驟A也有10份拷貝,但下面的步驟B設定為在每個子服務器上運行3個磁區,這就需要創建10×30條資料路徑,與圖10-7中的例子相似,這些資料流向路徑中的10×30-30=270條路徑包含了遠程步驟,會引起一些網路阻塞,以及CPU和記憶體的消耗,在設計帶磁區的集群轉換時,要考慮這個問題,

五、小結

本篇介紹了轉換的多執行緒、集群和資料庫磁區,重點內容包括:

  • 介紹了一個轉換如何并行執行步驟,如果一個步驟有多個步驟拷貝,如何分發資料行,介紹了資料行是如何被分發以及合并到一起的,并介紹了并發可能導致的幾個問題,
  • 介紹了如何在遠程服務器上部署、執行、管理和監控轉換和作業,
  • 深入介紹了如何使用多臺子服務器構建一個集群,如何構建轉換來利用這些子服務器資源,
  • 最后介紹了如何使用Kettle的資料庫磁區模式來并行處理資料庫的讀寫操作,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/232561.html

標籤:java

上一篇:由 ObjectInputStream 所引起的 Java 記憶體泄漏問題

下一篇:什么是微內核架構設計?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more