Thứ Sáu, 17 tháng 3, 2017

Buffers và Cached Part I

Tác giả:
1. Trả lời ngắn
Cached là kích thước của page cache.
Buffers là kích thước của in-memory block I/O buffers
2. Trả lời dài:
Cả Cached và Buffers đều có ý nghĩa là vùng lưu trữ tạm, nhưng mục đích sử dụng thì khác nhau, tổng quan thì có một số điểm sau:
Mục đích của cached là tạo ra một vùng nhớ tốc độ cao nhằm tăng tốc quá trình đọc/ghi file ra đĩa, trong khi buffers là tạo ra 1 vùng nhớ tạm có tốc độ bình thường, mục đích để gom data hoặc giữ data để dùng cho mục đích nào đó.
Cached được tạo từ static RAM (SRAM) nên nhanh hơn dynamic RAM (DRAM) dùng để tạo ra buffers.
Buffers thường dùng cho các tiến trình input/output, trong khi cached chủ yếu được dùng cho các tiến trình đọc/ghi file ra đĩa
Cached có thể là một phần của đĩa (đĩa có tốc độ cao) hoặc RAM trong khi buffers chỉ là một phần của RAM (không thể dùng đĩa để tạo ra buffers).

2.1 Cached

Cached là kích thước của Linux page cache, không bao gồm bộ nhớ trong swap cached thường được gọi là SwapCached (như vậy tổng kích thước page cache là Cached + SwapCached). Linux thực thi tất cả các thao tác I/O file thông qua page cache. Vùng nhớ này được dùng để tăng tốc quá trình đọc ghi file theo mô tả dưới đây.
Write được implement rất đơn giản là đánh dấu các trang tương ứng trong page cache là dirty (dirty corresponding pages), các flusher thread sau đó sẽ định kỳ ghi vô đĩa bất kỳ một dirty page nào. Có thể xem ví dụ sau để hiểu về cơ chế ghi
~$ dd if=/dev/zero of=/tmp/test.txt bs=1M count=10 && grep -i dirty /proc/meminfo && sync && grep -i dirty /proc/meminfo 
10+0 records in 
10+0 records out 
10485760 bytes (10 MB, 10 MiB) copied, 0.00854088 s, 1.2 GB/s 
Dirty: 712 kB 
Dirty: 0 kB

Giải thích như sau:
Lệnh đầu tiên ghi 1 file có kích thước 10MB
Như ta thấy thì dữ liệu của file được đánh dấu là dirty trong page cached bằng cách kiểm tra trong lệnh số 2, ở đây là 712 kB được đánh dấu là dirty
Lệnh số 3 giúp ta buộc sync dữ liệu từ page cached vào đĩa
Lệnh số 4 kiểm tra lại trong page cached xem có dữ liệu nào được đánh dấu dirty hay không, như ta thấy thì không còn (lưu ý là có thể >0 kB do có các tiến trình khác)
Kernel linux có một tiến trình là flush để định kì ghi dữ liệu từ page cached vào đĩa, có thể kiểm tra như saups -eaf | grep -i [f]lush root 867 2 0 Apr26 ? 00:00:20 [flush-8:0]

