2018年9月17日 星期一

Homebrew

Command

Package


Package installed Path

/user/local/Cellar/

List installed package

brew list

List target package

brew list mysql

Install package of latest version 

brew install mysql

Install package of target version

brew install mysql@5.6

Unlink now package

brew unlink mysql@5.6

Switch to new package

brew switch <formula><version>
brew switch mysql 8.0.12

Check current linked package

ls /usr/local/Cellar/<package>
ls /usr/local/Cellar/mysql

List which version of package is currently symlinked

ls -l /usr/local/bin/msyql  => ../Cellar/mysql56/5.6.27/bin/mysql

Service


Install brew services

brew tab homebrew/services

Start/stop a service

sudo brew services start mysql
sudo brew services stop mysql

is equal to:
* ln -sfv /usr/local/opt/mysql/*.plist ~/Library/LaunchAgents
* launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist

List installed services

brew services list

Run but not a background service

mysql.server start

List services

brew services list

MySQL

homebrew github

裝多份mysql 出現 connect /tmp/mysql.sock  error

裝多個版本

Start mysql as service

sudo brew services start mysql
sudo brew services stop mysql

Run but not a background service


mysql.server start

重複裝 出現connect /tmp/mysql.sock error,

先把之前的data folder 刪掉,
unlink,移除再重裝(或 reinstall)


2018年9月10日 星期一

Goland mac delve problem

Debug時錯誤

Error:could not launch process: EOF
Reason:goland使用內建的dlv,版本太舊,改用新的就可以了。

1 brew安裝delve

https://github.com/go-delve/homebrew-delve

2 goland 指定使用自己安裝的delve

選單 Help / Edit custom properties...
dlv.path=/Users/cruise/go/bin/dlv

2018年8月5日 星期日

OOP的五個原則

1. S Single Responsibility Principle (SRP) 單一職責
2. O Open Closed Principle (OCP)           開放封閉
3. L Liskov’s Substitution Principle (LSP) 里氏替換原則
4. I Interface Segregation Principle (ISP) 介面隔離
5. D Dependency Inversion Principle (DIP)  依賴倒轉

各原則是相通且相輔相成的。(廢話,各原則當然不可能互相抵觸。)

某原則可能是其他原則的基礎。

因為注重『單一職責』,程式碼才容易維持『開放封閉』。

因為『里氏替換原則』,才能用替換子物件的方式擴充功能(開放封閉)。

因為『介面隔離』,每個物件遵循各自介面,才能『依賴倒轉』。

Single Responsibility Principle
單一職責原則 / 只能有單一原因去更改類別

  • There should never be more than one reason for a class to change.
  • 每個類別(或者模組)只能有一種原因去改變它。意即每個類別只負責一個職責。
原則很簡單,但是職責的劃分很難。

原文由Robert C. Martin在《敏捷軟體開發,原則,模式和實踐》一書提出。

Robert C. Martin把職責定義為「改變的原因」。職責從另一個角度,就是改變的原因。也許從這個角度看,比較容易劃分。

書中範例:
一個用於編輯和列印報表的類別,有兩種原因會改變它,一個是因為報表內容改變,一個是報表格式改變。這兩種原因有本質上的不同,

所以應區分為兩個類。否則會因為改動其中一個原因而影響另一個。

設計類別(模組)時,要思考,之後只能因為一種原因而改變這個類別的內容。
如果你只會因為一種原因改變它,那它自然就只有一種職責。
從這個角度去思考職責劃分,就比較容易了。

範例武器系統:
遊戲的武器系統模組有「強化」「進階」等功能。每個都應該是一個單一模組。
兩個功能對象都是武器,可能輸入的是相同資料。
如果企劃更改「強化」效果,就要改模組。但「強化」跟「進階」是各自獨立的,所以設計成單一模組。

Open Closed Principle
開放封閉原則

  • Software entities (classes, modules, functions) should be open for extension but closed for modification.
  • 軟體實體(包括類別,模組,函式等)應讓外部能擴展自己的功能,
但對外關閉修改功能。

外部透過繼承等方式,擴充某實體的功能。關鍵字是:擴展。
外部不能修改它原本的功能。關鍵字是:修改。

垂直擴展:
實作上使用介面的方式,定義出開放的部分。繼承者實作介面,然後加讓自己的功能,可達到垂直擴展。

橫向擴展:
新的實體實作相同的介面,裡面提供不同的功能,就能達到橫向擴展。

橫向擴展:
一個實體實作了兩組介面,就能成為兩組繼承鏈的橋樑,達到橫向擴展。

除開放的介面外,其餘一律不跟外界接觸,達到修改封閉。

Lislov's Substitution Principle
里氏替換原則

  • Let q(x) be a property provable about objects x of type T. Then q(y) should be true for objects y of type S where S is a subtype of T.
  • 物件的父類可被其子類替換,而程式行為並無改變。
因為可替換,才延伸出可用子類擴充父類的功能。

因為雙方依賴於抽象層,於是可替換。

Interface Segregation Principle
介面隔離原則

  • Clients should not be forced to depend upon interfaces that they don't use.
  • The dependency of one class to another one should depend on the smallest possible interface。
  • 實作端不應被強迫依賴於它們用不到的介面上。
  • 一個類別依賴於另一個,最好只依賴於最少的介面上。
依賴於用不到的介面,就增加了耦合度,增加未來修改的負擔。總之就是依賴越小越好。

類別依賴於另一類別的介面上,也是越少越好,少到只要能滿組自己需求即可。

『單一職責』告訴我們未來修改的原因只能有一個,因此它不可能有太多功能,意即它只需依賴少少的介面。

介面設計時應區分出來,讓每個類別不碰到不需要的介面。

因為都依賴於抽象層,所以抽象層要劃分的小一點,否則就失去這些原則的功能了。

Dependency Inversion Principle
依賴倒轉原則


  • A high level module should not depend on low level modules. Both should depend on abstractions.
  • Abstractions should not depend on details. Details should depend on abstractions.
  • 高層模組不依賴於低層模組(例如某函式庫),兩者應透過抽象層溝通。例如兩者可透過中間定義的介面來溝通。
  • 抽象不依賴於細節(實作),細節依賴於抽象,其實跟上面同樣意思。兩者的原則都是要依賴於抽象(某介面)。

相互之間只依賴於介面,誰也不依賴另一方,雙方可以獨立修改,才能做到其他原則。

才能開放-封閉。各自內部修改,透過介面對外開放。子物件只要遵循相同介面,就能擴充功能。

中文翻譯的不好,讓人看不懂。個人的理解是透過抽象介面解除依賴,理解成『依賴解除』好點。

2018年7月26日 星期四

實作每秒千萬級別的訊息發送系統

場景

網路協議:       TCP/IP
網路程式介面: socket
CCU:            1000,000
每秒發送訊息次數: 10
總訊息傳送次數:    1000,000*10=10,000,000

瓶頸

linux內核
每秒送出的TCP/IP封包次數上限約 10,000,000/sec

鎖
要遍歷全部的連線,一個一個發送訊息,所以需要加鎖。
數量高達1000,000,所以這個過程很久,導致其他操作無法執行。
例如login,logout,都要等全部發送完解鎖後,才能執行。

頻寬
頻寬約需400MB-600MB之間。

解法

針對linux內核發送TCP/IP封包次數上限瓶頸
減少發送次數,一秒內的訊息,全部組合成一個訊息,統一發送。

針對鎖的瓶頸
把1000,000連線,分拆為多個集合,用併發的方式同步處理,
可有效減少上鎖時間。
鎖用讀寫鎖,不用互斥鎖。

針對頻寬瓶頸
訊息壓鎖。
換1GB網卡,加大頻寬。

單機架構



分散架構

2018年7月25日 星期三

MySQL 輸出結果到檔案


範例

select * from table_name
INTO OUTFILE '/directory/output.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'


以上執行select * from table_name 輸出到 '/directory/output.csv',
以逗號為欄位的分隔符號,然後每個欄位資料以雙引號刮起來,
每筆資料結尾以 '\n' 結束。

MySQL FOREIGN KEY

條件

使用innodb

範例

CREATE TABLE product (
prod_id INT NOT NULL,
prod_name CHAR(20),
PRIMARY KEY (prod_id))
ENGINE = INNODB;

CREATE TABLE order (
order_id INT NOT NULL,
prod_id INT,
FOREIGN KEY(prod_id) REFERENCES product(prod_id)
ON DELETE CASCADE
ON UPDATE CASCADE,
PRIMARY KEY (order_id))
ENGINE = INNODB;


設定 foreign key
 order table 的 prod_id 為foreign key

設定參數
ON DELETE CASCADE
ON UPDATE CASCADE

效果
此時如果 delete product table的某筆資料,
也會 delete order 有foreign key參考到的資料。

此時如果update product table的某筆 prod_id,
也會 update order 有foreign key參考到的 prod_id。

此時drop product table 會出錯,因為 order table 參考到它。

Foreign Key 參數說明

[ON DELETE {CASCADE | SET NULL | NO ACTION | RESTRICT}]
[ON UPDATE {CASCADE | SET NULL | NO ACTION | RESTRICT}]

當關聯父資料表的主鍵紀錄行被刪除或修改時,InnoDB 對子資料表中紀錄行的處理方式:

CASCADE - 會將有所關聯的紀錄行也會進行刪除或修改。
SET NULL - 會將有所關聯的紀錄行設定成 NULL。
NO ACTION - 有存在的關聯紀錄行時,會禁止父資料表的刪除或修改動作。
RESTRICT - 與 NO ACTION 相同。

Foreign Key效用

  1. 利用 db schema 防止程式錯誤及阻擋不合法寫入。
  2. 加速 join 效率。


2018年7月10日 星期二

Golang Primary Data Type


18種基本type
8種複合type

go lang 只有傳值,沒有傳參考
slice,map,pointer,channel都是參考類型,底層都有一個對應的資料結構
當傳slice,map,pointer當參數,修改其內容,也會改到底層對應資料

map
value,ok:=map["key"]
value=value
if無此key-value pair,value ==map element type的零值
if ok==true   表示有此key-value pair
if ok==false  表示無此key-value pair


Data type零值
int=0
bool = false
string= ""
複合類型 =nil
map,slice=nil
function =nil

closure 閉包
保留某個變數,以後可以使用。
不需要每次都建立該變數。
http://openhome.cc/Gossip/JavaScript/Closure.html

方法
是某個附屬於自定義類型的函式
或是附屬於自定義類型對應的指標類型的函式


Interface
只要一個類型實現了該interface的所以方法,那就是實現了該 interface