Khả năng định hình lưu lượng truy cập vào cơ sở dữ liệu là một trong những khả năng quan trọng nhất. Trong những ngày trước, bạn không có nhiều quyền kiểm soát đối với nó - các ứng dụng đã gửi lưu lượng truy cập đến cơ sở dữ liệu và đó là về nó. HAProxy, vốn thường được sử dụng, cũng không có tùy chọn để kiểm soát chi tiết lưu lượng. Với sự ra đời của các proxy nhận biết SQL, như ProxySQL, đã có nhiều khả năng hơn cho các quản trị viên cơ sở dữ liệu. Hãy cùng xem xét các khả năng xử lý và điều chỉnh kết nối trong ProxySQL.
Xử lý kết nối trong ProxySQL
Như bạn có thể biết, cách thức hoạt động của ProxySQL là thông qua các quy tắc truy vấn. Đó là danh sách các quy tắc mà mọi truy vấn đều được kiểm tra và điều chỉnh chính xác cách ProxySQL sẽ xử lý truy vấn. Bắt đầu từ đầu, ứng dụng kết nối với ProxySQL. Nó sẽ xác thực với ProxySQL (đây là lý do tại sao ProxySQL phải lưu trữ tất cả người dùng và băm mật khẩu) và sau đó ProxySQL sẽ chạy nó thông qua các quy tắc truy vấn để xác định nhóm máy chủ mà truy vấn sẽ được gửi đến.
ProxySQL mở một nhóm kết nối đến các máy chủ phụ trợ. Nó không phải là ánh xạ 1-1, theo mặc định, nó cố gắng sử dụng lại một kết nối phụ trợ cho càng nhiều kết nối frontend càng tốt. Đây được gọi là ghép kênh kết nối. Chi tiết phụ thuộc vào lưu lượng truy cập chính xác mà nó phải xử lý. Mọi giao dịch đang mở phải được xử lý trong cùng một kết nối. Nếu có một số loại biến cục bộ được xác định, kết nối này không thể được sử dụng lại. Việc có thể sử dụng lại kết nối phụ trợ đơn lẻ bởi nhiều kết nối giao diện người dùng làm giảm đáng kể gánh nặng cho cơ sở dữ liệu phụ trợ.
Khi kết nối được thực hiện với ProxySQL, như chúng tôi đã đề cập trước đây, nó sẽ được xử lý theo các quy tắc truy vấn. Tại đây việc định hình giao thông có thể diễn ra. Hãy xem qua các tùy chọn
Điều chỉnh kết nối trong ProxySQL
Đầu tiên, chúng ta hãy bỏ tất cả các CHỌN. Chúng tôi đang chạy “ứng dụng” của mình, Sysbench, theo cách sau:
[email protected]:~# sysbench /root/sysbench/src/lua/oltp_read_only.lua --threads=4 --events=200 --time=0 --mysql-host=10.0.0.101 --mysql-user=sbtest --mysql-password=sbtest --mysql-port=6033 --tables=32 --report-interval=1 --skip-trx=on --table-size=100000 --db-ps-mode=disable --rate=10 run
sysbench 1.1.0-bbee5d5 (using bundled LuaJIT 2.1.0-beta3)
Running the test with following options:
Number of threads: 4
Target transaction rate: 10/sec
Report intermediate results every 1 second(s)
Initializing random number generator from current time
Initializing worker threads...
Threads started!
[ 1s ] thds: 4 tps: 5.97 qps: 103.49 (r/w/o: 103.49/0.00/0.00) lat (ms,95%): 244.38 err/s: 0.00 reconn/s: 0.00
[ 1s ] queue length: 0, concurrency: 4
[ 2s ] thds: 4 tps: 13.02 qps: 181.32 (r/w/o: 181.32/0.00/0.00) lat (ms,95%): 580.02 err/s: 0.00 reconn/s: 0.00
[ 2s ] queue length: 5, concurrency: 4
[ 3s ] thds: 4 tps: 14.99 qps: 228.81 (r/w/o: 228.81/0.00/0.00) lat (ms,95%): 669.89 err/s: 0.00 reconn/s: 0.00
[ 3s ] queue length: 1, concurrency: 4
[ 4s ] thds: 4 tps: 16.99 qps: 232.88 (r/w/o: 232.88/0.00/0.00) lat (ms,95%): 350.33 err/s: 0.00 reconn/s: 0.00
[ 4s ] queue length: 0, concurrency: 3
[ 5s ] thds: 4 tps: 8.99 qps: 99.91 (r/w/o: 99.91/0.00/0.00) lat (ms,95%): 369.77 err/s: 0.00 reconn/s: 0.00
[ 5s ] queue length: 0, concurrency: 1
[ 6s ] thds: 4 tps: 3.99 qps: 55.81 (r/w/o: 55.81/0.00/0.00) lat (ms,95%): 147.61 err/s: 0.00 reconn/s: 0.00
[ 6s ] queue length: 0, concurrency: 1
[ 7s ] thds: 4 tps: 11.06 qps: 162.89 (r/w/o: 162.89/0.00/0.00) lat (ms,95%): 173.58 err/s: 0.00 reconn/s: 0.00
[ 7s ] queue length: 0, concurrency: 2
[ 8s ] thds: 4 tps: 7.99 qps: 112.88 (r/w/o: 112.88/0.00/0.00) lat (ms,95%): 200.47 err/s: 0.00 reconn/s: 0.00
[ 8s ] queue length: 0, concurrency: 2
[ 9s ] thds: 4 tps: 9.01 qps: 110.09 (r/w/o: 110.09/0.00/0.00) lat (ms,95%): 71.83 err/s: 0.00 reconn/s: 0.00
[ 9s ] queue length: 0, concurrency: 0
[ 10s ] thds: 4 tps: 9.99 qps: 143.87 (r/w/o: 143.87/0.00/0.00) lat (ms,95%): 153.02 err/s: 0.00 reconn/s: 0.00
[ 10s ] queue length: 0, concurrency: 1
[ 11s ] thds: 4 tps: 12.02 qps: 177.28 (r/w/o: 177.28/0.00/0.00) lat (ms,95%): 170.48 err/s: 0.00 reconn/s: 0.00
[ 11s ] queue length: 0, concurrency: 1
[ 12s ] thds: 4 tps: 5.00 qps: 70.95 (r/w/o: 70.95/0.00/0.00) lat (ms,95%): 231.53 err/s: 0.00 reconn/s: 0.00
[ 12s ] queue length: 0, concurrency: 2
[ 13s ] thds: 4 tps: 10.00 qps: 137.01 (r/w/o: 137.01/0.00/0.00) lat (ms,95%): 223.34 err/s: 0.00 reconn/s: 0.00
[ 13s ] queue length: 0, concurrency: 1
[ 14s ] thds: 4 tps: 11.01 qps: 143.14 (r/w/o: 143.14/0.00/0.00) lat (ms,95%): 130.13 err/s: 0.00 reconn/s: 0.00
[ 14s ] queue length: 0, concurrency: 0
[ 15s ] thds: 4 tps: 5.00 qps: 100.99 (r/w/o: 100.99/0.00/0.00) lat (ms,95%): 297.92 err/s: 0.00 reconn/s: 0.00
[ 15s ] queue length: 0, concurrency: 4
[ 16s ] thds: 4 tps: 10.98 qps: 122.82 (r/w/o: 122.82/0.00/0.00) lat (ms,95%): 344.08 err/s: 0.00 reconn/s: 0.00
[ 16s ] queue length: 0, concurrency: 0
[ 17s ] thds: 4 tps: 3.00 qps: 59.01 (r/w/o: 59.01/0.00/0.00) lat (ms,95%): 287.38 err/s: 0.00 reconn/s: 0.00
[ 17s ] queue length: 0, concurrency: 2
[ 18s ] thds: 4 tps: 13.01 qps: 165.14 (r/w/o: 165.14/0.00/0.00) lat (ms,95%): 173.58 err/s: 0.00 reconn/s: 0.00
[ 18s ] queue length: 0, concurrency: 0
[ 19s ] thds: 4 tps: 6.99 qps: 98.79 (r/w/o: 98.79/0.00/0.00) lat (ms,95%): 253.35 err/s: 0.00 reconn/s: 0.00
[ 19s ] queue length: 0, concurrency: 1
[ 20s ] thds: 4 tps: 9.98 qps: 164.60 (r/w/o: 164.60/0.00/0.00) lat (ms,95%): 590.56 err/s: 0.00 reconn/s: 0.00
[ 20s ] queue length: 0, concurrency: 3
SQL statistics:
queries performed:
read: 2800
write: 0
other: 0
total: 2800
transactions: 200 (9.64 per sec.)
queries: 2800 (134.89 per sec.)
ignored errors: 0 (0.00 per sec.)
reconnects: 0 (0.00 per sec.)
Throughput:
events/s (eps): 9.6352
time elapsed: 20.7573s
total number of events: 200
Latency (ms):
min: 44.36
avg: 202.66
max: 726.59
95th percentile: 590.56
sum: 40531.73
Threads fairness:
events (avg/stddev): 50.0000/0.71
execution time (avg/stddev): 10.1329/0.05
Đây là một lưu lượng truy cập chỉ đọc hoàn toàn, nó sẽ trung bình trong 10 giao dịch (140 truy vấn) mỗi giây. Vì đó chỉ là các CHỌN, nên chúng tôi có thể dễ dàng sửa đổi một trong các quy tắc truy vấn hiện có và chặn lưu lượng truy cập:
Điều này sẽ dẫn đến lỗi sau ở phía ứng dụng:
[email protected]:~# sysbench /root/sysbench/src/lua/oltp_read_only.lua --threads=4 --events=200 --time=0 --mysql-host=10.0.0.101 --mysql-user=sbtest --mysql-password=sbtest --mysql-port=6033 --tables=32 --report-interval=1 --skip-trx=on --table-size=100000 --db-ps-mode=disable --rate=10 run
sysbench 1.1.0-bbee5d5 (using bundled LuaJIT 2.1.0-beta3)
Running the test with following options:
Number of threads: 4
Target transaction rate: 10/sec
Report intermediate results every 1 second(s)
Initializing random number generator from current time
Initializing worker threads...
Threads started!
FATAL: mysql_drv_query() returned error 1148 (SELECT queries are not allowed!!!) for query 'SELECT c FROM sbtest25 WHERE id=83384'
FATAL: `thread_run' function failed: /usr/local/share/sysbench/oltp_common.lua:426: SQL error, errno = 1148, state = '42000': SELECT queries are not allowed!!!
Bây giờ, điều này rõ ràng là khắc nghiệt. Chúng ta có thể lịch sự hơn và chỉ tăng độ trễ cho các truy vấn CHỌN.
Điều này rõ ràng sẽ ảnh hưởng đến hiệu suất của các truy vấn khi 10 mili giây được thêm vào cho mọi SELECT được thực thi.
SQL statistics:
queries performed:
read: 2800
write: 0
other: 0
total: 2800
transactions: 200 (5.60 per sec.)
queries: 2800 (78.44 per sec.)
ignored errors: 0 (0.00 per sec.)
reconnects: 0 (0.00 per sec.)
Throughput:
events/s (eps): 5.6030
time elapsed: 35.6952s
total number of events: 200
Latency (ms):
min: 622.04
avg: 7957.01
max: 18808.60
95th percentile: 15934.78
sum: 1591401.12
Threads fairness:
events (avg/stddev): 50.0000/36.01
execution time (avg/stddev): 397.8503/271.50
Chúng tôi thiết lập độ trễ cho mọi truy vấn SELECT, điều này không nhất thiết có ý nghĩa gì ngoài việc cho thấy rằng bạn có thể làm điều đó. Thông thường, bạn muốn sử dụng độ trễ cho một số truy vấn vi phạm. Giả sử chúng ta có một truy vấn rất nặng và nó làm tăng tải đáng kể lên CPU của cơ sở dữ liệu. Tệ hơn nữa, nó đã được giới thiệu bởi sự thay đổi mã gần đây và nó đến từ tất cả các máy chủ ứng dụng. Chắc chắn, bạn có thể đợi các nhà phát triển hoàn nguyên thay đổi hoặc đưa ra bản sửa lỗi nhưng với ProxySQL, bạn có thể tự mình kiểm soát và chỉ cần chặn truy vấn hoặc giảm tác động của nó thậm chí khá đáng kể.
Giả sử rằng cơ sở dữ liệu của chúng ta đang hoạt động tốt khi chuông báo thức bắt đầu reo.
Xem nhanh các chỉ số cho chúng ta biết rằng số lượng truy vấn được thực thi bởi ProxySQL đi xuống trong khi hiệu suất sử dụng CPU tăng lên. Chúng ta có thể xem các Truy vấn hàng đầu trong ProxySQL để xem liệu chúng ta có thể nhận thấy điều gì đó bất thường hay không.
Thực sự là bất thường - một truy vấn mới không phải là một phần của hỗn hợp truy vấn thông thường mà chúng tôi đã quan sát trên hệ thống của mình. Chúng tôi có thể sử dụng tùy chọn để tạo quy tắc truy vấn.
Chúng tôi sẽ thêm độ trễ 50 giây vào truy vấn bằng cách đặt Độ trễ thành 50000 mili giây.
Chúng tôi có thể xác nhận rằng quy tắc truy vấn đang được sử dụng và các truy vấn đang áp dụng .
Sau một thời gian ngắn, chúng tôi cũng có thể nhận thấy rằng tải giảm và số trong số các truy vấn được thực thi lại nằm trong phạm vi mong đợi. Tất nhiên, thay vì thêm độ trễ vào truy vấn, chúng ta có thể chỉ cần chặn nó. Điều đó thậm chí còn dễ dàng hơn đối với chúng tôi nhưng việc chặn hoàn toàn truy vấn có thể gây ảnh hưởng đáng kể đến ứng dụng.
Chúng tôi hy vọng bài đăng blog ngắn này cung cấp cho bạn một số thông tin chi tiết về cách ProxySQL có thể giúp bạn định hình lưu lượng truy cập của mình và giảm hiệu suất truy cập do truy vấn chạy.