Còn về việc dùng MySQL bên trong các container Docker, thì đó là một sự kết hợp hoàn hảo trên mây. Nếu bạn từng làm việc với Docker, mọi lợi ích của nó cũng áp dụng cho các container MySQL:
- Cô lập và nhất quán: phiên bản MySQL sẽ được cô lập khỏi phần mềm và phụ thuộc khác, tránh xung đột tiềm ẩn
- Kiểm soát phiên bản: Docker cho phép bạn quản lý phiên bản toàn bộ ngăn xếp phần mềm cùng với MySQL. Điều này giúp tái tạo môi trường bất cứ lúc nào, thuận tiện cho phát triển và kiểm thử.
- Mở rộng và quản lý tài nguyên: Với Docker, bạn có thể mở rộng ứng dụng MySQL bằng cách cấp phát thêm tài nguyên như bộ nhớ hoặc CPU.
- Quản lý phụ thuộc: Docker đóng gói phiên bản MySQL của bạn, cho phép quản lý nhiều phiên bản khác nhau mà không gây ảnh hưởng tới máy cục bộ.
Quan trọng nhất là ứng dụng MySQL của bạn sẽ chạy ở bất cứ đâu, không chỉ trên máy của bạn.
Nếu bạn muốn so sánh MySQL với đối thủ phổ biến thứ hai, hãy xem bài so sánh chi tiết PostgreSQL vs. MySQL của chúng tôi.
Hôm nay, bạn sẽ học các kiến thức nền tảng để chạy MySQL song song với Docker. Bắt đầu thôi!
Yêu cầu tiên quyết
Vì bài viết này tập trung vào các container MySQL trên Docker, bạn cần đáp ứng một vài điều kiện để theo dõi:
- Truy cập dòng lệnh/terminal: bạn cần một môi trường cục bộ có truy cập terminal. Nếu đang ở môi trường Jupyter như Colab, vui lòng chuyển sang môi trường khác.
- Một phiên bản Docker đang chạy: bạn nên cài sẵn Docker Desktop (hướng dẫn trong hướng dẫn Docker cho Khoa học dữ liệu của chúng tôi). Khi hoạt động đầy đủ, góc dưới bên trái giao diện sẽ có biểu tượng cá voi con màu xanh lá:

và lệnh docker --help chạy không lỗi trên terminal.
- Hiểu biết cơ bản về Docker: mặc dù tôi sẽ giải thích mọi lệnh dùng trong bài, việc nắm cơ bản về Docker sẽ giúp bạn tận dụng bài viết tốt hơn nhiều.
- SQL: tương tự cho SQL — tôi sẽ không giải thích các lệnh SQL dùng trong bài vì sẽ lệch khỏi chủ đề chính. Nếu kỹ năng SQL của bạn hơi mai một, có thể ôn lại các chủ đề quan trọng trong khóa học này.
Tải Docker Image MySQL chính thức
Chúng ta sẽ bắt đầu bằng cách tải Docker image MySQL chính thức với lệnh sau:
$ docker pull mysql:latest
docker pull cần tên và phiên bản của image theo cú pháp image:version. Dùng từ khóa latest sẽ tải bản phát hành ổn định mới nhất.
Nếu bạn truy cập trang image MySQL chính thức trên Docker Hub, bạn sẽ thấy nhiều phiên bản khác nhau cho các mục đích khác nhau.

Dưới đây là cách tải v8.2, ví dụ:
$ docker pull mysql:8.2
Sau khi tải image, nó sẽ xuất hiện trong danh sách các Docker image hiện có:

Liệt kê các Docker image cũng có thể thực hiện qua terminal:
$ docker images

