2012-05-02 29 views
15

Tôi có một số lệnh quản lý dựa trên gevent. Vì lệnh quản lý của tôi tạo ra hàng nghìn yêu cầu, tôi có thể chuyển tất cả các cuộc gọi socket thành các cuộc gọi không chặn bằng Gevent. Điều này thực sự tăng tốc ứng dụng của tôi khi tôi có thể thực hiện các yêu cầu cùng một lúc.Làm thế nào để pgBouncer giúp tăng tốc Django

Hiện tại, nút cổ chai trong ứng dụng của tôi có vẻ là Postgres. Có vẻ như điều này là do thư viện Psycopg được sử dụng để kết nối với Django được viết bằng C và không hỗ trợ các kết nối không đồng bộ.

Tôi cũng đọc rằng việc sử dụng pgBouncer có thể tăng tốc độ Postgres lên 2X. Điều này nghe có vẻ tuyệt vời nhưng nó sẽ là tuyệt vời nếu ai đó có thể giải thích cách pgBouncer hoạt động và giúp đỡ?

Cảm ơn

+0

Cũng có khả năng mô hình cơ sở dữ liệu của bạn không khớp với các truy vấn bạn đang kích hoạt. Thông thường, chi phí trên mạng là rất nhỏ so với công việc cần thiết để tìm nạp khối dữ liệu từ đĩa, cũng: điều này không hiệu quả về chi phí, chỉ độ trễ. (ngoại trừ trường hợp kết nối/ngắt kết nối rất thường xuyên) – wildplasser

Trả lời

65

Bên cạnh việc tiết kiệm phí kết nối & ngắt kết nối khi thực hiện thao tác này trên mỗi yêu cầu, trình kết nối kết nối có thể kết nối một số lượng lớn kết nối máy khách với một số lượng nhỏ kết nối cơ sở dữ liệu thực. Trong PostgreSQL, số lượng tối ưu các kết nối cơ sở dữ liệu hoạt động thường ở đâu đó xung quanh ((2 * core_count) + effective_spindle_count). Trên con số này, cả thông lượng và thời gian chờ trở nên tồi tệ hơn.

Đôi khi mọi người sẽ nói "Tôi muốn hỗ trợ 2000 người dùng, với thời gian phản hồi nhanh". Nó là khá nhiều đảm bảo rằng nếu bạn cố gắng làm điều đó với 2000 kết nối cơ sở dữ liệu thực tế, hiệu suất sẽ là khủng khiếp. Nếu bạn có một máy tính với bốn bộ vi xử lý lõi tứ và bộ dữ liệu hoạt động được lưu trữ đầy đủ, bạn sẽ thấy hiệu suất tốt hơn cho những người dùng 2000 đó bằng cách chuyển các yêu cầu qua khoảng 35 kết nối cơ sở dữ liệu.

Để hiểu tại sao điều đó đúng, thử nghiệm ý tưởng này sẽ hữu ích. Hãy xem xét một máy chủ cơ sở dữ liệu giả định với chỉ một tài nguyên để chia sẻ - một lõi đơn. Lõi này sẽ cắt giảm thời gian bằng nhau giữa tất cả các yêu cầu đồng thời mà không phải trả phí. Hãy nói rằng 100 yêu cầu tất cả đi vào cùng một lúc, mỗi trong số đó cần một giây của thời gian CPU. Cốt lõi hoạt động trên tất cả chúng, cắt lát giữa chúng cho đến khi chúng hoàn thành 100 giây sau đó. Bây giờ hãy xem xét điều gì sẽ xảy ra nếu bạn đặt một nhóm kết nối ở phía trước sẽ chấp nhận 100 kết nối máy khách nhưng chỉ thực hiện một yêu cầu một lần tới máy chủ cơ sở dữ liệu, đưa bất kỳ yêu cầu nào đến trong khi kết nối bận vào hàng đợi. Bây giờ khi 100 yêu cầu đến cùng một lúc, một khách hàng nhận được phản hồi sau 1 giây; người khác nhận được phản hồi sau 2 giây và khách hàng cuối cùng nhận được phản hồi sau 100 giây. Không ai phải đợi lâu hơn để nhận được phản hồi, thông lượng là như nhau, nhưng độ trễ trung bình là 50,5 giây thay vì 100 giây. Một máy chủ cơ sở dữ liệu thực có nhiều tài nguyên hơn có thể được sử dụng song song, nhưng nguyên tắc tương tự giữ, khi chúng được bão hòa, bạn chỉ làm tổn thương mọi thứ bằng cách thêm nhiều yêu cầu cơ sở dữ liệu đồng thời hơn. Nó thực sự tồi tệ hơn ví dụ, bởi vì với nhiều nhiệm vụ hơn bạn có nhiều công tắc nhiệm vụ hơn, tăng ganh đua cho ổ khóa và bộ nhớ cache, L2 và L3, và nhiều vấn đề khác cắt thành cả thông lượng và độ trễ. Ngoài ra, trong khi cài đặt work_mem cao có thể giúp truy vấn theo một số cách, cài đặt đó là giới hạn cho mỗi nút kế hoạch cho mỗi kết nối, vì vậy với số lượng lớn các kết nối bạn cần phải rời khỏi điều này rất nhỏ để tránh bộ nhớ đệm đỏ bừng hoặc thậm chí dẫn đến trao đổi, dẫn đến kế hoạch chậm hơn hoặc những thứ như bảng băm tràn vào đĩa.

