Hướng dẫn php server side caching - bộ nhớ đệm phía máy chủ php
Bí quyết thành công trong việc đáp ứng hệ thống triệu user của những công ty lớn (và cả công ty nhỏ). Tại sao caching lại là kỹ thuật tối quan trọng để phù phép ứng dụng rùa bò của chúng ta thành siêu phẩm vạn người mê? Show Chắc chắn sẽ không phải nói quá khi khẳng định caching là kỹ thuật mà mọi developer đều cần phải biết. Từ backend tới frontend, từ web app tới mobile, hay thế giới mới lạ của ML và AI, blockchain... đều có sự tham gia của những thành phần làm nhiệm vụ caching. Caching có thể xuất hiện dưới hình thức to lù lù như dàn CDN ta hay thuê, hay nhỏ tí nị như chiếc bộ nhớ L1 của CPU.caching là kỹ thuật mà mọi developer đều cần phải biết. Từ backend tới frontend, từ web app tới mobile, hay thế giới mới lạ của ML và AI, blockchain... đều có sự tham gia của những thành phần làm nhiệm vụ caching. Caching có thể xuất hiện dưới hình thức to lù lù như dàn CDN ta hay thuê, hay nhỏ tí nị như chiếc bộ nhớ L1 của CPU. Có lẽ vì vậy mà chỉ cần search google với các từ khóa liên quan tới caching là ngay lập tức bạn sẽ bị choáng ngợp bởi số lượng kết quả và kiến thức liên quan. Vậy thì có cách nào để biết mình đang ở đâu trong thế giới cache bao la rộng lớn này, cũng như biết với level của mình hiện tại thì tiếp cận loại cache gì là phù hợp không?mình đang ở đâu trong thế giới cache bao la rộng lớn này, cũng như biết với level của mình hiện tại thì tiếp cận loại cache gì là phù hợp không? Câu trả lời, tất nhiên là có, và đó chính là điều mà series Caching đại pháp của mình truyền tải. Đây không phải là một series blog show off công nghệ hay sách giáo khoa giới thiệu cho các bạn mọi loại cache có trên đời mà là một con đường mình đã đi qua. Giờ đây các bạn có thể đi theo (hoặc tham khảo cho vui) để từng bước nâng cao trình độ bản thân.Caching đại pháp của mình truyền tải. Đây không phải là một series blog show off công nghệ hay sách giáo khoa giới thiệu cho các bạn mọi loại cache có trên đời mà là một con đường mình đã đi qua. Giờ đây các bạn có thể đi theo (hoặc tham khảo cho vui) để từng bước nâng cao trình độ bản thân. First things firstNhưng trước tiên, hãy tạm thời bình tĩnh, rót chén nước trà và nhâm nhi để tìm hiểu 1 chút về tác giả và nguồn gốc lịch sử của series này. Tác giả, tất nhiên là mình, Minh Monmen trong sự cố gắng làm thế giới trở nên tốt đẹp hơn (xàm xí thôi) bằng cách viết ra những bài viết có thể làm theo và có thể học hỏi / chửi bới hơn là những bài viết mang tính chất giới thiệu công nghệ khủng hay những hệ thống phức tạp của các công ty lớn.Minh Monmen trong sự cố gắng làm thế giới trở nên tốt đẹp hơn (xàm xí thôi) bằng cách viết ra những bài viết có thể làm theo và có thể học hỏi / chửi bới hơn là những bài viết mang tính chất giới thiệu công nghệ khủng hay những hệ thống phức tạp của các công ty lớn. Còn series này? Tất nhiên là được ra đời từ nhiều đêm trăn trở và nhiều lần được nghe câu hỏi: Ứng dụng của tôi chậm thế này, tôi phải làm thế nào? rồi.Ứng dụng của tôi chậm thế này, tôi phải làm thế nào? rồi. Thật ra thì series này cũng nằm trong kế hoạch năm 2021 của mình, chen giữa series mình đang thực hiện gần đây là Performance Optimization Guideline. Nếu bạn nào theo dõi thì sẽ biết bài tiếp theo của series đó sẽ là:
Bài viết tới này mình sẽ nêu lên những vấn đề về mặt performance khi động chạm tới hệ thống caching. Tuy nhiên điều mà mình vẫn băn khoăn là làm thế nào để người ta có thể tối ưu được hệ thống caching, trong khi còn chưa có hiểu biết đầy đủ về nó?. Chính vì vậy, series Caching đại pháp này được ra đời trước bài viết kia để chuẩn bị cho các bạn những kiến thức cần thiết để tiếp cận bài viết của mình hiệu quả hơn.làm thế nào để người ta có thể tối ưu được hệ thống caching, trong khi còn chưa có hiểu biết đầy đủ về nó?. Chính vì vậy, series Caching đại pháp này được ra đời trước bài viết kia để chuẩn bị cho các bạn những kiến thức cần thiết để tiếp cận bài viết của mình hiệu quả hơn. Nội dung của series Caching đại pháp này sẽ bao gồm 3 phần (dự kiến):Caching đại pháp này sẽ bao gồm 3 phần (dự kiến):
Hãy bắt đầu với phần đầu tiên: Nấc thang lên level của developer trước nhé.Nấc thang lên level của developer trước nhé. Level 0: Những concept cơ bảnĐôi điều về tất cả các loại cache mà bạn cần phải hiểu:tất cả các loại cache mà bạn cần phải hiểu:
Xong, đây là những đặc điểm chung của mọi loại cache mà bạn cần phải nhớ. Còn đây là tiêu chí để xem xét có cần cache cái này không:có cần cache cái này không:
Đây cũng là điểm tối quan trọng, luôn giữ trong đầu 2 tiêu chí này để xác định có cần cache không nhé. Ví dụ:
The bigger pictureBức tranh tổng quan về hệ thống caching thường gặp do mình tự vẽ từ kiến thức của bản thân, do đó còn nhiều thiếu sót rất mong các bạn có thể góp ý bổ sung thêm. Ở đây các bạn có thể nhìn thấy 4 layer chính khi nói tới 1 application phổ biến là: Client side, proxy, application và database. Tại mỗi layer này thì đều có những hệ thống cache tương ứng và chúng ta có thể có các mức độ kiểm soát khác nhau. Ngoài ra còn 1 layer ẩn chính là lớp OS / Kernel mà dev cỏ chúng ta gần như không kiểm soát được. Client side: là layer tại device của người dùng (mobile app, browser) là layer tại device của người dùng (mobile app, browser) Đặc điểm: Caching phục vụ trải nghiệm của 1 người dùng. Do đó việc cache cái gì và cache bao lâu sẽ phục vụ trải nghiệm người dùng chứ không phải hệ thống.1 người dùng. Do đó việc cache cái gì và cache bao lâu sẽ phục vụ trải nghiệm người dùng chứ không phải hệ thống. Tại lớp này chúng ta có 1 phần quyền kiểm soát thông qua việc:1 phần quyền kiểm soát thông qua việc:
1 phần quyền kiểm soát là do các hoạt động tương tác với cache sẽ tốn thời gian, công sức và khó sửa chữa khi có vấn đề xảy ra. Proxy / LB: là các layer trung gian trước khi request của người dùng tới được application của chúng ta. Các lớp này có thể là CDN, Reverse proxy, Gateway,... là các layer trung gian trước khi request của người dùng tới được application của chúng ta. Các lớp này có thể là CDN, Reverse proxy, Gateway,... Đặc điểm: Caching tại các lớp trung gian chủ yếu phục vụ content tĩnh cho số lượng lớn người dùng.content tĩnh cho số lượng lớn người dùng. Tại lớp này chúng ta có phần lớn quyền kiểm soát thông qua việc:phần lớn quyền kiểm soát thông qua việc:
Phần lớn quyền kiểm soát là do việc tương tác với cache có thể thực hiện 1 cách tự động, tuy nhiên sẽ tốn công sức và bị phụ thuộc vào bên thứ 3 khi muôn giải quyết các vấn đề xảy ra. Application: là lớp cache tại application. là lớp cache tại application. Đặc điểm: Caching phục vụ content động cho số lượng lớn người dùng.content động cho số lượng lớn người dùng. Tại lớp này chúng ta có toàn quyền kiểm soát thông qua việc:toàn quyền kiểm soát thông qua việc:
Toàn quyền kiểm soát là việc chúng ta chủ động quyết định cache cái gì, ở đâu và dễ dàng tương tác, chỉnh sửa,... hệ thống cache do hệ thống này hoàn toàn vô hình với người dùng và ít bị phụ thuộc vào bên thứ 3. Database: là lớp cache tại database. là lớp cache tại database. Đặc điểm: Caching phục vụ truy xuất dữ liệu.truy xuất dữ liệu. Tại lớp này, mình chỉ xem xét các bạn là những người dùng database, do đó các bạn cũng sẽ chỉ có 1 phần quyền kiểm soát đối với việc database sẽ cache thứ gì hay như thế nào thông qua:người dùng database, do đó các bạn cũng sẽ chỉ có 1 phần quyền kiểm soát đối với việc database sẽ cache thứ gì hay như thế nào thông qua:
1 phần quyền kiểm soát là việc chúng ta chỉ có thể coi database là 1 cái blackbox và optimize dựa trên các thông số được recommend của nhà cung cấp. OS / Kernel: là lớp cache của OS/ Kernel xuất hiện tại mọi thành phần của hệ thống. là lớp cache của OS/ Kernel xuất hiện tại mọi thành phần của hệ thống. Đặc điểm: Caching phục vụ xử lý dữ liệu.xử lý dữ liệu. Tại lớp này, chúng ta gần như không có quyền kiểm soát đối với việc OS sử dụng các bộ nhớ để cache ra sao. Đối với phần lớn developer thì cũng chưa cần phải đi sâu vào lớp này nhiều làm gì. Tối ưu tại lớp này thường liên quan tới Micro-optimization và chưa thật sự cần thiết với chúng ta.không có quyền kiểm soát đối với việc OS sử dụng các bộ nhớ để cache ra sao. Đối với phần lớn developer thì cũng chưa cần phải đi sâu vào lớp này nhiều làm gì. Tối ưu tại lớp này thường liên quan tới Micro-optimization và chưa thật sự cần thiết với chúng ta. Level 1: Monolith webpage with single serverMới tập tọe làm web, chắc các bạn cũng sẽ như mình, sẽ bắt đầu với những ứng dụng kiểu cũ: monolithic, chạy trên 1 server, render data html,... Chúng ta hãy cùng phân tích 1 chút về đặc điểm ứng dụng tại level này nhé:kiểu cũ: monolithic, chạy trên 1 server, render data html,... Chúng ta hãy cùng phân tích 1 chút về đặc điểm ứng dụng tại level này nhé:
Đây là những thứ mà ứng dụng này bị chậm:
Đây là những thứ mình sẽ tối ưu bằng caching: Cụ thể:
Các loại RDBMS như MySQL, PostgreSQL,... đều có cơ chế query cache ngay trong DB, chỉ cần config bật lên là được. Các bạn có thể google search về từng loại database cache với từ khóa cache Các ứng dụng ở level này có mức độ reuse query rất cao giữa các user cũng như cùng 1 user request trang có nhiều phần lặp lại. Phần này không cần control quá nhiều ở data cache nên có thể dùng luôn query cache trong DB. 1 điểm nữa để các bạn consider DB cache là data size của bạn. Nếu data size còn nhỏ và có thể chứa toàn bộ data trong RAM của DB thì bật Query cache là đủ. Ví dụ bật cache trên MySQL:
Sử dụng file để làm cache cho các thành phần phải render từ DB. Ưu điểm:
Wordpress, xenforo,... đều đã có plugin. Các framework sử dụng view engine cũng hỗ trợ cache result html.
Ví dụ việc cache full page trên laravel:
Các bạn đẩy các file media như video,image,... ra các CDN (Content Delivery Network). Bản chất CDN là các hệ thống cache theo vị trí địa lý, giúp người dùng ở VN hay người dùng US khi request media file cho ứng dụng đều không bị chậm. Đây là thứ ảnh hưởng rất lớn đến trải nghiệm của người dùng trên ứng dụng, do đó cũng cần được xem xét để tách ra ngay từ những bước tối ưu đầu tiên. Để sử dụng được CDN cho media thì các bạn phải làm mấy việc:
Có rất nhiều các nhà cung cấp S3-like storage trên thế giới như AWS, GCP, Digital Ocean,... hay tại VN như các công ty làm cloud. Bạn có thể tùy ý lựa chọn. Kết quả: Thời mới đi làm mình đã sử dụng file cache để tối ưu 1 trang báo xây dựng bằng xenforo, giúp giảm thời gian load 1 trang html từ 2s xuống 200ms, giảm thời gian load toàn bộ trang từ 18s xuống 8s bằng việc bật cache lại các query result, các html part trong 1 page và sử dụng CDN cho media file. Những action này can thiệp rất ít tới code hệ thống, chủ yếu là config và cài đặt plugin. Thời mới đi làm mình đã sử dụng file cache để tối ưu 1 trang báo xây dựng bằng xenforo, giúp giảm thời gian load 1 trang html từ 2s xuống 200ms, giảm thời gian load toàn bộ trang từ 18s xuống 8s bằng việc bật cache lại các query result, các html part trong 1 page và sử dụng CDN cho media file. Những action này can thiệp rất ít tới code hệ thống, chủ yếu là config và cài đặt plugin. Level 2: Monolith webpage with multiple serverTiến hóa lên level 2, mình làm quen với hệ thống có nhiều server với lượng traffic lớn hơn mặc dù ứng dụng thì không khác mấy. Cache tại level này mình sẽ có thêm nhiệm vụ tăng khả năng đáp ứng của hệ thống, còn thời gian response 1 page thì có thể giảm hoặc giảm ít hơn chút so với level 1 là được rồi. Điểm qua 1 vài đặc điểm ứng dụng hiện tại:
Đây là những loại cache mình sử dụng cho ứng dụng này: Cụ thể:
Query cache của database có 1 điểm bất lợi là locking và có thể khiến performance tổng thể của DB đi xuống. Do đó ở đây mình move việc cache kết quả ra khỏi database và chuyển hoàn toàn xuống tầng application. Do application chạy trên nhiều server nên ưu tiên lúc này chuyển sang tính đúng đắn của dữ liệu nhiều hơn, nên mình đã chuyển từ file cache (chỉ chạy trên từng server) sang hệ thống cache riêng sử dụng Redis / memcache. Ngoài ra mình sẽ cần 1 bộ nhớ cache chung để nâng cao hiệu quả cache, và lúc này dùng redis/memcache được cài đặt trên server riêng sẽ rất hiệu quả. Lúc này mình tập trung vào cache mấy cái:
Ví dụ cache query result với laravel:
Phần này chỉ có tác dụng với những ngôn ngữ thông dịch kiểu PHP, việc bật cache operation code với những code base to và nặng sẽ giúp cải thiện đáng kể performance của ứng dụng và giảm thời gian 1 request đi kha khá. Ở đây mình đã bật cache Opcode với opcache. Chi tiết tham khảo chị gu gờ nhé.
Mình tiếp tục sử dụng CDN cho các static content dạng css, js, font,... Để sử dụng CDN cho css, js thì các bạn phải làm mấy việc:
Sử dụng cache toàn trang trên reverse proxy như nginx, haproxy để cache lại toàn bộ html page. Để sử dụng cache toàn trang thì các bạn phải làm mấy việc:
Đây là biện pháp để dừng request của người dùng ngay tại lớp Proxy/LB và giảm tải cho ứng dụng, là 1 trong những chiêu thức quan trọng và hữu hiệu nhất với các hệ thống dạng bài viết. Vừa cải thiện đáng kể trải nghiệm của user trên trang và tăng khả năng đáp ứng lượng traffic lớn của hệ thống. Ví dụ config cache trên nginx:
Kết quả: Mình đã tối ưu 1 trang web livestream (monolith, multi server) bằng việc tách phần tĩnh (là phần html) ra để cache toàn trang và phần get link live (động cho từng user) chuyển qua ajax. Kết hợp với CDN cho static asset và redis cho các data object đã giúp mình tăng số CCU mà hệ thống có thể chịu được lên rất nhiều. Mình đã tối ưu 1 trang web livestream (monolith, multi server) bằng việc tách phần tĩnh (là phần html) ra để cache toàn trang và phần get link live (động cho từng user) chuyển qua ajax. Kết hợp với CDN cho static asset và redis cho các data object đã giúp mình tăng số CCU mà hệ thống có thể chịu được lên rất nhiều. Level 3: Web API with SPATiếp tục lên tới level 3, khi ứng dụng của mình mở rộng tới mobile và web SPA. Việc của mình là phải tối ưu API để response của 1 request chỉ từ 50ms - 100ms. Hãy cùng điểm qua vài đặc điểm của các Web API và Web SPA:
Ở level này, việc tách biệt hoàn toàn phần static data như html, js, css,... ra khỏi phần data đã giúp cho caching trở nên dễ dàng hơn kha khá. Tại level này, mình đã focus vào các yếu tố sau:
Cụ thể là:
Tối ưu việc cache data object bằng redis, memcache thông qua theo dõi tỷ lệ cache hit/miss và sửa đổi các luồng API get data. Chỗ này thì đã làm từ trước rồi mình sẽ không nói thêm nữa.
Phần này thực hiện dễ hơn so với level trước, do các framework JS hiện đại đã làm sẵn việc tách html, css, js ra thành các file tĩnh và có thể dễ dàng cache lại trên CDN hơn so với trước đây.
Vì client phải gọi nhiều request tới server hơn, do đó lúc này các bạn sẽ cần quan tâm nhiều hơn tới trải nghiệm người dùng và phải cải thiện nó thông qua việc can thiệp vào client cache thông qua HTTP header. Client cache bằng Header sẽ có mấy kiểu:
Kết quả: Mình đã tối ưu 1 hệ thống thương mại điện tử dạng webview nhúng trong app với thời gian load rất ấn tượng, chờ khoảng 50ms để bắt đầu load content và load hết toàn trang mất 3-4s. Mình đã tối ưu 1 hệ thống thương mại điện tử dạng webview nhúng trong app với thời gian load rất ấn tượng, chờ khoảng 50ms để bắt đầu load content và load hết toàn trang mất 3-4s. Level 4: MicroservicesLên đến level 4, lúc này mình focus vào tối ưu nhiều hơn các hệ thống xử lý dữ liệu (do phần static asset đã tách biệt hoàn toàn và xử lý xong ở level trước rồi). Hãy cùng điểm qua 1 vài đặc điểm của hệ thống này:
Lúc này, bài toán caching với micro services trở nên chuyên biệt hơn và cần phải có cách xử lý đáp ứng nhiều yếu tố hơn chứ không chỉ cache xong là xong nữa.cache xong là xong nữa.
Wow, dùng nhiều quá phải không? Tất nhiên là nó phải có tính kế thừa từ những level trước rồi. Có nhiều cái đã dùng ở level trước, nhưng giờ tiếp tục dùng nhưng ở level cao hơn.
Thật ra cái này không liên quan nhiều tới cache lắm mà là tối ưu database nhiều hơn. Ở đây với tư cách là devops và người thiết kế hệ thống thì mình sẽ phải đảm bảo config database tối ưu cho việc cache lại index và hot data trên RAM. Việc này sẽ gồm rất nhiều các việc nhỏ hơn kiểu:
Tuy nhiên về mặt tổng thể thì nó vẫn là cache, do đó mình vẫn đưa vào đây.
Mặc dù vẫn là cache data object đã implement từ những level trước, nhưng đối với hệ thống micro services thì việc sử dụng hiệu quả loại cache này trở thành yếu tố tối quan trọng của hệ thống. Ở đây mình sử dụng chủ yếu 2 loại storage là: 3rd storage (redis, memcache) và memory (hashmap, variable). Lúc này việc lựa chọn storage quan trọng hơn nhiều so với các level trước và đây là những yếu tố bạn phải cân nhắc:3rd storage (redis, memcache) và memory (hashmap, variable). Lúc này việc lựa chọn storage quan trọng hơn nhiều so với các level trước và đây là những yếu tố bạn phải cân nhắc: 3rd storage (redis, memcache) cho khả năng scale và performance rất tốt nhờ cluster, phù hợp với đa số trường hợp. Memory cache (hashmap, variable) có khả năng scale và hiệu quả thấp hơn do chỉ tồn tại trên từng app instance, nhưng tốc độ sẽ nhanh hơn rất nhiều so với remote cache như redis. Do đó nó phù hợp với những ứng dụng đặc thù có yêu cầu performance rất cao. Bọn mình đã phải tối ưu để nhiều service có latency < 1ms thông qua việc sử dụng memory cache hợp lý. cho khả năng scale và performance rất tốt nhờ cluster, phù hợp với đa số trường hợp. Memory cache (hashmap, variable) có khả năng scale và hiệu quả thấp hơn do chỉ tồn tại trên từng app instance, nhưng tốc độ sẽ nhanh hơn rất nhiều so với remote cache như redis. Do đó nó phù hợp với những ứng dụng đặc thù có yêu cầu performance rất cao. Bọn mình đã phải tối ưu để nhiều service có latency < 1ms thông qua việc sử dụng memory cache hợp lý. Chi tiết hơn về việc chọn các loại cache mình sẽ nói ở bài viết sau.
Tại level này thì việc sử dụng cache reverse proxy và CDN đã trở thành cơ bản, tuy nhiên để cache được API response thì các bạn phải rất hiểu về từng endpoint của mình: cái nào cần cache và cache bao lâu. Việc này sẽ khá tốn thời gian để implement Cache header cho từng loại endpoint cũng như rà soát vấn đề toàn vẹn dữ liệu, do vậy mình không khuyến khích mọi người làm nó quá sớm nếu chưa thật sự có traffic khủng khiếp.
Tại level này, các ứng dụng client đã tương đối phức tạp và việc tối ưu trải nghiệm người dùng trở nên quan trọng hơn. Do đó anh em client sẽ tiến thêm 1 bước trong việc chủ động cache lại data trên client. Việc này giống như facebook vẫn show được bài viết khi ứng dụng offline vậy. Việc cache lại data trên client sẽ giảm được rất nhiều request tới server, tuy nhiên mình cũng không khuyến khích các bạn làm quá sớm, vì dữ liệu cache trên client rất khó quản lý và nếu không cẩn thận có thể gây ra những vấn đề về toàn vẹn dữ liệu dở khóc dở cười luôn. Level 5: HardcoreThật ra level này mình cũng chưa đạt tới, chỉ nghe đồn là các tiền bối ở đây sẽ tối ưu tới tận cách dùng memory của OS, tới tận việc dùng L1, L2, L3 của CPU,... Nghe đã thấy sợ hãi rồi nên là thôi bỏ qua nhé. Tổng kếtTrên đây là con đường mình đã đi qua để có thể nâng cao dần hiểu biết của bản thân liên quan đến caching. Các bạn sẽ thấy nó tương ứng với từng thời kỳ, từng sản phẩm mình đã trải qua và có độ phức tạp từ thấp tới cao. Có thể con đường của các bạn sẽ khác khi tiếp cận từ định nghĩa, các loại cache nói chung, cách implement,... và có thể sẽ hơi loạn loạn 1 chút khi không biết với bài toán này thì mình sẽ cần những loại cache gì. Hy vọng là thông qua con đường của mình, các bạn sẽ có 1 cái nhìn mới lạ, đi từ thực tế và sát hơn với những gì các bạn đang làm hàng ngày. Trong bài viết sau, mình sẽ nói kỹ hơn 1 số trường hợp cache cụ thể mà mình đã trải qua và các yếu tố để lựa chọn giải pháp cache nhé. Link phần 2: Caching đại pháp 2: Cache thế nào cho hợp lý? P/s: Hãy ủng hộ tác giả bằng việc upvote + clip bài viết và series này nhé!upvote + clip bài viết và series này nhé! Bái bai. |