Hãy tận dụng tối đa hệ thống bạn đang có
(blog.danslimmon.com)- Nút thắt cổ chai Postgres của một ứng dụng SaaS đơn lẻ trở nên nghiêm trọng, khiến mức sử dụng CPU duy trì ở 60~80% và có lúc tăng lên 100%, dẫn đến một sự cố ngắn
- Mở rộng theo chiều dọc bằng cách chuyển sang instance DB lớn hơn đã chạm giới hạn, nên rất khó tiếp tục hấp thụ thêm tải theo cùng cách đó
- Ghi sharding và microservices có thể nâng cao dung lượng và độ linh hoạt vận hành, nhưng vẫn liên tục để lại chi phí phức tạp từ backup, giám sát, migration, ORM cho tới topology mạng
- Trên thực tế, trong 3 tháng nhóm đã loại bỏ các truy vấn nặng, tối ưu mã Rails, tinh chỉnh Postgres và tách một số truy vấn chỉ đọc đắt đỏ sang DB bản sao
- Kết quả là mức sử dụng CPU DB cao nhất theo tuần giảm từ 90% xuống 30%, tạo thêm dư địa để tận dụng hệ thống hiện tại lâu hơn trước khi chuyển sang kiến trúc thế hệ tiếp theo
Nút thắt Postgres và điểm kết của mở rộng theo chiều dọc
- Khi tải của một ứng dụng SaaS đơn lẻ tăng lên, hiệu năng Postgres trở thành nút thắt cổ chai chính
- Mức sử dụng CPU duy trì trong khoảng 60~80%
- Ít nhất một lần đã tăng vọt lên 100%, gây ra một sự cố ngắn
- Trước đây, mỗi khi DB trở nên quá bận, nhóm lại thay bằng một instance lớn hơn để mua thêm thời gian
- Cách này giúp có thể tập trung vào những việc khác như phát triển tính năng
- Khi đó họ đã dùng instance lớn nhất, nên không thể mở rộng theo chiều dọc thêm nữa
Kiến trúc thế hệ tiếp theo hấp dẫn nhưng đắt đỏ
- Những lựa chọn chính được thảo luận là ghi sharding và microservices
- Ghi sharding là cách đặt các cụm DB độc lập và ghi dữ liệu vào một DB cụ thể theo chiến lược phân vùng
- Về mặt tiềm năng, nó có thể tăng dung lượng lên 2~3 bậc độ lớn
- Microservices chia monolith thành nhiều dịch vụ, mỗi dịch vụ có kho dữ liệu riêng
- Có thể chọn kho dữ liệu phù hợp với workload của từng dịch vụ
- Cả hai cách đều mở rộng lựa chọn về khả năng chịu lỗi và độ phục hồi vận hành, nhưng mục tiêu trước mắt là đưa hiệu năng DB về trạng thái có thể kiểm soát
Phức tạp một khi đã đưa vào sẽ liên tục tạo chi phí
- Sự gia tăng phức tạp không chỉ dừng ở chi phí triển khai cấu trúc mới mà còn kéo theo chi phí chú ý về sau
- Nếu chọn sharding DB, mọi quyết định kỹ thuật trong tương lai đều phải xử lý thêm lớp phức tạp mới
- Backup
- Giám sát
- Migration
- ORM
- Topology mạng
- Microservices cũng tạo ra gánh nặng tương tự; việc duy trì kiến trúc bổ sung có thể làm chậm hoặc khiến phải từ bỏ việc chuyển giao tính năng
Trước tiên tìm dư địa trong hệ thống hiện tại
- Ngay cả khi có vẻ cần một cuộc chuyển đổi kiến trúc lớn, hệ thống hiện có thường vẫn còn dư địa bổ sung
- Chỉ bằng điều chỉnh workload, tinh chỉnh hiệu năng và thêm các hệ thống phụ trợ, có thể mua thêm vài tháng hoặc vài năm
- Nếu các lựa chọn này khả thi, đáng để thử chúng trước khi xây dựng hẳn một hệ thống thế hệ tiếp theo
Các tối ưu hóa đã thực hiện trên thực tế
- Ở công việc đầu tiên, hai kỹ sư đã dành khoảng 3 tháng chủ yếu để xử lý các vấn đề hiệu năng DB
- Không có một mẹo thần kỳ duy nhất nào
- Dùng telemetry để tìm các truy vấn nặng
- Xác định nơi phát sinh truy vấn trong codebase Rails
- Tối ưu hoặc loại bỏ truy vấn
- Tinh chỉnh nhiều thiết lập Postgres
- Ở công việc thứ hai, hai kỹ sư khác đã sửa codebase để một số truy vấn chỉ đọc đắt đỏ chạy trên DB bản sao
- Tách truy vấn
SELECTxuất hiện thường xuyên nhất do cơ chế polling của web client gây ra khỏi DB chính
- Tách truy vấn
Kết quả và nguyên tắc vận hành
- Gộp hai công việc lại, mức sử dụng CPU DB cao nhất theo tuần đã giảm từ 90% xuống 30%
- Mức sử dụng CPU cao nhất theo tuần: {l:90,30}
- Dư địa CPU tăng lên đáng kể, và khả năng giảm tải khỏi DB chính cũng lớn hơn nhiều
- Khi chạm vào nhiều phần của codebase và có nhiều lập trình viên cùng cộng tác, kiến thức phân tán về hệ thống hiện tại cũng được tích lũy
- Phức tạp không phải lúc nào cũng xấu, và đến một lúc nào đó vẫn sẽ phải chuyển sang cấu trúc phức tạp hơn trước khi chạm tới giới hạn căn bản của kiến trúc DB
- Nhưng cho đến trước thời điểm đó, nếu vắt kiệt hệ thống hiện tại trước, bạn có thể làm việc lâu hơn với một hệ thống nhàm chán và đơn giản nhất có thể, điều này cũng có lợi hơn về chi phí và tính thực dụng
1 bình luận
Các ý kiến trên Hacker News
Nhìn vào các vấn đề hiệu năng cơ sở dữ liệu, suy nghĩ nóng nhất của tôi cho các dự án mới là: hãy thiết kế sao cho hot path của ứng dụng hoàn toàn không dùng join
Lưu trữ rẻ, nên cứ phi chuẩn hóa toàn bộ và cập nhật tất cả trong transaction là được. Thật sự đáng kinh ngạc khi bỏ join đi thì nhanh hơn đến mức nào. Các truy vấn phân tích ad-hoc có thể được sao chép sang một cơ sở dữ liệu khác dành cho phân tích
Tôi có cảm xúc phức tạp với DynamoDB của Amazon, nhưng điểm rằng muốn dùng đúng thì trước hết phải lên kế hoạch mẫu sử dụng rồi mới xác định schema là điều đáng mang sang cả cơ sở dữ liệu quan hệ. Dạo này tôi thậm chí cho rằng nếu không nhằm mục đích phân tích thì join là không cần thiết. Các cơ sở dữ liệu chính đều có thuộc tính ACID, còn lưu trữ thì rẻ đến mức khó tin, nên cứ phi chuẩn hóa là xong
Để tránh hot partition, tốt hơn nên dùng thứ gì đó gần với UUID thay vì số nguyên. Không phải thuốc chữa bách bệnh và cũng có nhược điểm, nhưng bạn có thể quen với hiệu năng “luôn ổn” có thể mở rộng ngang, thay vì hiệu năng tuyệt vời của số nguyên rồi một ngày nào đó sẽ sụp đổ
Một suy nghĩ còn nóng hơn nữa là đánh index cho mọi cột, nhưng đó là chủ đề để bàn vào ngày khác
Nhìn từ góc độ nợ kỹ thuật, nếu cố làm mọi thứ nhanh ngay từ đầu thì chi phí sẽ cao hơn nhiều. Tốc độ phát triển sẽ chậm đi đáng kể, và có khả năng chúng tôi đã thất bại trong vài cuộc khủng hoảng
Thay vào đó, chúng tôi trả thêm vài nghìn đô la mỗi tháng cho chi phí máy móc so với nhu cầu thực tế, và tiết kiệm được vài tháng nhân lực vào thời điểm chưa tuyển đủ kỹ sư và chi phí cơ hội của phát triển tính năng rất lớn. Vì không thể biết trước đâu sẽ là nút thắt cổ chai, để làm mọi thứ nhanh ngay từ đầu có lẽ cần nhiều hơn 10–20 lần công việc. Một số nút thắt khá bất ngờ
Join có thể gây hại ở quy mô lớn, nhưng phần lớn startup ít nhất là giai đoạn đầu không có vấn đề về quy mô. Phi chuẩn hóa có thể là một tối ưu hóa tốt, nhưng bạn phải trả chi phí tốc độ là đồng bộ mọi bản sao mỗi khi có thay đổi. Sẽ có ai đó tạo ra lỗi không cập nhật một trường phi chuẩn hóa không phải nguồn chính, khiến người dùng thấy dữ liệu cũ. Thông thường, dùng join rồi tối ưu sau bằng read-aside cache hoặc tương tự sẽ rẻ hơn về tổng chi phí so với việc bẻ cong schema
Ngược lại, ghi một dữ liệu vào 20 nơi thay vì 1 nơi thì chậm hơn nhiều về hiệu năng, truy vấn cũng cực kỳ phức tạp và dễ phát sinh lỗi. Sẽ có chuyện cập nhật 18 nơi nhưng quên mất 2 nơi
Người ta nêu lưu trữ rẻ như lợi thế của phi chuẩn hóa, nhưng lưu trữ ở đây là vấn đề nhỏ nhất. Bề mặt lỗi lớn hơn rất nhiều và hiệu năng ghi kém mới là vấn đề thật sự, và hiệu năng ghi đó rất dễ ăn mòn cả hiệu năng đọc
Ứng dụng cao về cơ bản chỉ làm một việc, những thứ còn lại bổ trợ cho việc đó. Phần lớn các Big Tech mà bạn có thể nghĩ đến thuộc loại này. Trong mô hình dữ liệu chỉ có vài khái niệm vận hành thật sự quan trọng
Facebook thực chất chỉ có người, bài đăng và quảng cáo. Netflix thì khoảng tài khoản và chương trình. Sản phẩm Amazon cốt lõi là người bán, người mua, hàng hóa, và có thể thêm vài thứ hậu cần phía sau
Lý do có nhiều ứng dụng cao là vì chúng dễ. Chúng dễ hơn nhiều so với ứng dụng rộng thường được gọi là “enterprise”. Lý do phần mềm enterprise tệ là vì nó khó, và đây là vùng ít được khám phá nhất cũng như có cơ hội khổng lồ. Những người chơi hiện hữu như Oracle đang làm rất tệ ở đây, và nếu bạn bước vào với tư duy kiểu ứng dụng cao thì bạn cũng sẽ như vậy
Những lời khuyên như “tuyệt đối đừng dùng join”, “thiết kế xoay quanh một bảng duy nhất” có lý với ứng dụng cao, nhưng là lời khuyên khủng khiếp với ứng dụng rộng. Thỉnh thoảng có thể thấy các công ty ứng dụng rất cao thất bại thảm hại khi thử làm việc ngoài năng lực cốt lõi, vì họ đầy những người tôn sùng các lời khuyên này
Lời khuyên này dành cho các công ty đã thành công, đang làm việc dễ và đã hái hết những quả thấp. Ngay cả các ứng dụng cao chưa trở thành nạn nhân của thành công cũng không cần xẻ nát mô hình dữ liệu vì hiệu năng. Chỉ những công ty đã thành công khổng lồ và đang vắt kiệt giọt hiệu năng cuối cùng mới bận tâm đến chuyện đó, mà chính những công ty ấy lại là nơi ít cần lời khuyên nhất. Các lời khuyên xoay quanh ứng dụng cao kiểu “FAANG làm vậy thì bạn cũng nên làm”, “nếu có 1 tỷ người dùng thì sao?” làm ô nhiễm đầu óc của những người muốn làm việc thú vị hơn là hiển thị quảng cáo cho hàng tỷ người
Với các join lớn, về sau vẫn có cách sửa hiệu năng như đẩy vào materialized view hoặc ETL sang kho lưu trữ dạng cột. Nhưng nếu ai đó sao chép cột
subtotal_centsvào các model Order, Invoice, Payment, NotificationEmail, UserProfileRecentOrders, rồi để 296 nơi tham chiếu hoặc cập nhật nó, thì con đường quay lại trạng thái lành mạnh sẽ rất dàiThường vấn đề phát sinh ở các bảng có tính chất bản ghi lịch sử. Dữ liệu cần cho vận hành hằng ngày chỉ là một phần rất nhỏ trong bảng thực tế, nhưng thao tác trên một bảng khổng lồ thì kiểu gì cũng chậm, bất kể có index nào. Bản thân việc thêm nhiều index hơn cũng trở thành vấn đề
Ít nhất trong cơ sở dữ liệu quan hệ truyền thống, chỉ đánh index cho mọi cột là chưa đủ; cần tạo đúng index tổ hợp cột có thể được sử dụng. DynamoDB có thể khác
Hãy vắt kiệt tối đa những gì mình có, và sau khi đã vắt kiệt một thời gian, hãy thay đổi cách nhìn nhận vấn đề; khi vắt thêm ở chỗ này, chỗ kia, rồi cả chỗ nữa, bạn sẽ đột nhiên nhận ra vẫn còn rất nhiều thứ còn lại
Tôi đã tối ưu một monolith khổng lồ trong khoảng hai tháng: từ mức dưới 2.000 RPS, nơi PM và đội ngũ nghĩ rằng không còn gì để vắt ra nữa, lên dưới 3.200 RPS nhờ thay phần cứng; chỉnh thêm vài ngày lên 4.000 RPS; cố thêm một chút lên 10.000 RPS; rồi khoảng một tuần sau lên 40.000 RPS
Có người nói “thế này là đủ rồi, không cần đi xa hơn nữa”, nhưng sau khi thay đổi khá nhiều thứ, nó nhảy lên hơn 2 triệu RPS trên một máy duy nhất, và một tháng sau thì xử lý ổn định hơn 40 triệu RPS với độ trễ thấp. Vẫn còn chút dư địa để đẩy tiếp
Hiện tại chúng tôi thậm chí chưa dùng đến 5% năng lực có thể khai thác. Chỉ riêng việc thay đổi cách nghĩ về vấn đề đã tạo ra mức thay đổi như vậy. Việc chuyển từ máy chủ cũ sang máy chủ mới chỉ giúp tăng từ 1.800 RPS lên nhỉnh hơn 3.000 RPS, chỉ có vậy. Thêm phần cứng không sửa được vấn đề gốc, còn thêm độ phức tạp chỉ là đẩy vấn đề về sau. Khi thay đổi cách nghĩ về vấn đề, bản thân vấn đề và câu trả lời cũng thay đổi
Bổ sung cho câu “tách monolith thành nhiều dịch vụ liên kết với nhau, mỗi dịch vụ có kho dữ liệu riêng có thể mở rộng theo điều kiện của nó”, ở thời điểm này không nhất thiết phải tách mọi microservice có thể. Chỉ cần hỏi “phần tách nào sẽ tạo tác động lớn nhất?”
Trong trường hợp của tôi, tôi tách một phần dữ liệu chuỗi thời gian từ Mongo sang Cassandra. Cấu trúc bảng của Cassandra phù hợp hơn nhiều. Tập dữ liệu đó có schema được định nghĩa rõ ràng, và Cassandra có thể đóng gói dữ liệu hiệu quả hơn nhiều. Ở phần đó không cần sự linh hoạt của tài liệu JSON
Vì dữ liệu đó chiếm phần lớn tổng dữ liệu, nên sau đó Mongo trở nên khá ổn. Chỉ cần đúng một lần tách. Về mặt kỹ thuật, trước và sau vẫn đều là monolith, chỉ là cùng một dịch vụ ghi vào hai database
Trớ trêu là về sau có một kiến trúc sư kiểu lý thuyết suông muốn gộp tất cả dữ liệu vào một document store JSON, và đã có nhiều cuộc trao đổi kiểu “chúng ta đã đi con đường đó rồi và biết nó kết thúc ở đâu”
Mở rộng theo chiều dọc mới nên là giải pháp đầu tiên hiển nhiên. Đây là điểm nhiều người bỏ lỡ, và bài viết cũng có đề cập phần nào: mở rộng theo chiều dọc gần giống mở rộng theo chiều ngang mà không phá vỡ tính nhất quán của database
Còn rất nhiều dư địa để vắt, và hiếm khi cần dễ dàng đưa ra các antipattern như bỏ qua join hay kiểm chứng dữ liệu chỉ vì gặp vấn đề hiệu năng
Nếu các lập trình viên biết đọc kết quả EXPLAIN/ANALYZE và biết lập chỉ mục đúng cách cũng như tối ưu truy vấn, có thể tránh được vô số quyết định thiết kế quá mức
Chỉ cần ghi lại các truy vấn, lọc ra những truy vấn chạy cực thường xuyên hoặc mất nhiều thời gian, cache những truy vấn chạy thường xuyên, và tối ưu những truy vấn nặng. Làm việc này một cách có hệ thống sẽ giúp hệ thống khỏe mạnh hơn
Theo kinh nghiệm của tôi, những thứ giúp ích nhiều là APM, log truy vấn chậm, replica đọc/ghi của database, partitioning và sharding
Các công cụ như https://explainmysql.com cho thấy rõ hơn trên thực tế cần tối ưu điều gì, nên trở thành một hệ thống dễ tiếp cận hơn cho những lập trình viên có đủ kiến thức để cấu hình database nhưng chưa đủ để hiểu cách nó được dùng bên trong
Tôi có cảm giác ai đó đã đang xây một hệ thống AI mà chỉ cần đưa schema và log vào là nó sẽ kỳ diệu chạy ra SQL cần cải thiện. Không chắc có nên tin hay không, nhưng nhiều công ty hẳn sẽ muốn dùng thứ đó hơn là tuyển DBA chuyên trách
Tôi không biết có phải luôn chỉ định index hint cho từng truy vấn hay không. Đôi khi có vẻ truy vấn không dùng index dù index đó tồn tại. Tôi nghĩ nếu dùng execution plan của SQL thì có thể hiểu vấn đề này tốt hơn
Không thể sửa code tệ bằng một kiến trúc mới. Nó chỉ đẩy vấn đề lùi lại một thời gian mà thôi
Tôi nhớ đến một câu mình thích. “Ta ra trận với đội quân mình đang có, chứ không phải đội quân mình muốn có hay muốn có trong tương lai”
Có thể bạn sẽ muốn bỏ qua sự thật rằng câu này xuất phát từ Donald Rumsfeld. Dù vậy, ông ấy cũng có vài câu rất hay như “unknown unknowns”
Khi làm việc trong đội nhóm, tôi thường nhớ đến câu này. Không phải ai cũng hoàn toàn đồng ý, hay có cùng cách hiểu và mục tiêu chung. Có người có thể làm việc theo cách kém hiệu quả hoặc không phải cách tôi ưa thích. Nhưng có đội vẫn tốt hơn là không có, nên phải tìm cách tốt nhất để đạt mục tiêu với đội mình đang có
Điều này cũng áp dụng rất đúng với hệ thống
https://www.youtube.com/watch?v=XH_34tqxAjA
https://www.google.com/search?q=no+battle+plan+survives
Câu này áp dụng với chính chúng ta tốt hơn là với hệ thống
Theo kinh nghiệm của tôi, trong các web app xây trên ORM, khi tải cơ sở dữ liệu trở thành vấn đề thì có rất nhiều quả thấp dễ hái có thể đạt được bằng tối ưu truy vấn
Vượt ra ngoài những điều cơ bản như “có vấn đề N+1 không”, ORM đôi khi không tạo ra truy vấn tối ưu. Tôi không muốn xây một web app production phức tạp mà không có ORM, nhưng thỉnh thoảng cần có khả năng thoát khỏi ORM
Cần profile các truy vấn đang chạy thật trong production và tiêu tốn nhiều tài nguyên nhất. Nhìn vào các truy vấn đó và hiểu hình dạng của các bảng liên quan. Có khi ORM dùng join nhưng thực ra cần subquery, và cũng có trường hợp ngược lại. Đôi khi cần tiền tổng hợp một phần kết quả, hoặc điều chỉnh điều kiện WHERE trong các join phức tạp
Tôi từng thấy một truy vấn do ORM sinh ra, chạy tương đối thường xuyên, đang giết chết cơ sở dữ liệu; sau vài chỉnh sửa nhỏ, thời gian chạy từ hơn 20 giây giảm xuống dưới 1 giây
expire_on_commit=FalseTùy chọn này cũng không bảo đảm sẽ dùng RETURNING; nó chỉ dùng nếu database driver và cơ sở dữ liệu hỗ trợ, và ORM hỗ trợ tổ hợp driver/cơ sở dữ liệu đó. SQL được sinh ra có xuất hiện trong log, nhưng không có API để kiểm tra trực tiếp, nên nếu không tự bắt log rồi cào ra thì không có cách nào buộc test suite xác nhận việc dùng RETURNING. May là trong framework Pytest thì việc này khá dễ
Tôi thích ORM, nhưng những chuyện như thế này phức tạp đến mức gây bực bội ở nhiều tầng. Tôi cũng hiểu SQLAlchemy là một thư viện khổng lồ nên không thể mọi thứ đều dễ. Dù vậy, ví dụ này cho thấy rõ sự đánh đổi khi dùng ORM
Tôi biết nếu dùng trực tiếp
insert()trong Core thì sẽ làm được như ý. Ở đây tôi đang nói đến trường hợp.add()một đối tượng ORM vàoAsyncSessionPhần lớn business logic nên được diễn đạt bằng ngôn ngữ của đại số quan hệ cùng vài phần mở rộng thì tốt hơn OOP
Câu “chi phí thật sự của việc tăng độ phức tạp, và thường là chi phí lớn hơn nhiều, là sự chú ý” cũng chính là tải nhận thức
Tôi đã mệt mỏi khi làm việc với các hệ thống microservice vẫn có downtime trong khi không ai biết toàn bộ hệ thống vận hành ra sao. Phần lớn thực ra là distributed monolith, nơi thay đổi trải trên nhiều service và phải triển khai theo thứ tự. Dữ liệu phải được sao chép, công việc phải được đồng bộ, và trạng thái phải được chia sẻ
https://www.youtube.com/watch?v=y8OnoxKotPQ
Nhưng nếu muốn sửa hoặc chỉnh hệ thống mà cần ai đó hiểu toàn bộ, đó là tín hiệu mạnh rằng bạn đã vi phạm các quy tắc như single responsibility hoặc abstraction đúng thông qua API. Dù vậy, theo kinh nghiệm của tôi, chuyện này rất phổ biến. Để debug một pipeline gồm N microservice, thường phải chạy và build cả N service trên máy local
Nói nghiêm ngặt thì đây là một monolith cộng thêm network partition và biến động build/deploy vô hạn. Cuối cùng, tôi xem đó là một môi trường làm việc cực kỳ khó, vượt quá năng lực của bất kỳ lập trình viên con người nào
Tôi thích bài này. Trong vài tháng qua tôi đã cố truyền đạt cùng thông điệp đó với quản lý, nhưng không thành công mấy
Cụm Redshift quá tải của chúng tôi đã sập nhiều lần, và vì đã nâng tối đa lên node RA3 rồi nên giờ chúng tôi sắp bắt đầu một đợt migration lớn sang “hạ tầng thế hệ tiếp theo”. Hạ tầng thế hệ tiếp theo ở đây nghĩa là ba cụm Redshift được quản lý bằng CDK
Hạ tầng mới phức tạp hơn hiện trạng rất nhiều, và tôi không chắc nó sẽ là viên đạn bạc mà mọi người kỳ vọng
Đây là giải pháp nhàm chán. Nếu không xây các hệ thống cực kỳ quan trọng liên quan trực tiếp đến sinh mạng và thân thể, nó nên là câu trả lời mặc định. Tổng chi phí sở hữu chắc chắn thấp hơn nhiều
Tôi đã thấy quá nhiều trường hợp nếu không có tài nguyên để vận hành một hệ thống dự phòng lớn, thì chính độ phức tạp mà hệ thống dự phòng thêm vào lại trở thành vấn đề. Tập trung vào sự đơn giản thì tốt hơn
Nếu để hỗ trợ độ phức tạp mà phải bổ sung nhiều người, trong khi xét về tiền bạc và đánh giá rủi ro thì không cần làm vậy, phương án đơn giản hơn tốt hơn rất nhiều. Không phải tôi chưa từng thấy những trường hợp cuối cùng cần một dự án khổng lồ để tiến lên, nhưng đôi khi ngay cả dự án đó vẫn nhỏ hơn tổng chi phí đã phải gánh để tiếp tục chịu đựng độ phức tạp cho đến thời điểm ấy. Điều này phụ thuộc rất nhiều vào thứ bạn đang xây dựng
Việc tìm ra các tối ưu hiệu năng trong hệ thống và vắt kiệt phần hiệu năng còn lại để có được giải pháp thật sự rất thú vị
Tôi nhớ đến cuốn Understanding_Software_Dynamics của Richard L. Sites. Cuốn sách này dạy cách đo lường và khắc phục các vấn đề về độ trễ, cũng như việc giảm độ trễ ở quy mô lớn có thể tạo ra mức tiết kiệm lớn đến mức nào
Việc đo lường và suy luận về những vấn đề như vậy thì khó, nhưng giải pháp thường lại đơn giản. Ví dụ, ở trang 9, ông nói: “[a] simple change paid for 10 years of my salary.”
Một ngày nào đó tôi cũng muốn thử thực hiện một tối ưu có sức ảnh hưởng như vậy
https://research.google/pubs/pub36575/
Tuy nhiên xung quanh cũng có rất nhiều người thông minh, nên nếu bạn tìm thấy một cơ hội lớn thì thường sẽ có lý do vì sao người khác chưa nhảy vào. Đó có thể là lý do kỹ thuật, cũng có thể là lý do tổ chức
Một ví dụ cho trường hợp sau: Google thường không thưởng lớn cho loại công việc này trừ khi đang có áp lực về tài nguyên. Có thể tôi đã nhận được khoảng 100 đô la tiền thưởng đồng nghiệp nhờ một tối ưu nào đó, nhưng hoàn toàn không có chuyện được hoa hồng 10%, thăng chức, hay quyền không đi làm trong 10 năm mà vẫn nhận lương. Nói chung, công ty muốn kỹ sư làm việc cho tăng trưởng doanh thu hơn là cắt giảm chi phí. Chính sách này có đúng hay không thì vượt quá bậc lương của tôi
Lúc đó có vẻ như họ không còn có thể nâng cấu hình thêm chỉ bằng vài cú nhấp trong console quản trị nữa, nên mới phải thật sự động não để giải quyết vấn đề dung lượng. Nếu tối ưu phần mã cụ thể đó sớm hơn, có lẽ ngay từ đầu đã không cần đến cấu hình instance lớn như vậy