Tuesday 21 October 2014

MySQL Community vs Enterprise vs Standard

Trong khoảng 2 năm làm việc của mình, database mình sử dụng thường xuyên nhất là MySQL, trong nhiều dự án khác nhau, vì tính phổ biến và dễ sử dụng.

Câu hỏi mình tự hỏi bản thân mình là tại sao MySQL lại có các phiên bản khác nhau như vậy? (Community - Standard - Enterprise). Có ai từng có câu hỏi tương tự như mình chưa nhỉ?

Thanks to Lynn Ferrante, mình tìm được câu trả lời từ một bài viết của anh ấy.

Community vs Enterprise

2 phiên bản community và enterprise khá là giống nhau, chỉ khác ở chỗ, ở bản enterprise được thêm vào một số tính năng:
- Support : support for mission critical issues and hot fixes.
- Backup : MEB ( MySQL Enterprise Backup ), online InnoDB,MyISAM backups.
- Monitoring Tools : MEM ( MySQL Enterprise Monitor ), Query Analyzer, Web Based configuration Plugins :
- Additional plugins for performance improvement i.e. thread pool, PAM authentication etc

Ta thấy tính năng quan trọng nhất của bản enterprise chính là sử dụng "thread pool" để tối ưu hiệu năng cho database. Vậy thread pool là gì? và tại sao nó làm tăng hiệu năng?

Đây là câu trả lời chính thức từ MySQL (rất đầy đủ và chi tiết):
Bản tóm tắt:
MySQL Thread Pool là plugin dùng để tăng khả năng quản lí kết nối (connection handling) của MySQL server, giới hạn số lượng kết nối đồng thời thực thi statement/query và transaction để đảm bảo mỗi connection đều có CPU và memory để thực hiện công việc của nó.
Bình thường MySQL sử dụng mô hình thread-handling (một connection đến sẽ có một thread xử lí). Do đó, càng nhiều client kết nối đến server và thực thi statement, hiệu suất chung sẽ giảm đi.
Thread Pool được tạo ra để thay thế thread-handling, làm giảm overhead và tăng performance, hiệu quả khi xử lí nhiều thread cho số lượng lớn kết nối, đặc biệt hệ thống mới (multi-CPU/Core system)
Thread Pool sử dụng cách "chia để trị" (devide and conquer) để giới hạn và cân bằng sự đồng thời. Nó tách biệt connection và thread, do đó không có quan hệ gì giữa thread xử lí và connection đến. Nó quản lí client connection theo từng thread group, chúng được đánh dấu độ ưu tiên và xếp hàng dựa vào bản chất của công việc của chúng.

Cơ chế hoạt động:
Thread được tổ chức thành 16 group (mặc định, có thể tăng lên thành 64 group). Mỗi group bắt đầu với 1 thread và có thể tăng lên đến maximum 4096 thread, additional thread được tạo ra khi cần thiết.
Mỗi connection đến được gán vào một group theo cơ chế Round robin. Mỗi group đều có một "listener thread" để lắng nghe yêu cầu kết nối đến.

 Khi có yêu cầu kết nối đến group, listener thread của group sẽ thực thi ngay lập tức nếu không bận và không có yêu cầu nào đang đợi. Nếu yêu cầu được thực hiện xong nhanh, listener thread sẽ trở về trạng thái chờ yêu cầu tiếp theo (ngăn chặn việc thêm một thread mới được tạo ra). Nếu yêu cầu đó không kết thúc nhanh (vẫn còn đang xử lí), một thread mới được tạo ra, trở thành lister thread mới.

Nếu listener thread đang bận xử lí, yêu cầu đến được xếp vào hàng đợi. Sẽ có một khoảng thời gian rất ngắn (thread_pool_stall_limit, mặc định là 60ms) ta phải đợi để biết câu lệnh đang thực thi có kết thúc nhanh hay không. Nếu nó hoàn thành nhanh (ít hơn thời gian của thread_pool_stall_limit), ta có thể sử dụng lại thread này cho yêu cầu tiếp theo trong hàng đợi, giúp loại trừ overhead việc tạo thread mới hay có quá nhiều statement ngắn để thực thi đồng thời (parrallel)


