Cách xác định điểm ngọt giữa kích thước nhóm và kết nối cơ sở dữ liệu trong PostgreSQL


14

Chúng tôi đang gặp sự cố khi xử lý lưu lượng trong giờ cao điểm đến máy chủ cơ sở dữ liệu của chúng tôi. Chúng tôi đang xem xét cải thiện phần cứng (xem câu hỏi này về khía cạnh đó ) nhưng chúng tôi cũng muốn làm việc với cấu hình tổng hợp và điều chỉnh máy chủ.

Ứng dụng chúng tôi đang làm việc là một trò chơi nhiều người chơi theo lượt cho điện thoại thông minh, trong đó phần phụ trợ bao gồm Rails với kỳ lânPostgreQuery 9.1 làm cơ sở dữ liệu. Chúng tôi hiện có 600 000 người dùng đã đăng ký và vì trạng thái trò chơi được lưu trữ trong cơ sở dữ liệu, hàng nghìn lần ghi được thực hiện cứ sau vài giây. Chúng tôi đã phân tích các tệp nhật ký từ PostgreSQL bằng PGBadger và trong những giờ quan trọng, chúng tôi nhận được rất nhiều

FATAL: remaining connection slots are reserved for non-replication superuser connections

Giải pháp ngây thơ để khắc phục vấn đề này sẽ là tăng max_connections (hiện là 100) trong postgresql.conf . Tôi đã đọc http://wiki.postgresql.org/wiki/Number_Of_Database_Connections cho biết đây có thể không phải là điều đúng đắn. Trong bài viết đã nói ở trên, nó đề cập đến việc tìm ra điểm ngọt ngào giữa max_connections và kích thước nhóm .

Có thể làm gì để tìm thấy điểm ngọt ngào này? Có công cụ nào tốt để đo hiệu suất I / O cho các giá trị khác nhau của max_connectionskích thước nhóm không?

Thiết lập hiện tại của chúng tôi là 4 máy chủ trò chơi, mỗi máy chủ có 16 nhân viên kỳ lân và kích thước nhóm là 5.

Dưới đây là các cài đặt postgres không mặc định mà chúng tôi đang sử dụng:

version                      | PostgreSQL 9.1.5 on x86_64-unknown-linux-gnu,compiled by gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3, 64-bit
checkpoint_completion_target | 0.9
checkpoint_segments          | 60
checkpoint_timeout           | 6min
client_encoding              | UTF8
effective_cache_size         | 2GB
lc_collate                   | en_US.UTF-8
lc_ctype                     | en_US.UTF-8
log_destination              | csvlog
log_directory                | pg_log
log_filename                 | postgresql-%Y-%m-%d_%H%M%S.log
log_line_prefix              | %t
log_min_duration_statement   | 200ms
log_rotation_age             | 1d
log_rotation_size            | 10MB
logging_collector            | on
max_connections              | 100
max_stack_depth              | 2MB
server_encoding              | UTF8
shared_buffers               | 1GB
ssl                          | on
TimeZone                     | localtime
wal_buffers                  | 16MB
work_mem                     | 8MB

Bạn có phải là người đã hỏi về điều này trong danh sách gửi thư trong vài tuần qua? Nếu vậy, tôi sẽ thêm liên kết ngược vào cuộc thảo luận đó. Ngoài ra: Phần cứng và cấu hình máy chủ DB của bạn là gì? wiki.postgresql.org/wiki/Slow_Query_Questions . Bao gồm các cài đặt không mặc định: wiki.postgresql.org/wiki/Server_Configuration . Bạn đã đọc wiki.postgresql.org/wiki/Tuning_Your_PostgreQuery_Server chưa? Bạn có làm việc hàng loạt thành các giao dịch lớn hơn nếu có thể? Bạn có sử dụng một lớp bộ nhớ đệm và nếu vậy, những gì? Bạn đang sử dụng synchronous_commit = offhay a commit_delay?
Craig Ringer