Ghi nhớ: Docker image là bản thiết kế (blueprint) để dựng container. Cũng như bản thiết kế cho phép bạn xây một ngôi nhà, Docker image chứa mọi hướng dẫn và thành phần cần thiết để tạo một phiên bản đang chạy của ứng dụng hoặc dịch vụ.
Nếu bạn quen với Lập trình Hướng đối tượng (OOP), hãy coi Docker image như các lớp (class). Từ một class, bạn có thể tạo nhiều đối tượng; tương tự, từ một Docker image, bạn có thể tạo nhiều container.
Chạy và quản lý một container máy chủ MySQL
Giờ hãy tạo container đầu tiên từ image mysql. Đây là lệnh chúng ta sẽ dùng:
$ docker run --name test-mysql -e MYSQL_ROOT_PASSWORD=strong_password -d mysql
run: tạo một container mới hoặc khởi động một container đã có--name CONTAINER_NAME: đặt tên cho container. Tên nên ngắn gọn, dễ đọc. Ở đây làtest-mysql.-e ENV_VARIABLE=value: thẻ -e tạo biến môi trường khả dụng trong container. Việc đặtMYSQL_ROOT_PASSWORDlà bắt buộc để sau này có thể chạy lệnh SQL từ container. Hãy lưu mật khẩu mạnh của bạn ở nơi an toàn (đừng chỉ nhớ trong đầu).-d: viết tắt của detached, thẻ-dgiúp container chạy nền. Nếu bỏ thẻ này, lệnh sẽ in log liên tục cho đến khi container dừng.image_name: đối số cuối cùng là tên image dùng để tạo container. Ở đây làmysql.
Nếu lệnh trả về một chuỗi dài khó hiểu (ID container), nghĩa là container đã khởi động. Bạn có thể kiểm tra trạng thái bằng docker ps:

Ghi nhớ: Docker container là một trình mô phỏng hệ điều hành mạnh mẽ. Ngoài chạy MySQL, bạn có thể thực hiện bất kỳ tác vụ nào thường làm với terminal của máy tính ngay bên trong container.
Để truy cập terminal bên trong container, bạn có thể dùng lệnh sau:
$ docker exec -it container_name bash
Lệnh này sẽ mở một phiên bash.
Kết nối nội bộ tới container máy chủ MySQL
Mọi container MySQL đều khởi chạy một máy chủ MySQL bao gồm mọi thứ để tạo và quản lý cơ sở dữ liệu bằng SQL. Để kết nối tới máy chủ, container cũng kèm một trình khách MySQL cho phép chúng ta chạy truy vấn SQL. Trình khách thực chất là tên gọi khác của lệnh terminal mysql. Hãy dùng nó bên trong terminal của test-mysql:
1. Mở terminal bash của test-mysql:
$ docker exec -it test-mysql bash
2. Kết nối tới client với tư cách người dùng root:
$ mysql -u root -p
Enter password: ...
mysql>
Chúng ta dùng thẻ -u để chỉ định tên người dùng (root) và thêm thẻ -p để nhập mật khẩu khi được nhắc.