Thiết kế của thread pool là cố gắng có một thread thực thi trên một group bất kì lúc nào. Số lượng group (thread_pool_size_variable) là cực kì quan trọng, vì nó xấp xỉ với số lượng short-running statement thực thi đồng thời trong khoảng bất kì lúc nào. Long-running statement được ngăn chặn không gây ra việc đợi cho các statement khác, vì nếu chúng vượt quá thời gian (thread_pool_stall_limit), một thread khác sẽ được tạo ra, yêu cầu tiếp theo trong hàng đợi sẽ thực thi trên đó.

Có 2 loại hàng đợi cho waiting statement, low và high priority.
Hàng đợi low priority (ưu tiên thấp) bao gồm:
- tất cả các statement cho các loại non-transactional storage engine (MyISAM, ISAM)
- tất cả các statement nếu autocommit được enable.
- statement đầu tiên trong InnoDB transaction.
Các câu lệnh trên tất nhiên sẽ không nằm đợi mãi như vậy, vì nó sẽ bị đá đến hàng đợi hàng đợi high priority khi thời gian thread_pool_prio_kickup_timer hết. Tuy nhiên, chỉ có số lượng tối đa số statement được di chuyển trong một khoảng thời gian mà thôi(100 statement/s), đảm bảo mọi thứ trong tầm điều khiển.

Hàng đợi high priority (ưu tiên cao) bao gồm:
- bất kì câu lệnh tiếp theo nào trong InnoDB transaction.
- bất kì câu lệnh nào bị kick khỏi hàng đợi low priority.

Standard vs Enterprise
Bạn có thể thêm thông tin ở đây để biết nó khác nhau chỗ nào ;)

Some information links:
- http://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_thread_pool_algorithm
- http://dev.mysql.com/doc/refman/5.6/en/thread-pool-tuning.html















Tuesday 7 October 2014

Bandwidth vs Throughput

Đây là 2 từ khóa rất dễ bị hỏi và bắt bẽ trong các buổi interview, hi vọng bài này sẽ giúp các bạn phần nào hiểu được bản chất của 2 từ khóa này.

- Bandwidth: là tốc độ một thiết bị có thể gửi dữ liệu trên một đường truyền nhanh đến mức nào. Một trong những ví dụ kinh điển là đường cao tốc có 4 lane chạy cùng một chiều. Cả 4 lane đều đông xe và di chuyển với tốc độ nhanh nhất , trong trường hợp này đường cao tốc là bandwidth.

- Throughput: có nghĩa là bao nhiêu bit thực sự được truyền đi giữa 2 máy tính, hoặc tỉ lệ trung bình thành công các message được gửi đi qua kênh truyền. Dữ liệu này có thể được truyền qua đường truyền vật lý hay logic. Cũng với ví dụ xe ô-tô lúc nãy, giả sử một chiếc xe đại diện cho một gói tin 64KB, một vòng đi và về của xe trên cùng một tuyến đường trong một đơn vị thời gian (thường là mili giây) gọi là throughput.

Để dễ hiểu hơn nữa, mình sẽ đưa ra một ví dụ qua công thức tính:

Giả sử chúng ta có:

- Tất cả kết nối giữa các ISP đều là 45Mbps
- Tất cả thiết bị đều có TCP window là 64KB (65535 byte)
- Các thiết bị thực hiện testing đều kết nối trực tiếp đến ISP của mỗi vùng
- Chỉ có các traffic của thiết bị thực hiện testing trên đường truyền
- Không có nghẽn mạng giữa các node
- Không có mất gói tin giữa các node
- RTT (round trip time) giữa server (New York) đến client (Chicago) là 30ms
- RTT (round trip time) giữa servẻ (New York) đến client (Japan) là 20ms






Ta có mô hình như trên. Công thức tính throughput của upload/download giữa các node như sau:
TCP throughput NY to Chicago = (64000 bytes x 8) bits / 0.03 second = 17066666 bps = 17Mbps
TCP throughput NY to Japan = (640000 bytes x 8) bits / 0.03 second = 2560000 bps = 2.56Mbps