Vậy bạn có tổng cộng 20 kết nối đến máy chủ PostgreSQL? 5 mỗi máy chủ trò chơi? Với 5 liên kết từ mỗi máy chủ trò chơi được chia sẻ trên 16 công nhân kỳ lân?
Craig Ringer

Oh, bạn đang đăng nhập truy vấn chậm? Nếu vậy, điểm nóng của bạn là gì? Đơn giản INSERT? Lược đồ của bạn như thế nào - nó có được phân vùng không? Một explain analyzesố truy vấn mẫu là gì? Tần suất kiểm tra của bạn là bao lâu và mất bao lâu? (xem các tùy chọn đăng nhập điểm kiểm tra). Và nghiêm túc, phiên bản PostgreSQL của bạn là gì? (Cập nhật: Có vẻ như bạn liệt kê phần cứng của mình tại đây: dba.stackexchange.com/questions/28061/ mẹo )
Craig Ringer

Dù sao, để điều chỉnh kích thước nhóm cụ thể, câu trả lời thực sự duy nhất là thiết lập đo lường mạnh mẽ của tải và thông lượng máy chủ DB, sau đó bắt đầu điều chỉnh lên và xuống cho đến khi bạn tìm thấy điểm ngọt.
Craig Ringer

@CraigRinger Không tôi không phải là người đó. Nhưng cảm ơn vì các liên kết ngược! Tôi đã đọc Điều chỉnh máy chủ PostgreSQL của bạn và làm theo một số mẹo được đề cập. Bây giờ tôi đã bao gồm các cài đặt không mặc định. Chúng tôi hiện đang xem xét thực hiện các giao dịch và thử nghiệm lớn hơnsynchronous_commit = off
lorgartzor

Câu trả lời:


14

Câu trả lời ngắn ở đây là "thử nghiệm và lỗi được hướng dẫn bởi các số liệu theo dõi và hiệu suất".

Có một số quy tắc chung sẽ giúp bạn tìm thấy khu vực mơ hồ mà bạn nên bắt đầu, nhưng chúng rất chung chung. Các hướng dẫn rộng rãi "số lượng CPU cộng với số lượng đĩa độc lập" thường được trích dẫn, nhưng đó chỉ là một điểm khởi đầu cực kỳ khó hiểu.

Những gì bạn thực sự cần làm là có được các số liệu hiệu suất mạnh mẽ cho ứng dụng của bạn. Bắt đầu ghi số liệu thống kê.

Không có nhiều cách thức tích hợp công cụ cho việc này. Có những thứ như check_postgrestập lệnh nagios , ghi nhật ký hiệu năng hệ thống Cacti, trình thu thập số liệu thống kê PostgreQuery, v.v ... nhưng không có nhiều thứ kết hợp tất cả lại với nhau. Đáng buồn thay, bạn sẽ phải tự làm điều đó một chút. Đối với phía PostgreSQL, hãy xem giám sát trong hướng dẫn PostgreSQL. Một số tùy chọn bên thứ ba tồn tại, như Postgres Enterprise Monitor của EnterpriseDB .

Đối với các số liệu cấp ứng dụng được đề cập ở đây, bạn sẽ muốn ghi lại chúng trong các cấu trúc dữ liệu được chia sẻ hoặc trong một DB không bền bên ngoài như Redis và tổng hợp chúng khi bạn ghi chúng hoặc trước khi bạn viết chúng vào DB PostgreQuery của bạn. Cố gắng đăng nhập trực tiếp vào PG sẽ làm biến dạng các phép đo của bạn với chi phí được tạo bằng cách ghi lại các phép đo và làm cho vấn đề trở nên tồi tệ hơn.

