###### tags: `code`
# 品優科技筆試(網路)
Brian Cho卓宥辰
## 請簡述 TCP 建立到關閉的過程,並簡單舉例。
建立連線:三次握手
斷開連線:四次揮手
由於 TCP 連線是全雙工的,因此每個方向都必須單獨進行關閉。
這個原則是當一方完成它的資料傳送任務後就能傳送一個 FIN 來終止這個方向的連線。
## 請簡述MySQL中myisam與innodb的區別,至少5點。
### myisam
myisam不支持事務,但是每次查詢都是原子的;
myisam支持表級鎖,即每次操作是對整個表加鎖;
#### 存儲表的總行數;
一個 MYISAM 表有三個文件:索引文件、表結構文件、數據文件;
採用菲聚集索引,索引文件的數據域存儲指向數據文件的指針。輔索引與主索引
基本一致,但是輔索引不用保證唯一性。
### InnoDb:
支持 ACID 的事務,支持事務的四種隔離級別;
支持行級鎖及外鍵約束:因此可以支持寫並發;
#### 不存儲總行數:
一個 InnoDb 引擎存儲在一個文件空間(共享表空間,表大小不受操作系統控制,
一個表可能分佈在多個文件裡),也有可能為多個(設置為獨立表空,表大小受
操作系統文件大小限制,一般為 2G),受操作系統文件大小的限制;
主鍵索引採用聚集索引(索引的數據域存儲數據文件本身),輔索引的數據域存
儲主鍵的值;因此從輔索引查找數據,需要先通過輔索引找到主鍵值,再訪問輔
索引;最好使用自增主鍵,防止插入數據時,為維持 B+樹結構,文件的大調整。
## 請描述如何使用 Redis 來做分佈鎖,會用到什麼 api?
1. 加鎖動作
2. 守護線程,鎖自動續期
3. 解鎖動作
## 請列出使用過的 RDBMS 與 NoSQL,並描述兩者差異。
### 使用過
PostgreSQL ,ArandoDB
### 關聯式資料庫(RDBMS)
RDBMS (Relational Database Management System) 又為關聯式資料庫管理系統,意即資料庫是由多個資料表(Table)所組成,並且可以將資料表關聯起來,去連結多個資料表之間的關係。諸如 MySQL, PostgreSQL, MS SQL, … 都是關聯式資料庫。以下列出幾個關聯式資料庫的特點:
由資料表(Table)組成,其中 row 代表一筆資料,column 代表資料欄位名稱
Schema 必須先定義好,並且只接受同樣格式資料的插入與修改。往後如果要修改 schema,必須對於已存在的資料做相對應的處理較為麻煩
可以使用 JOIN 來連結多個資料表,做較複雜的查詢
具備 ACID 特性
使用 SQL(Structured Querying Language) 來管理及查詢資料
### 非關聯式資料庫(NOSQL)
NOSQL(Non-SQL,又為 Not only SQL) 稱為非關聯式資料庫,跟關聯式資料庫不一樣,不需要定義 schema、沒有關聯的關係。諸如 MongoDB, Redis, … 都是非關聯式資料庫的一種。以下為非關聯式資料庫的幾個特點:
資料庫由 collection 組成
collection 中每筆資料為一份 document,document 的資料格式不需一致
以 CAP theorem 為概念設計
常用於分散式雲端系統
## 請說明 Message Queue 的用途,並列出具有其功能的工具。
訊息佇列(Message Queue,簡稱MQ),從字面意思上看,本質是個佇列,FIFO先入先出,只不過佇列中存放的內容是message。
其主要用途:
不同程序 Process 之間
不同執行緒 Thread 之間
不同服務之間 (Microservice)
RabbitMQ , moonmq
## 請描述一個分散式架構系統,並畫出其架構圖。
玩家登入與遊玩服務做分散設計
```mermaid
graph LR
GS[GameService]
GS2[GameService2]
GM[Login]
C[Client]
C-->GM
GM-->GS
GM-->GS2
GM-->DB
GS-->DB
GS2-->DB
```
### 承6,請描述在架構中如何設計跨服務的 GUID
GUID的總數也足夠大,達到了2128(3.4×1038)個,所以隨機生成兩個相同GUID的可能性是非常小的
### 承6,請描述在該架構中,如何處理資料落地時的一致性問題 (e.g. Cache 與 Database)
Consistency (一致性)
站在 client 的角度來觀察系統的行為和特徵
從 client 的讀寫角度來描述資料一致性
在事務執行過程中,系統其實處於一個不一致的狀態,不同的節點的資料並不完全一致,但 client 讀操作能夠獲取最新的寫結果就沒有問題
Availability (可用性)
只有非故障節點才能滿足可用性要求,如果節點本身就故障了,發給節點的請求不一定能得到一個響應
不能超時、不能出錯,結果是合理的(但結果有可能因為資料尚未同步完整,導致資料是不正確的)
Partition Tolerance (分區容忍性)
只有返回 reasonable response 才是 function(可用功能),而 function 強調”發揮作用” & “履行職責”
即發生了分區現象,不管是什麼原因,可能是網路封包遺失,也可能是連接中斷,還可能是擁塞,只要導致了網路分區,就通通算在裡面
### 承6,請描述在該架構中,所出現的併發情境及可能產生的問題,提出對應的解決方案
高併發登入時,會壅塞登入系統,可以做附載平衡系統處理
### 承6,請以架構中的任一 Service 為例,如何實現 Graceful shutdown 與災難恢復
1. 單一Service,藉由context來Graceful shutdown相關線程
2. 定期或即時快取系統快照至redis或其他外部儲存設備
3. 如果需要災難恢復,則根據快照恢復系統
## 排序過的 N 個正整數中,如何使用二元搜尋法找到其中的一個數?
```
e.g. [3, 5, 6, 7, 8, 10],找到 5。
```
```go
func Search(n int, f func(int) bool) int {
// Define f(-1) == false and f(n) == true.
// Invariant: f(i-1) == false, f(j) == true.
i, j := 0, n
for i < j {
h := int(uint(i+j) >> 1) // avoid overflow when computing h
// i ≤ h < j
if !f(h) {
i = h + 1 // preserves f(i-1) == false
} else {
j = h // preserves f(j) == true
}
}
// i == j, f(i-1) == false, and f(j) (= f(i)) == true => answer is i.
return i
}
```
## 在一個產生隨機 1 或 0 陣列中,如何簡化隨機的次數?
```
e.g. [30%, 70%] 產生兩個數,
第一個數有 30% 機率為 0,70 % 為 1
第二個數有 70% 機率為 1,30% 為 0
如何只用一次亂數就產生出需要的陣列
```
$rng \in [0,2^{32}-1]$
rng1 = rng&0x0000FFFF
rng2 = (rng&0xFFFF0000)>>16
$rng1,rng2 \in [0,2^{16}-1]$
根據rng1,rng2在2^16的占比即可決定隨機數列