Đó là TCP throughput lí thuyết dưới điều kiện giả định, cả 2 client ở Chicago và Japan sẽ không thể đạt tới 45Mbps. Do đó, cả 2 chỉ sử dụng tới 37% và 5.6% của bandwidth.

Vậy, với trường hợp thứ nhất (37%) sẽ có thể có 3 client cùng sử dụng chuyển dữ liệu mà không xảy ra overutilization, với trường hợp thứ hai (5.6%) có thể lên đến 17.5 client.

Đến đây có một số bạn sẽ thắc mắc rằng: tại sao lại lấy tcp window chia cho rtt. Mình sẽ có một bài viết sao giải thích tại sao tcp window và tính quan trong của nó.

Friday 3 October 2014

[GoLang] Warm up for newbies

Rãnh rỗi gần mấy tháng rồi, ngồi đánh Dota hoài cũng chán, nên đua đòi tập tành viết code, đọc GO được gần một tháng rồi mà chưa làm được gì! Buồn thiệt chứ :D

Quyết tâm dâng cao, hôm nay viết một bài giới thiệu về GOLang.

Go go go go!

Tại sao lại là go? - Nói thật mình cũng chả quan tâm nhiều đến nó sẽ làm được gì (performance, concurrency, garbage collection …). Ấn tượng đầu tiên cú pháp khá giống Python (thấy thích rồi - dễ đọc), đọc document một hồi lại thấy giống giống C (thích nữa nha - mặc dù trình độ viết C của mình like shit), lí do cuối cùng là của anh google (chắc là sẽ ngon đây). OK, quất thôi.

Mình đang sử dụng OS là Ubuntu 14.04 LTS, IDE là liteide.

Cài đặt GoLang và IDE

Thật ra cái này nó hướng dẫn chi tiết dữ lắm luôn rồi, bạn nào biết tiếng Anh chút xíu cũng có thể cài đặt ở đây
Vào trang này down bản go mới nhất phù hợp với OS của mình nha.

duym@local:~$ wget https://storage.googleapis.com/golang/go1.3.3.linux-amd64.tar.gz
duym@local:~$ tar xvfz go1.3.3.linux-amd64.tar.gz

Rồi, để đó, bây giờ ta sẽ cài liteide
Vào đây down về bản mới nhất về rồi giải nén.

duym@local:~$ tar xvfj liteidex23.2.linux-64.tar.bz2

Xong, có compiler, có ide rồi, bây giờ cấu hình chút xíu nhìn cho nó chuyên nghiệp nào :)
Tạo một workspace để lưu các project ta sẽ thực hiện sau này.

duym@local:~$ mkdir go_repo
duym@local:~$ cd go_repo
duym@local:~/go_repo$ mkdir src pkg src bin

Chúng ta tạo ra 3 thư mục: src, pkg, bin. Tại sao?
+ src: chứa source file (.go, .c, .g, .s) của các project chúng ta sẽ thực hiện sau này
+ pkg: chứa compiled file .a (hiểu nôm na như library, ok?)
+ bin: chưa file thực thi

Tùy chỉnh biến môi trường, ta sẽ edit file $HOME/.bashrc (ở đây mình sử dụng Ubuntu, các bạn sử dụng OS khác thì tự mò nhá, mò không ra thì mailcho mình)

export GOPATH=$HOME/go_repo
export GOBIN=$GOPATH/bin
export GOROOT=$HOME/go
export PATH=$PATH:$GOROOT/bin:$HOME/liteide/bin

Lưu lại và refresh lại biến môi trường nào.

duym@local:~$ . .bashrc

Check lại xem nào:
duym@local:~/$ go env
GOARCH="amd64"
GOBIN="/home/duym/go_repo/bin"
GOCHAR="6"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/duym/go_repo"
GORACE=""
GOROOT="/home/duym/go"
GOTOOLDIR="/home/duym/go/pkg/tool/linux_amd64"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0"
CXX="g++"
CGO_ENABLED="1"

Ngon, nhưng dừng lại giải thích các biến môi trường phía trên chút xíu:
- GOPATH: là workspace mà chúng ta lúc nãy đã tạo (có chứa thư mục: src, bin, pkg)
- GOBIN: nơi lưu các file excute, sau khi đã build từ src và pkg
- GOROOT: thư mục cài đặt Go

