Thread Pools có thể làm gì?
Theo truyền thống, MySQL đã gán một Thread cho mọi kết nối client và khi số lượng user đồng thời tăng lên, mô hình này cho thấy hiệu suất giảm. Nhiều luồng hoạt động sẽ giết hiệu năng, bởi vì việc tăng số lượng Thread dẫn đến chuyển đổi ngữ cảnh xấu cho bộ nhớ CPU và tăng sự tranh chấp đối với các khóa nóng. Một giải pháp lý tưởng sẽ giúp giảm chuyển đổi ngữ cảnh là duy trì số lượng Thread thấp hơn số lượng user. Nhưng con số này cũng không nên quá thấp, vì chúng ta cũng muốn sử dụng CPU hết mức, vì vậy lý tưởng nhất là phải có một Thread hoạt động duy nhất cho mỗi CPU trên máy.
Các tính năng của MariaDB Thread Pool
Bắt đầu từ MariaDB 5.5 triển khai một nhóm dynamic/adaptive pool, tự nó sẽ đảm nhiệm việc tạo ra các Thread mới trong thời điểm có nhu cầu cao và giảm bớt Thread khi không có nhu cầu hoạt động.
Đây là cách hoạt động kết thừa từ thông số pool-of-threads, với các mục tiêu sau:
- Làm cho pool có thể linh động, để nó sẽ phát triển và co lại bất cứ khi nào cần thiết.
- Giảm thiểu lượng chi phí cần thiết để duy trì Thread Pool.
- Tận dụng tốt nhất các khả năng của hệ điều hành cơ bản. Ví dụ, nếu triển khai Thread Pool có thể hoạt động, thì nó được sử dụng và nếu không, thì nên sử dụng phương pháp ghép kênh I/O mặc định sẽ được sử dụng.
- Giới hạn các tài nguyên được sử dụng bởi các Thread.
Khi nào sử dụng Thread Pool
Thread Pool hiệu quả nhất trong các tình huống trong đó các truy vấn tương đối ngắn và tải bị ràng buộc bởi CPU, chẳng hạn như trong khối lượng công việc OLTP(Online Transaction Processing). Nếu khối lượng công việc không bị ràng buộc bởi CPU, thì bạn vẫn có thể hưởng lợi từ việc giới hạn số lượng luồng để tiết kiệm bộ nhớ ram cho database memory buffers(bộ nhớ đệm trên ram)
Khi nào Thread Pool sẽ kém hiệu quả
Có những trường hợp đặc biệt, hiếm gặp trong đó Thread Pool kém hiệu như sau
- Nếu bạn có khối lượng công việc rất lớn , thì Thread Pool có thể không hoạt động tốt cho bạn. Điển hình trong ví dụ này là rất nhiều công việc dẫn đến nhiều Thread gây ra bởi nhiều user tuy nhiên thời gian user sử dụng rất ngắn dẫn đến việc các Thread mở ra và đã phục vụ xong công việc nhưng không được đóng bớt Thread.Trong tình huống này, hiệu suất có thể được cải thiện bằng cách điều chỉnh giảm các Thread không sử dụng. Ví dụ: với thread_pool_idle_timeout
- Nếu bạn có nhiều truy vấn đồng thời, dài, không cho năng suất , thì Thread Pool không hoạt động tốt cho bạn. Có nghĩa là nhiều truy vấn hoạt động với thời gian dài sẽ chiếm hết các Thread trong Thread Pool làm cho các truy vấn sau phải chờ xử lý. Tuy nhiên, Thread Pool đã có thể phát hiện để ngăn chặn chúng hoàn toàn độc quyền hoạt động trên Thread Pool bằng biến hệ thống thread_pool_stall_limit
- Nếu bạn dựa vào thực tế là các truy vấn đơn giản luôn kết thúc nhanh chóng , bất kể máy chủ cơ sở dữ liệu của bạn được tải như thế nào, thì Thread Pool có thể không hoạt động tốt cho bạn. Khi Thread Pool được bật trên máy chủ có có tải cao, vượt quá tài nguyên có sẵn. Điều này có nghĩa là ngay cả khi bản thân câu lệnh không mất nhiều thời gian để thực thi, thậm chí đơn giản như các câu lệnh đơn giản “SELECT 1” có thể mất nhiều thời gian hơn khi Thread Pool được kích hoạt so với one-thread-per-connection khi nó được xếp hàng.
Cấu hình Thread Pool trên hệ thống Unix
Biến thread_handling là biến hệ thống chính được sử dụng để cấu hình Thread Pool.
Bạn có thể thêm cấu hình sau vào file my.cnf và khởi động lại MariaDB để kích hoạt.
[mariadb] ... thread_handling = pool-of-thread
Các biến hệ thống sau đây cũng có thể được cấu hình trên Unix:
- thread_pool_size – Số lượng thread groups trong Thread Pool, xác định có bao nhiêu câu lệnh có thể thực thi đồng thời. Giá trị mặc định là số lượng CPU trên hệ thống. Đặt giá trị của biến hệ thống này khi khởi động hệ thống, giá trị tối đa có thể đặt là 100000. Việc triển khai Thread Pool sử dụng các đối tượng được gọi là thread groups để phân chia các kết nối máy khách thành nhiều threads độc lập. Biến thread_pool_size xác định số lượng thread groups trên một hệ thống. Nói chung, mục tiêu của việc thực hiện thread group là để có một thread chạy trên mỗi CPU trên hệ thống tại một thời điểm. Do đó, giá trị mặc định của thread_pool_size biến hệ thống có kích thước tự động theo số lượng CPU trên hệ thống. Khi muốn thông số thread groups được thay đổi tự động 1 cách linh hoạt ta không set thông số này quá 128. Như ví dụ dưới đây ta chỉ set 32.
[mariadb] .. thread_handling = pool-of-thread thread_pool_size = 32
- thread_pool_max_threads : Số lượng thread tối đa trong nhóm Thread Pool. Khi đạt đến giới hạn này, sẽ không có thread mới nào được tạo trong hầu hết các trường hợp. Trong các trường hợp hiếm hoi, số lượng thread thực tế có thể vượt quá mức này một chút, bởi vì mỗi Thread Pool cần ít nhất hai thread (tức là ít nhất một worker thread và ít nhất một listener thread). Giá trị mặc định trong MariaDB 5.5 và MariaDB 10.0 là 500. Giá trị mặc định trong MariaDB 10.1 là 1000 trong MariaDB 10.1 . Giá trị mặc định trong MariaDB 10.2 trở lên là 65536.
- thread_pool_stall_limit : Số mili giây giữa mỗi lần kiểm tra hoạt động của các thread được thực hiện bởi thời gian quy định cho mỗi thread(timer thread). Giá trị mặc định là 500. Khi timer thread phát hiện ra rằng một thread group bị đình trệ, nó sẽ đánh thức một worker thread đang ngủ trong thread group, nếu có sẵn một nhóm. Nếu không có cái nào, thì nó tạo ra một luồng công nhân mới trong nhóm luồng nếu có thể. Điều này tạm thời cho phép một số kết nối máy khách trong thread group chạy song song. Tuy nhiên, lưu ý rằng timer thread sẽ không tạo ra worker thread mới nếu số lượng thread trong thread pool đã lớn hơn hoặc bằng mức tối đa được xác định bởi biến hệ thống thread_pool_max_threads, trừ khi thread group chưa có listener thread.
- thread_pool_oversubscribe : Xác định có bao nhiêu worker threads trong một thread group có thể duy trì hoạt động cùng một lúc khi một thread group được đăng ký vượt mức. Giá trị mặc định là 3. Thông thường, một thread group chỉ có một worker thread hoạt động tại một thời điểm. Tuy nhiên, timer thread có thể thêm các worker thread hoạt động nhiều hơn vào một thread group nếu nó phát hiện ra vượt số lương thread quy định . Chỉ cho phép một thread trên mỗi CPU có nghĩa là thread có thể có quyền truy cập không hạn chế vào CPU khi chạy, nhưng điều đó cũng có nghĩa là có thêm chi phí từ việc đưa thread vào chế độ ngủ hoặc đánh thức chúng thường xuyên hơn. Cho phép nhiều hơn một thread trên mỗi CPU có nghĩa là các thread phải chia sẻ CPU, nhưng điều đó cũng có nghĩa là có ít chi phí hơn từ việc đưa các thread vào chế độ ngủ hoặc đánh thức chúng.
- thread_pool_idle_timeout : Số giây trước khi một worker thread rỗi kết thúc. Giá trị mặc định là 60. Nếu hiện tại không có việc gì để làm, một thread nhàn rỗi nên đợi bao lâu trước khi thoát?
Cấu hình lập lịch ưu tiên
Bắt đầu với MariaDB 10.2.2 , có thể định cấu hình mức độ ưu tiên kết nối. Hành vi ưu tiên được cấu hình bởi thread_pool_priority .
Theo mặc định, nếu thread_pool_priority được đặt thành auto, thì các query sẽ được ưu tiên cao hơn trong trường hợp kết nối hiện tại nằm trong một transaction. Điều này cho phép transaction đang chạy kết thúc nhanh hơn và có tác dụng hạ thấp số lượng transaction đang chạy song song. Cài đặt mặc định thường sẽ cải thiện thông lượng cho khối lượng công việc transaction. Nhưng cũng có thể đặt rõ ràng mức độ ưu tiên cho kết nối hiện tại thành ‘cao’ hoặc ‘thấp’.
Ngoài ra còn có một cơ chế để đảm bảo rằng các kết nối ưu tiên cao hơn sẽ không độc quyền các luồng công nhân trong nhóm (điều này sẽ gây ra sự chậm trễ vô thời hạn cho các kết nối ưu tiên thấp). Trên Unix, các kết nối ưu tiên thấp được đưa vào hàng ưu tiên cao sau khi hết thời gian được chỉ định bởi thread_pool_prio_kickup_timer .
Monitoring Thread Pool
Variable | Description |
---|---|
Threadpool_threads | Số lượng thread trong thread pool. Trong các trường hợp hiếm hoi, giá trị này có thể cao hơn một chút thread_pool_max_threads, bởi vì mỗi thread group cần ít nhất hai threads (tức là ít nhất một worker thread và ít nhất một listener thread) để ngăn chặn tắt nghẽn. |
Threadpool_idle_threads | Số lượng thread không hoạt động trong thread pool. Thread trở nên không hoạt động vì nhiều lý do, chẳng hạn như bằng cách chờ đợi công việc mới. Tuy nhiên, một thread không hoạt động không nhất thiết là một thread chưa được phân công công việc. thread cũng được coi là không hoạt động nếu chúng bị chặn trong khi chờ vào I/O trên đĩa hoặc trong khi chờ khóa, v.v. Biến trạng thái này chỉ có ý nghĩa trên Unix . |
Notes.
Các thread_cache_size không được sử dụng khi các thread pool được sử dụng và các Threads_cached sẽ có một giá trị là 0.