Tùy chọn đơn giản nhất có lẽ là một singleton trong mỗi máy chủ ứng dụng mà bạn sử dụng để ghi lại số liệu thống kê ứng dụng. Bạn có thể muốn giữ một cập nhật liên tục tối thiểu, tối đa, n, tổng và trung bình; theo cách đó bạn không phải lưu trữ từng điểm stat, chỉ là các tổng hợp. Người độc thân này có thể viết số liệu thống kê tổng hợp của mình lên PG mỗi x phút, tỷ lệ đủ thấp để tác động hiệu suất sẽ ở mức tối thiểu.

Bắt đầu với:

  • Độ trễ yêu cầu là gì? Nói cách khác, ứng dụng mất bao lâu để nhận được yêu cầu từ khách hàng cho đến khi ứng dụng trả lời khách hàng. Ghi lại điều này trong tổng hợp trong một khoảng thời gian, chứ không phải là hồ sơ cá nhân. Nhóm nó theo loại yêu cầu; nói, theo trang.

  • Độ trễ truy cập cơ sở dữ liệu cho mỗi truy vấn hoặc loại truy vấn mà ứng dụng thực thi là gì? Mất bao lâu để hỏi DB về thông tin / lưu trữ thông tin cho đến khi hoàn thành và có thể chuyển sang nhiệm vụ tiếp theo? Một lần nữa, tổng hợp các số liệu thống kê này trong ứng dụng và chỉ viết thông tin tổng hợp vào DB.

  • Thông lượng của bạn như thế nào? Trong bất kỳ x phút đã cho nào, có bao nhiêu truy vấn của mỗi lớp chính mà ứng dụng của bạn thực thi được DB phục vụ?

  • Trong cùng khoảng thời gian x phút đó, có bao nhiêu yêu cầu của khách hàng?

  • Lấy mẫu cứ sau vài giây và tổng hợp trên cùng một cửa sổ x phút trong DB, có bao nhiêu kết nối DB? Có bao nhiêu trong số đó là nhàn rỗi? Có bao nhiêu người đã hoạt động? Trong phần chèn? Cập nhật? chọn? xóa? Có bao nhiêu giao dịch đã có trong khoảng thời gian đó? Xem tài liệu thu thập số liệu thống kê

  • Một lần nữa lấy mẫu và tổng hợp trong cùng khoảng thời gian, số liệu hiệu suất của hệ thống máy chủ như thế nào? Có bao nhiêu đọc và bao nhiêu ghi IOs / giây? Megabyte mỗi giây của đĩa đọc và ghi? Sử dụng CPU? Tải trung bình? Sử dụng RAM?

Bây giờ bạn có thể bắt đầu tìm hiểu về hiệu suất của ứng dụng bằng cách tương quan dữ liệu, vẽ biểu đồ, v.v. Bạn sẽ bắt đầu thấy các mẫu, bắt đầu tìm các nút thắt cổ chai.

Bạn có thể biết rằng hệ thống của bạn hoạt động bình thường INSERTUPDATEcó tốc độ giao dịch cao, mặc dù I / O đĩa khá thấp tính bằng megabyte mỗi giây. Đây sẽ là một gợi ý mà bạn cần để cải thiện hiệu suất xả đĩa của mình với bộ điều khiển RAID bộ nhớ đệm ghi lại được hỗ trợ bằng pin hoặc một số ổ SSD được bảo vệ bằng năng lượng chất lượng cao. Bạn cũng có thể sử dụng synchronous_commit = offnếu bạn mất một vài giao dịch khi máy chủ gặp sự cố và / hoặc a commit_delay, để tắt một số tải đồng bộ hóa.

Khi bạn vẽ biểu đồ giao dịch của mình mỗi giây theo số lượng kết nối đồng thời và chính xác cho tỷ lệ yêu cầu khác nhau mà ứng dụng đang nhìn thấy, bạn sẽ có thể biết rõ hơn về vị trí thông lượng của bạn.

Nếu bạn không có bộ nhớ xả nhanh (RAID BBU hoặc SSD nhanh bền), bạn sẽ không muốn nhiều hơn một số lượng nhỏ các kết nối chủ động, có thể nhiều nhất là gấp đôi số lượng đĩa bạn có, có thể ít hơn tùy thuộc vào sắp xếp RAID , hiệu suất đĩa, v.v ... Trong trường hợp này, nó thậm chí không có giá trị dùng thử và lỗi; chỉ cần nâng cấp hệ thống lưu trữ của bạn lên một hệ thống nhanh chóng .

Xem pg_test_fsyncmột công cụ sẽ giúp bạn xác định xem đây có phải là một vấn đề cho bạn không. Hầu hết các gói PostgreSQL cài đặt công cụ này như một phần của đóng góp, vì vậy bạn không cần phải biên dịch nó. Nếu bạn nhận được ít hơn một vài ngàn ops / giây trong pg_test_fsyncbạn khẩn trương cần phải nâng cấp hệ thống lưu trữ của bạn. Máy tính xách tay được trang bị SSD của tôi có 5000-7000. Máy trạm của tôi đang hoạt động với một mảng RAID 10 đĩa gồm 72 đĩa tốc độ 7200 vòng / phút và ghi qua (không ghi vào bộ đệm) nhận được khoảng 80 ops / giây f_datasync, giảm xuống 20 ops / giây fsync(); nó chậm hơn hàng trăm lần . So sánh: máy tính xách tay với ssd vs máy trạm với RAID 10 ghi (không ghi bộ đệm). SSD của máy tính xách tay này là rẻ và tôi không nhất thiết phải tin tưởng nó để xóa bộ nhớ cache ghi của nó khi mất điện; Tôi giữ các bản sao lưu tốt và sẽ không sử dụng nó cho dữ liệu tôi quan tâm. SSD chất lượng tốt cũng hoạt động tốt nếu không tốt hơn và có độ bền ghi.

Trong trường hợp ứng dụng của bạn, tôi khuyên bạn nên xem xét:

  • Một hệ thống lưu trữ tốt với xả nhanh. Tôi không thể nhấn mạnh điều này đủ. SSD chất lượng tốt, không mất điện và / hoặc bộ điều khiển RAID với bộ đệm ghi lại được bảo vệ bằng điện.
  • Sử dụng UNLOGGEDbảng cho dữ liệu bạn có thể đủ khả năng để mất. Định kỳ tổng hợp nó vào các bảng đã đăng nhập. Ví dụ: giữ các trò chơi đang diễn ra trong các bảng chưa được đăng ký và ghi điểm vào các bảng bền thông thường.
  • Sử dụng một commit_delay(ít hữu ích hơn với lưu trữ nhanh chóng - gợi ý)
  • Tắt synchronous_commitcho các giao dịch bạn có thể đủ khả năng để mất (ít hữu ích hơn với lưu trữ nhanh chóng - gợi ý gợi ý)
  • Các bảng phân vùng, đặc biệt là các bảng có dữ liệu "hết tuổi" và được dọn sạch. Thay vì xóa khỏi bảng được phân vùng, hãy bỏ phân vùng.
  • Chỉ số một phần
  • Giảm số lượng chỉ mục bạn tạo. Mỗi chỉ số có một chi phí viết.
  • Kết hợp công việc thành các giao dịch lớn hơn
  • Sử dụng các bản sao dự phòng nóng chỉ đọc để giảm tải đọc khỏi DB chính
  • Sử dụng một lớp bộ đệm như memcached hoặc redis cho dữ liệu thay đổi ít thường xuyên hơn hoặc có thể đủ khả năng để cũ. Bạn có thể sử dụng LISTENNOTIFYthực hiện vô hiệu hóa bộ đệm bằng cách sử dụng các kích hoạt trên các bảng PostgreSQL.

Nếu nghi ngờ: http://www.postgresql.org/support/prof Profession_support/

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.