OK, bây giờ chạy liteide lên và “hello world” nào :D

duym@local:~$ liteide &

Sorry all, đáng lẽ tới bước này thì mình sẽ chụp hình cho các bạn trực quan hơn, nhưng mà mình lười quá :D nên mình sẽ post clip hướng dẫn “chạy helloworld” link này nha.

Thursday 2 October 2014

Using Two Factor Google Authenticator

Với gmail hay hotmail, hiện tại, đã hỗ trợ sử dụng xác thực 2 bước để login.
Hôm nay mình sẽ hướng dẫn mọi người sử dụng google authenticator để tạo xác thực 2 bước trên desktop hay ssh trên Linux.
2 bước xác thực là gì? Là hành động yêu cầu xác nhận danh tính của người sử dụng thông qua 2 bước:
 + bước 1: mặc định là password (có thể đổi thành key)
 + bước 2: sử dụng 1 chuỗi số được tạo ra từ google authenticator app (theo thuật toán TOTP - Time-based One-Time Password)

Yêu cầu đầu tiên chúng ta phải có smartphone :) Hướng dẫn cài đặt google authenticator lên smart phone Install Google Authenticator

1. Cài đặt
CentOS
# sudo yum install google-authenticator

Ubuntu
# sudo apt-get install libpam-google-authenticator

2. Cấu hình

# google-authenticator

Trên màn hình console sẽ hiện ra một bản QRCode, chúng ta sử dụng điện thoại đã cài đặt authenticator lúc nãy, quét QRCode này.( OK, bây giờ chúng ta đã có được password để xác thực ở bước 2)

Đây là các câu hỏi sẽ hiện ra cùng với QRCode để chúng ta có thể tăng tính bảo mật hơn. Đề nghị các bạn nên gõ y (yes) và Enter hết :D
Do you want me to update your "/home/duym/.google_authenticator" file (y/n) y
=> Nơi lưu trữ secret key và các thông số cấu hình.
Do you want to disallow multiple uses of the same authentication token? This restricts you to one login about every 30s, but it increases your chances to notice or even prevent man-in-the-middle attacks (y/n) y
=> Bạn có cho phép tắt việc sử dụng nhiều lần cho cùng 1 token hay không.
By default, tokens are good for 30 seconds and in order to compensate for possible time-skew between the client and the server, we allow an extra token before and after the current time. If you experience problems with poor time synchronization, you can increase the window from its default size of 1:30min to about 4min. Do you want to do so (y/n) y
=> Bạn có muốn tăng thời gian khả dụng của token hay không? Mặc định là 1p30s, ở đây nếu trả lời là yes thì thời gian đó sẽ tăng lên thành 4phút
If the computer that you are logging into isn't hardened against brute-force login attempts, you can enable rate-limiting for the authentication module. By default, this limits attackers to no more than 3 login attempts every 30s. Do you want to enable rate-limiting (y/n) y
=> Bạn có muốn bật chức năng giới hạn số lần login lên không? Ở đây là 3 lần trong 30s.

Zậy là xong. Ta sẽ thực hiện cấu hình server/desktop để có thể sử dụng được chức năng này.

Cấu hình cho sshd có thể sử dụng chức năng này, ta thực hiện:
# sudo echo "auth required pam_google_authenticator.so" >> /etc/pam.d/sshd
Edit file /etc/ssh/sshd_config
# ChallengeResponseAuthentication yes
Restart lại ssh service
# sudo service ssh restart

Cấu hình cho desktop sử dụng chức năng này:
Ubuntu:
# sudo echo "auth required pam_google_authenticator.so" >> /etc/pam.d/lightdm
# sudo echo "auth required pam_google_authenticator.so" >> /etc/pam.d/gnome-screensaver

Fedora:
# sudo echo "auth required pam_google_authenticator.so" >> /etc/pam.d/gdm-password

OK. Xong! Bây giờ là test lại:
# ssh localhost
Password:
Verification code:
Welcome to Ubuntu 14.04.1 LTS (GNU/Linux 3.13.0-37-generic x86_64)

Have fun.