Một số sản phẩm cơ sở dữ liệu xây dựng một cách hiệu quả hồ bơi kết nối vào máy chủ, nhưng cộng đồng PostgreSQL đã đảm nhận vị trí mà vì việc kết nối tốt nhất được thực hiện gần hơn với phần mềm máy khách, họ sẽ để người dùng quản lý việc này. Hầu hết các poolers sẽ có một số cách để hạn chế các kết nối cơ sở dữ liệu đến một số cứng, trong khi cho phép nhiều yêu cầu khách đồng thời hơn, xếp hàng chúng khi cần thiết. Đây là những gì bạn muốn và sẽ được thực hiện trên cơ sở giao dịch, không phải theo tuyên bố hoặc kết nối.

+1

Câu trả lời hay. Tôi không thể đồng ý thêm nữa. – wildplasser

+0

Những hippies front-end này tất cả đều muốn thực hiện và ngắt kết nối nhanh nhất có thể, và đặt poolers kết nối ở phía trước nếu chúng không thể đạt tới trạng thái cao tự nhiên của chúng. Tôi thích công thức 2 * ncore + nspindle. Mỗi quá trình được coi là bị chặn trong một đĩa đọc. – wildplasser

+0

@kgrittn Tôi giả định trong thử nghiệm suy nghĩ của bạn ở trên, mỗi truy vấn mất một giây để chạy trong trường hợp không có các yêu cầu khác? –

9

PgBouncer giảm độ trễ trong việc thiết lập kết nối bằng cách dùng làm proxy duy trì hồ bơi kết nối. Điều này có thể giúp tăng tốc ứng dụng của bạn nếu bạn đang mở nhiều kết nối ngắn ngủi với Postgres. Nếu bạn chỉ có một số lượng nhỏ các kết nối, bạn sẽ không thấy nhiều thắng lợi.

+0

Nếu Iäve hiểu điều này đúng - Django vẫn tạo kết nối lặp đi lặp lại nhưng pgBouncer giảm thời gian cần thiết để tạo kết nối này. Tôi đã nghe nói rằng Django tạo ra một kết nối mới cho mọi yêu cầu. Theo yêu cầu, mọi người có nghĩa là yêu cầu web tìm nạp trang (có nghĩa là mọi lệnh được thực hiện trong chu kỳ của một lượt xem sẽ đi qua một kết nối cơ sở dữ liệu) hoặc yêu cầu có nghĩa là mỗi lần nhấn cơ sở dữ liệu riêng lẻ (SELECT, INSERT, UPDATE và DELETE) Trong trường hợp đó, mỗi lệnh đơn sẽ được thực thi trong một kết nối mới mặc dù chúng sẽ ở cùng một chu kỳ xem –

+2

Có, Django sẽ tạo một kết nối mới, nhưng kết nối sẽ được thiết lập nhanh hơn vì nó sẽ là một cá thể PgBouncer cục bộ. Django sẽ sử dụng một kết nối mới cho mọi yêu cầu web, không phải truy vấn cơ sở dữ liệu. –

+1

Bạn có thể tìm thấy [câu hỏi này] (http://stackoverflow.com/questions/1125504/django-persistent-database-connection) có một số thông tin thú vị hơn. Nhưng lưu ý rằng có một lý do kết nối mới được mở trên mọi yêu cầu. Nếu yêu cầu gặp lỗi, có thể giao dịch có thể không được đóng đúng (trong số các thứ khác) dẫn đến kết quả không mong muốn. –

Các vấn đề liên quan