Read được implement bằng cách trả về dữ liệu từ page cached, nếu dữ liệu đó không có trong cached, data đó sẽ được di cư lần đầu tiên từ đĩa vào page cache. Trên các hệ thống Linux hiện đại, cached dễ dàng có thể lên tới hàng GB, và nó sẽ co giãn để đáp ứng áp lực của bộ nhớ. Hệ thống sẽ "xóa" page cache cùng với việc swap data từ page cache ra đĩa để làm trống bộ nhớ nhiều hơn nếu cần.
2.2 Buffers
Buffers là vùng đệm mục đích để tổ chức và giữ dữ liệu trong một vùng nhớ nào đó cho đến khi dữ liệu này được chuyển qua nơi khác. Thông thường buffers được dùng trong các quá trình input/output mà tốc độ nhận và xuất dữ liệu khác biệt lớn ( CPU và máy in).
Ví dụ
Thao tác in văn bản: CPU là thiết bị có tốc độ cao, trong khi máy in là một thiết bị có tốc độ xử lí chậm. Khi một người ra lệnh in, dữ liệu in sẽ được đẩy vào vùng buffers (điểm khác biệt với cached là vùng này không cần tốc độ cao). Sau đó máy in có thể truy cập vào vùng buffers đó với tốc độ rùa bò trong khi CPU đã đc giải phóng để đi làm nhiệm vụ khác.
Thao tác burn đĩa CD: quá trình tương tự máy in nhưng có một điểm là nếu data có kích thước nhỏ, khi được đưa vào vùng buffers thì các data này sẽ được gom lại thành từng block có kích thước bằng kích thước của block size .Trước Linux kernel 2.4, có 2 loại cached riêng biệt, file thì trong page cache, disk block thì trong buffers cache. Đây là một cách đơn giản để implement, nó khá rõ ràng nhưng kém hiệu quả. Từ phiên bản 2.4, nội dung của 2 loại cache này được hợp nhất.~$ free -m total used free shared bufferss cacheddMem: 15950 14771 1179 0 248 10306-/+ bufferss/cached: 4216 11733Swap: 0 0 0Như ta thấy dòng -/+ bufferss/cached đã được hợp nhất, nếu cộng cột buffers và cached ở dòng thứ nhất và cột free của dóng số 1 sẽ thấy bằng tổng cột số 3 dòng số 3
1179 + 248 + 10306 = 11733
Next-step: tìm hiểu thuật toán áp dụng cho page cache và buffers (khả năng là LRU với page cache và FIFO với buffers, nên ta thấy buffers khá là giống queue)
Nhận xét của người đọc.
Page Cache hay còn gọi là Buffer Cache trong Linux nằm trên DRAM nhé, trong khi Swap Cache nằm trên ổ cứng. Nếu sử dụng lệnh free-m thì nó chính là column cuối cùng:
[root@testserver ~]# free -m
total used free shared buffers cached
Mem: 15976 15195 781 0 167 9153
-/+ buffers/cache: 5874 10102
Swap: 2000 0 1999
Mục đích của Page Cache giúp OS lấy data nhanh hơn, ví dụ muốn đọc lại data (mà không cần phải chui vào hard-disk, CDROM rất chậm).
"Cached được tạo từ static RAM (SRAM) nên nhanh hơn dynamic RAM (DRAM) dùng để tạo ra buffers"
Câu này khá tối nghĩa. SRAM (được dùng để build lên L1, L2, L3, L4 cache) là bộ nhớ của CPU và được CPU dùng lưu tạm data khi cần save data khi switching context (xử lý với OS multi-task), chứ không phải được tạo ra từ SRAM (SRAM cũng chỉ là 1 volatile storage mà thôi). Cache này hoàn toàn # với Page Cache / Buffer Cache.
Thêm một chút về English:
Cache (két) vùng nhớ giúp việc đọc ra được nhanh hơn. Nếu hiểu theo nghĩa tổng quát thì cache hoàn toàn có thể nằm trên ổ cứng, ví dụ các app server thay vì generate động file html, thì lưu các file html lần đầu gọi vào cứng, sau này cần file này lần nữa, sẽ gọi ra và trả về, chứ không cần chạy 1 script rất chậm chạp nữa.
Buffer (đệm) các app thường sử dụng các vùng unused memory để lưu tạm trước khi ghi vào các thiết bị non-volatile storage. Trước kia, nếu ghi vào ổ cứng mỗi lần có dữ liệu, một sẽ khiến ổ cứng move đầu đọc nhiều lần và 2 là dữ liệu ghi vào có thể bị phân mảnh. Thay vào đó, dữ liệu được gom lại thành 1 gói to và ghi 1 lần mà thôi."Buffers thường dùng cho các tiến trình input/output, trong khi cached chủ yếu được dùng cho các tiến trình đọc/ghi file ra đĩa"
Mình nghĩ câu này cũng nên sửa lại. Nếu chơi LOL hẳn bạn biết con buff làm gì ^^ Cũng như vậy, buffer giúp bảo vệ đầu ghi khi thao tác in/out với các thiết bị không đồng bộ về tốc độ, còn cached giúp cho app đọc dữ liệu nhanh hơn, thay vì đọc trong ổ cứng, đâu liên quan nhiều tới đọc/ghi file ra đĩa. Đa phần cached còn nằm trên RAM cho nhanh.Nếu coi OS như một app to (process id = 1) chuyên quản lý các app con (process) thì OS dùng buffer để move dữ liệu dần dần sang HDD (bản thân HDD cũng có buffer nhé), sang CDROM, printer, ... còn cached để ghi tạm data khi tính toán xong, ..., giúp lấy ra nhanh hơn (nhất là khi OS đa nhiệm, nó phải liên tục làm việc với nhiều app trong 1 khoảng thời gian nào đó). Chính vì thế, buffer thường được ví với cơ chế FIFO vì giống như việc move 1 data stream từ nơi này sang nơi kia, move xong là xoá. Còn cached thì là cơ chế "Most used", nghĩa là dùng nhiều thì còn, dùng ít thì chuyển sang Swap, ít nữa hoặc k dùng thì clear. Thế nên, nói tới cached là phải nói tới TTL (Time to live, thời gian sống), cache hit/miss (khi cần dữ liệu, nó sẽ tìm RAM trước, xong Swapp, xong mới là ổ cứng. Cache hit càng cao chứng tỏ cache càng hiệu quả và nhanh. Nói tới cached là nói tới việc miss, mất sync) và random access (truy cập ngẫu nhiên qua offset)
OS đa nhiệm sẽ cấp phát / thu hồi 1 Virtual Memory mà app yêu cầu, giống như cách mà app trong OS đơn nhiệm làm với Real Memory. Cái này giúp isolate môi trường chạy, giúp việc đa nhiệm dễ dàng hơn và data trên RAM bảo toàn được tính consistent.
"Nếu sử dụng lệnh free-m thì nó chính là column cuối cùng: ý này mình chưa hiểu, cột cuối ở đây ý bạn là cached?
Phần cuối: mình biết cache tổng quát nó là gì, mục đích bài viết của mình là để hiểu rõ khái niệm cached và buffers trong việc quản lý bộ nhớ trên Linux. Bạn sẽ thấy nó có lợi ích là tại sao khi bạn check memory free từ lệnh free -m thì xem cột free của hàng -/+ buffers/cache chứ không phải cột free của hàng Mem hay tại sao server của bạn lúc nào "trông như là" xài hết memory"
Tại sao lại không sử dụng được cột cuối cùng? Trong ví dụ của bạn, OS đã cache mất 10 MB, bạn vẫn còn unused memory và không config swap cached. Quá đơn giản mà. Còn khái niệm free thì cũng tuỳ cách hiểu thôi, free = unused + cached + buffer có gì sai đâu? Buffer thì dùng xong clear, hiển nhiên sẽ là free, còn cached thì OS tận dụng tối đa để serve "page fault", nếu giờ app cần thì hiển nhiên cached sẽ bị clear, dành cho app.Ngoài lề, rất nhiều bạn phát âm từ này sai cached = "cấch", cách đọc đúng phải là "kés", giống như cái két đựng tiền ý (cơ chế hoạt động như vậy).
Mình biết bạn hiểu cached và buffer, tuy nhiên nhiều info mình nghĩ chưa đúng thì mình comment thôi. Kiến thức được built từ tranh luận mà.
@xluffy ok bạn. Mình góp thêm 1 ý nữa là: việc không config SwapCache là một bad practice, trừ phi bạn quá tự tin vào dung lượng RAM của mình. Việc các app chạy bị lỗi, nhất là lỗi memory leak (khi bị queue, khi bị crash, ...) mình hoàn toàn không thể kiểm soát được. Do đó, có 1 RAM ảo (gấp 2 là ổn nhất, vì sẽ save được 2 lần data ở RAM thật) để đỡ cho các trường hợp này là cần thiết.
@xluffy Mình đâu có bảo là dùng Swap là main memory nhỉ. Swap dùng để đề phòng những trường hợp bất khả kháng thôi, chứ còn khi monitor hardware trên production thì thường theo tỷ lệ 80:20, nghĩa là RAM hay CPU luôn được dùng ở mức 80% là ngon nhất. Khi còn unused RAM thì OS đâu cần "ném" data xuống Swap làm gì?
Thực tế là mình có một con production 80GB RAM, mình config toàn bộ InnoDB buffer trên RAM hết (hoạt động giống y in-memory db với datasize khoảng 60GB). Khi nào OS có dấu hiệu dùng trên 80% RAM là newrelic.com ném notification xuống phone cho mình để mình lên monitor rồi. Cái SwapCache config thế thôi, chứ read/write hầu như = 0 luôn.
Nếu bạn không config, vào một ngày đẹp trời, app crash, memory leak là cả con server đứng hình / treo / hỏng luôn thì sao. Phòng bệnh hơn chữa bệnh mà.

Không có nhận xét nào:

Đăng nhận xét