Bạn cũng có thể kết nối tới máy chủ MySQL từ bên ngoài container. Ví dụ, để kết nối từ máy chủ (host), bạn có thể cài trình khách MySQL thủ công trên hệ thống của mình.
Để cài MySQL và client của nó trên Windows, bạn có thể làm theo hướng dẫn từ tài liệu cài đặt MySQL chính thức.
Với Mac, bạn có thể dùng Homebrew:
$ brew install mysql
Với Linux hoặc WSL2 (lựa chọn của tôi), bạn có thể dùng sudo:
$ sudo apt update
$ sudo apt install mysql-client
Sau khi cài đặt, nếu container đang chạy, hãy dừng và xóa nó:
$ docker stop test-mysql
test-mysql
$ docker rm test-mysql
Tiếp theo, chúng ta sẽ khởi động lại container bằng cách ánh xạ một cổng từ container sang một cổng trên máy cục bộ:
$ docker run -d --name test-mysql -e MYSQL_ROOT_PASSWORD=strong_password -p 3307:3306 mysql
Lệnh này thực hiện như sau:
-p 3307:3306: Ánh xạ cổng 3306 của container (cổng mặc định của MySQL) sang cổng 3307 trên máy cục bộ. Tức là mọi lưu lượng gửi tới cổng 3307 cục bộ sẽ được chuyển tiếp đến cổng 3306 của container và máy chủ MySQL sẽ truy cập được qua cổng đó.-d: Tiếp tục chạy container ở chế độ nền.--name test-mysql: Tái sử dụng tên container "test-mysql".-e MYSQL_ROOT_PASSWORD=strong_password: Đặt lại mật khẩu root cho máy chủ MySQL.mysql: Chỉ định Docker image sẽ chạy, là image MySQL chính thức.
Sau khi terminal in ra một ID container mới, chúng ta có thể kiểm tra ánh xạ cổng:
$ docker port test-mysql
3306/tcp -> 0.0.0.0:3307
Đã thành công! Giờ đây, từ máy cục bộ, bạn có thể kết nối tới máy chủ trên cổng 3307 bằng client mysql:
$ mysql --host=127.0.0.1 --port=3307 -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.2.0 MySQL Community Server - GPL
Copyright (c) 2000, 2023, Oracle and/or its affiliates…
Cấu hình container MySQL
Bạn có thể cấu hình container MySQL cho rất nhiều thiết lập bằng một tệp cấu hình. Thông thường, tệp sẽ được lưu trong một trong các thư mục sau của container:
/etc/mysql//etc/mysql/conf.d/etc/mysql/mysql.conf.d
Các thư mục có thể thay đổi theo image. Nhưng tên và phần mở rộng tiêu chuẩn cho tệp cấu hình là my.cnf. Nếu tệp không tồn tại trong bất kỳ thư mục nào ở trên, điều đó nghĩa là container yêu cầu một tệp cấu hình tùy chỉnh. Đây là trường hợp của container test-mysql của chúng ta:
$ ls /etc/mysql/conf.d/ # Returns no output
Trong những tình huống như vậy, chúng ta cần làm các bước cẩn thận sau:
1. Dừng và xóa container:
$ docker stop test-mysql; docker rm test-mysql
2. Tạo một tệp cấu hình trống ở máy cục bộ (trên máy của bạn):
$ sudo mkdir -p /etc/docker/test-mysql # Tạo thư mục
$ sudo touch /etc/docker/test-mysql/my.cnf # Tạo tệp cấu hình trong thư mục
3. Khởi động lại container bằng cách liên kết hai tệp .cnf trống:
$ docker run \
--name test-mysql \
-v /etc/docker/test-mysql:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=strong_password \
-d mysql
Chúng ta đang dùng một thẻ mới: -v, viết tắt của volume. Thẻ này dùng để liên kết thư mục giữa container và máy cục bộ. Trong ngôn ngữ khoa học máy tính, quá trình này gọi là gắn kết (mount).
Vì vậy, trong lệnh trên, chúng ta đang gắn thư mục cục bộ /etc/docker/test-mysql vào thư mục /etc/mysql/conf.d của container. Điều này sẽ liên kết nội dung của cả hai thư mục. Mọi thay đổi ở bất kỳ thư mục nào cũng sẽ được phản ánh ở cả hai.
Việc gắn kết cho phép chúng ta chỉnh sửa tệp my.cnf trên máy cục bộ để thay đổi cấu hình của các container Docker. Và điểm hay nhất là các cấu hình đã chỉnh sửa sẽ tồn tại trên máy cục bộ ngay cả khi container bị dừng hoặc xóa. Có thể tái sử dụng được.
Vậy sau bước này, chúng ta có thể thay đổi những cấu hình gì? Câu trả lời phụ thuộc vào trường hợp sử dụng của bạn. Chúng ta sẽ đề cập bên dưới.
Bạn muốn được chứng nhận Docker? Hãy xem hướng dẫn của chúng tôi về chứng chỉ Docker!
Nên cấu hình những tùy chọn nào?
Trong khi cấu hình mặc định của container MySQL phù hợp với nhiều kịch bản phổ biến, bạn nên điều chỉnh một số thiết lập để tối ưu hiệu năng, bảo mật và sử dụng tài nguyên. Dưới đây là các tùy chọn thường được thay đổi:
Hiệu năng
- innodb_buffer_pool_size: Xác định lượng bộ nhớ cấp cho buffer pool của InnoDB, nơi lưu đệm dữ liệu truy cập thường xuyên để lấy nhanh hơn. Tăng giá trị này có thể cải thiện hiệu năng cho khối lượng công việc đọc nặng, nhưng cũng tốn thêm bộ nhớ.
- query_cache_size: Kiểm soát kích thước bộ nhớ đệm truy vấn, nơi lưu các truy vấn đã chạy để thực thi lại nhanh hơn. Tăng giá trị có thể cải thiện hiệu năng với truy vấn lặp lại, nhưng cũng tốn thêm bộ nhớ và có thể không hiệu quả với truy vấn động.
- thread_pool_size: Xác định số lượng kết nối đồng thời tối đa mà máy chủ có thể xử lý. Điều chỉnh theo tải lưu lượng dự kiến có thể tối ưu sử dụng tài nguyên và tránh nút thắt cổ chai.
Bảo mật
- bind-address: Giới hạn máy chủ MySQL chỉ lắng nghe trên các giao diện mạng cụ thể, hạn chế truy cập từ nguồn không được phép.
- mysql_bind_host: Cho phép bind máy chủ MySQL vào các địa chỉ IP cụ thể thay vì lắng nghe trên mọi giao diện.
- validate_password_policy: Bật các yêu cầu mật khẩu nghiêm ngặt hơn để tăng bảo mật.
Sử dụng tài nguyên
- max_connections: Kiểm soát số kết nối đồng thời tối đa được phép. Điều chỉnh giá trị này có thể ngăn cạn kiệt tài nguyên và đảm bảo máy chủ vận hành hiệu quả.
- innodb_file_per_table: Lưu mỗi bảng InnoDB trong một tệp riêng, có thể cải thiện hiệu năng nhưng tăng nhu cầu lưu trữ.
- innodb_io_capacity: Đặt IOPS ước tính cho hệ thống lưu trữ, giúp bộ máy tối ưu việc dùng buffer pool và thao tác đĩa.
Các chỉnh sửa phổ biến khác
- character_set_server: Đặt bộ mã ký tự mặc định cho máy chủ, đảm bảo mã hóa và xử lý dữ liệu nhất quán.
- collation_server: Xác định quy tắc đối chiếu mặc định dùng để sắp xếp và so sánh dữ liệu ký tự.
- log_bin: Bật ghi log nhị phân hoạt động của máy chủ, hữu ích cho khắc phục sự cố và sao chép.
Để xem danh sách đầy đủ các tùy chọn cấu hình, bạn có thể chạy lệnh sau:
$ docker run -it --rm mysql:tag --verbose --help
Bạn có thể chỉnh sửa tệp .cnf bằng bất kỳ trình soạn thảo văn bản nào. Đây là cú pháp cần theo:
[mysqld]
max_connections=200
other_params=value
...
Cách lưu giữ dữ liệu trong container MySQL trên Docker
Lưu bền dữ liệu trong các container MySQL rất quan trọng vì nhiều lý do:
- Tính bền dữ liệu: Khi bạn dừng hoặc xóa container, toàn bộ dữ liệu sẽ mất, bao gồm cả cơ sở dữ liệu. Tách dữ liệu khỏi container giúp luôn truy cập được.
- Chia sẻ dữ liệu giữa các container: Tách dữ liệu khỏi container cho phép nhiều container truy cập. Cách này tránh trùng lặp dữ liệu và đơn giản hóa đồng bộ giữa các dự án dùng chung dữ liệu.
- Di động và sao lưu: dữ liệu được lưu bền có thể dễ dàng sao lưu và chia sẻ độc lập, giúp khôi phục đáng tin cậy khi mất dữ liệu hoặc xóa nhầm.
- Cải thiện hiệu năng và khả năng mở rộng: Bằng cách lưu dữ liệu truy cập thường xuyên lên bộ nhớ bền như SSD, bạn có thể cải thiện hiệu năng ứng dụng so với dựa vào lớp ghi của container, vốn thường chậm hơn.
Quy trình cũng giống như ta đã thấy — chúng ta sẽ tạo một volume và gắn nó vào nơi dữ liệu được lưu trong container. Các bước như sau:
1. Tạo một volume:
$ docker volume create test-mysql-data
Lệnh volume create tạo một vùng lưu trữ dành riêng trên hệ thống tệp cục bộ cho volume. Sau khi gắn volume, toàn bộ dữ liệu container sẽ liên kết với nó.
2. Khởi động lại container với volume đã gắn:
$ docker stop test-mysql; docker rm test-mysql
$ docker run \
--name test-mysql \
-v test-mysql-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=strong_password \
-d mysql
Lần này, cú pháp có dạng: -v volume_name:directory_in_container. Tất cả volume tạo ra nên được gắn vào thư mục /var/lib/mysql như tài liệu image MySQL chỉ định.
Vì vậy, giờ đây mọi cơ sở dữ liệu hoặc bảng được tạo trong test-mysql sẽ được lưu bền cục bộ, ngay cả khi container bị dừng hoặc xóa.
Lệnh cuối cùng
Xuyên suốt bài viết, lệnh docker run của chúng ta đã thay đổi đáng kể. Hãy tổng hợp mọi biến thể vào một lệnh tổng cuối cùng. Chúng ta cần dừng và xóa container một lần nữa. Ta cũng sẽ xóa volume để bắt đầu lại từ đầu:
$ docker stop test-mysql; docker rm test-mysql
$ docker volume rm test-mysql-data
Đây là lệnh tổng cuối cùng:
$ docker run \
--name final-mysql \
-e MYSQL_ROOT_PASSWORD=strong_password \
-p 3307:3306 \
-v /etc/docker/test-mysql:/etc/mysql/conf.d \
-v final-mysql-data:/var/lib/mysql \
-d mysql
Lệnh này gắn tệp my.cnf cục bộ trước đó của chúng ta vào vị trí mong muốn đồng thời tạo một volume mới tên final-mysql-data và gắn nó.
Quản lý thiết lập MySQL phức tạp với Docker Compose
Với các thiết lập nâng cao liên quan nhiều container, chẳng hạn chạy MySQL cùng các dịch vụ khác (ví dụ máy chủ web hoặc backend ứng dụng), Docker Compose đơn giản hóa quy trình bằng cách cho phép bạn định nghĩa và quản lý các ứng dụng đa container chỉ với một tệp cấu hình.
Dưới đây là ví dụ cơ bản về tệp docker-compose.yml cho một container MySQL:
version: '3.9'
services:
db:
image: mysql:8.3.0
container_name: mysql-db
environment:
MYSQL_ROOT_PASSWORD: strong_password
MYSQL_DATABASE: example_db
MYSQL_USER: user
MYSQL_PASSWORD: user_password
ports:
- "3306:3306"
volumes:
- db_data:/var/lib/mysql
- ./mysql-config:/etc/mysql/conf.d
volumes:
db_data:
Các bước sử dụng Docker Compose:
- Tạo tệp
docker-compose.yml: Lưu tệp cấu hình trong thư mục dự án của bạn. - Khởi động các dịch vụ: Chạy lệnh sau để khởi động tất cả dịch vụ được định nghĩa trong tệp:
docker-compose up -d
- Dừng các dịch vụ: Tắt các dịch vụ khi hoàn tất:
docker-compose down
Lợi ích của Docker Compose cho MySQL:
- Đơn giản hóa cấu hình: Quản lý cấu hình MySQL, cổng và volume trong một tệp duy nhất.
- Dễ mở rộng: Dễ dàng mở rộng cơ sở dữ liệu hoặc tích hợp với các dịch vụ khác trong ngăn xếp ứng dụng của bạn.
- Dữ liệu bền vững: Tự động quản lý volume để duy trì dữ liệu qua các lần khởi động lại container.
Sử dụng Docker Compose đặc biệt hữu ích khi quản lý nhiều môi trường (ví dụ phát triển, staging và sản xuất) hoặc khi cộng tác theo nhóm.
Kết luận
Bài viết đã bao quát những khía cạnh thiết yếu của việc chạy và quản lý cơ sở dữ liệu MySQL bên trong các container Docker. Chúng ta đã học cách tải và thiết lập image MySQL, khởi động máy chủ MySQL trong container, cách chỉnh sửa các container đó và thêm volume cho cấu hình tùy chỉnh cũng như lưu bền dữ liệu.
Để tìm hiểu thêm, tôi gợi ý các tài nguyên sau:
- Giới thiệu về Docker cho khoa học dữ liệu
- Khóa học Giới thiệu về Docker
- Container hóa Docker và Kubernetes cho machine learning
- Tài liệu Image MySQL trên Docker
- Sổ tay tham khảo MySQL
Cảm ơn bạn đã đọc!
FAQs
Tôi có thể dùng Docker Compose để quản lý nhiều container MySQL không?
Có. Docker Compose là công cụ tuyệt vời để quản lý nhiều container Docker, bao gồm cả MySQL. Bạn có thể định nghĩa cấu hình dịch vụ MySQL trong tệp docker-compose.yml, cho phép bạn khởi động, dừng và quản lý nhiều dịch vụ chỉ với một lệnh.
Làm thế nào để nâng cấp MySQL lên phiên bản mới hơn trong Docker container?
Để nâng cấp MySQL trong Docker container, bạn cần pull phiên bản MySQL Docker image mới và sau đó tạo lại container của bạn với image mới này. Hãy đảm bảo có bản sao lưu dữ liệu trước khi tiến hành nâng cấp.
Tôi có thể chạy nhiều container MySQL trên cùng một host không?
Có, bạn có thể chạy nhiều container MySQL trên cùng một máy chủ. Mỗi container phải được gán một cổng riêng trên host bằng tùy chọn -p để tránh xung đột cổng.
Những thực hành bảo mật tốt nhất khi chạy các container MySQL là gì?
Thực hành bảo mật tốt bao gồm không phơi bày container MySQL ra internet công cộng nếu không có biện pháp bảo mật phù hợp, sử dụng mật khẩu mạnh, thường xuyên cập nhật Docker và MySQL image, và dùng Docker secrets cho thông tin nhạy cảm như mật khẩu.
Làm sao tôi có thể tự động hóa việc sao lưu cơ sở dữ liệu MySQL trong Docker?
Bạn có thể tự động hóa sao lưu bằng cách tạo cron job trên máy host dùng docker exec để chạy mysqldump bên trong container. Ngoài ra, bạn có thể dùng Docker volume để lưu bền dữ liệu và xử lý sao lưu trực tiếp từ host.
Tôi có thể kết nối tới container MySQL từ một container khác không?
Có, bạn có thể kết nối từ một container khác bằng cách đảm bảo cả hai container ở cùng một mạng Docker. Bạn có thể dùng tên container làm hostname khi kết nối.
Làm sao khắc phục sự cố kết nối với container MySQL của tôi?
Khắc phục sự cố kết nối bằng cách kiểm tra container có đang chạy không (docker ps), xác minh ánh xạ cổng (docker port), kiểm tra cấu hình mạng và đảm bảo máy chủ MySQL bên trong container được cấu hình để chấp nhận kết nối từ host của bạn hoặc từ các container khác.
Có thể dùng tệp cấu hình MySQL tùy chỉnh mà không cần gắn từ host không?
Có thể tạo tệp cấu hình tùy chỉnh ngay trong container. Tuy nhiên, phổ biến hơn là gắn (mount) từ host để dễ quản lý và đảm bảo tính bền vững.
Làm sao tôi có thể theo dõi hiệu năng của container MySQL?
Bạn có thể theo dõi hiệu năng bằng các công cụ như mysqladmin cho các số đo chuyên biệt MySQL, lệnh stats tích hợp của Docker (docker stats), hoặc các giải pháp giám sát bên thứ ba như Prometheus với các exporter cho Docker và MySQL.
Tôi nên làm gì nếu container MySQL của tôi bị crash?
Nếu container của bạn bị crash, đầu tiên hãy kiểm tra log bằng docker logs <container_name> để xác định lỗi. Đảm bảo cấu hình và biến môi trường chính xác, và kiểm tra không có giới hạn tài nguyên (CPU, bộ nhớ). Khởi động lại container và theo dõi hiệu năng của nó.

Tôi là người sáng tạo nội dung về khoa học dữ liệu với hơn 2 năm kinh nghiệm và là một trong những tài khoản có lượng người theo dõi lớn nhất trên Medium. Tôi thích viết các bài chuyên sâu về AI và ML với chút giọng điệu mỉa mai, vì bạn cũng phải làm gì đó để chúng bớt khô khan. Tôi đã xuất bản hơn 130 bài viết và một khóa học trên DataCamp, cùng với một khóa nữa đang được thực hiện. Nội dung của tôi đã được hơn 5 triệu lượt xem, trong đó 20 nghìn người đã trở thành người theo dõi trên cả Medium và LinkedIn.
MySQL là công cụ cơ sở dữ liệu quan hệ phổ biến nhất, với thị phần hơn 40%. So với các đối thủ như PostgreSQL (16%) và Oracle Database (11%), các con số của MySQL trông rất ấn tượng.
MySQL phổ biến vì vừa đơn giản vừa mạnh mẽ. Dưới đây là những điểm nổi bật: