You are on page 1of 40

DIJKSTRA ẤN PHẨM CHUYÊN ĐỀ CHO KỸ SƯ PHẦN MỀM NGƯỜI VIỆT

TẬP 1 | THÁNG 04 - 2018

THIẾT KẾ HỆ THỐNG QUẢN LÝ


DANH MỤC SẢN PHẨM TRONG
HỆ THỐNG ECOMMERCE tr.08
CHUYÊN ĐỀ

FLOATING POINT VÀ SAI SỐ


TRONG TÍNH TOÁN tr.24
GROKKING’S CORNER

KĨ SƯ PHẦN MỀM GIỎI THÌ


PHẢI NHƯ THẾ NÀO? tr.30

NHÀ XUẤT BẢN ĐỒNG NAI


Mục lục
TẬP 1 | THÁNG 04 - 2018

05 The
Về Grokking Vietnam
Grokking Team

08 Thiết kế hệ thống quản lý danh mục


sản phẩm trong hệ thống eCommerce
Lê Minh Nghĩa - Tiki.VN

14 Kipalog
Lock Free Programming

18 LêHTTP/1 và HTTP/2
Nguyên Dũng

22 PostgreSQL
nào?
Buffer hoạt động như thế

Phạm Hữu Luân

24 Floating Point và sai số trong tính toán


Phú Trần

28 Thiết kế tính năng Feature Toggle &


Feature Rollout

Grokking Việt Nam


30 Grokking’s Corner: Kĩ sư phần mềm giỏi
thì phải như thế nào? Xây dựng hệ sinh thái cho cộng
Nguyễn Văn Quang Huy
đồng kỹ sư phần mềm trình độ
33 Sự hình thành và phát triển của các cộng
đồng công nghệ ở Việt Nam
cao ở Việt Nam
The Grokking Team

38 Sách hay nên đọc

2 DIJSKTRA
Lời mở đầu Grokking Vietnam
Bạn đọc thân mến,
Chịu trách nhiệm xuất bản
Bạn đang cầm trên tay tập đầu Võ Thành Lộc
tiên của ấn phẩm Dijkstra - ấn
phẩm chuyên đề dành cho kỹ sư Biên tập
phần mềm người Việt - kết quả Phạm Thanh Thuý
của một thời gian dài thai nghén ý Phạm Hữu Luân
tưởng của đội ngũ Grokking Viet- Đỗ Anh Thông
nam.
Thiết kế và dàn trang
Trong ấn phẩm này, nhóm biên Đỗ Anh Thông
soạn sẽ cố gắng cung cấp những Nguyễn Thị Minh Tâm
bài viết chuyên sâu về lĩnh vực công nghệ phần mềm, những bài phân tích
kiến trúc, những bài viết về văn hóa, cộng đồng và các bài viết về kiến thức Cộng tác nội dung
nền tảng khoa học máy tính. Để đảm bảo tính chính xác cũng như tính cập Nguyễn Văn Quang Huy
nhật, những bài viết này sẽ được viết bởi chính những kỹ sư phần mềm đang Lê Minh Nghĩa
làm việc trong những công ty phần mềm tại Việt Nam hoặc nước ngoài. Lê Nguyên Dũng
Phú Trần
Trong quá trình biên soạn tờ ấn phẩm này sẽ không tránh khỏi những sơ Đỗ Xuân Huy
suất, nhóm biên soạn mong nhận được những ý kiến đóng góp để nhóm Phạm Hữu Luân
biên soạn có thể không ngừng nâng cao chất lượng bài viết của ấn phẩm Khắc Anh
trong những số sau.
Cùng với sự góp ý của các bạn
trong nhóm Grokking Research

GROKKING VIETNAM Mọi bài vở, ý kiến đóng góp xin


vui lòng gửi về dijkstra@grokking.
org

DIJSKTRA 3
v

grokking
Thành lập năm 2014
từ 3 founders, Grokking hiện có đội ngũ
nhân sự vận hành xấp xỉ 20 người và cộng
đồng Slack với hơn 1000 thành viên tham
gia trên cơ sở tình nguyện, và cùng hướng
tới một sứ mệnh chung:

“Xây dựng hệ sinh thái cho cộng


đồng kỹ sư phần mềm trình độ cao ở Việt
Nam”

4 DIJSKTRA
GROKKING
VIỆT NAM
Grok (v) /grok/ to understand something so profoundly that it fully absorbed in oneself

Thân chào các bạn, nhiều người hiện nay là một Outsourcing Hub.

Đ ã gần ba năm kể từ hoạt động đầu tiên (11/2014), đội ngũ


Grokking Vietnam đã đi qua một chặng đường dài với
nhiều dự án được tổ chức như Tech Talks, Hackathon, Train-
Bạn Huy - founder của Grokking đã chia sẻ: “Kĩ sư Việt Nam
thực sự rất giỏi, rất lành nghề nếu tính trên phương diện out-
sourcing, nhưng điều làm kĩ sư Việt Nam thua xa Singapore và
ing Course, … nhưng có nhiều bạn vẫn chưa thực sự hiểu Mỹ là thiếu tư duy nền tảng”.
được Grokking là gì. Do đó, trong số đầu tiên của DIJIKSTRA,
chúng mình muốn nhân cơ hội này để giới thiệu lại về tổ chức Và sau đây là những điều chúng mình tin tưởng sẽ giúp rút
Grokking Vietnam, về quá trình thành lập cũng như những giá ngắn khoảng cách đó:
trị mà Grokking Vietnam đang theo đuổi. Mong rằng từ đây,
những ai cảm thấy phù hợp với những giá trị Grokking mang
lại sẽ có động lực đến với chúng mình nhiều hơn, còn những ai
nhìn thấy những cơ hội mà Grokking bỏ lỡ, sẽ giúp chúng mình
nhận ra và phát triển để đạt tới tầm kỳ vọng của mọi người.

GROKKING – MỘT TỔ CHỨC KHÔNG VÌ LỢI NHUẬN


Bắt đầu hoạt động đầu tiên vào năm 2014, khi trên địa bàn TP
HCM đã có khá nhiều cộng đồng lập trình viên sinh hoạt như
JSMeetup, Ruby Meetup, Grokking thường được mọi người
nhận diện như một cộng đồng công nghệ. Tuy nhiên, chúng
mình muốn định nghĩa bản thân là một tổ chức không vì lợi
nhuận (not for profit), tức là Grokking sẽ có cơ cấu hoạt động,
quy trình và sứ mệnh cụ thể để tổ chức được bền vững và mang
lại nhiều giá trị nhất cho giới kĩ sư phần mềm tại Việt Nam. Kể
từ năm 2014 tới nay, từ một nhóm nhỏ gồm 3 sáng lập viên,
Grokking hiện có đội ngũ nhân sự xấp xỉ 20 người và cộng đồng CHIA SẺ NHỮNG KIẾN THỨC KĨ THUẬT CĂN BẢN VÀ
Slack với hơn 1000 thành viên. Toàn bộ nhân sự của chúng CHUYÊN SÂU CỦA NGÀNH KHOA HỌC MÁY TÍNH VÀ KĨ
mình đều hoạt động trên cơ sở tình nguyện, và cùng hướng tới SƯ PHẦN MỀM
một sứ mệnh chung của Grokking: Với niềm tin rằng trở thành một kĩ sư phần mềm giỏi, chúng
ta không chỉ cần thành thục các kĩ năng lập trình mà còn phải
nắm chắc những kiến thức căn bản nhất của ngành CS (Com-
“Xây dựng hệ sinh thái cho puter Science) & SE (Software Engineering), sau một thời gian
bàn bạc và chuẩn bị, nhóm sáng lập viên của Grokking đã tổ
cộng đồng kỹ sư phần mềm chức Grokking Tech Talk #1 với chủ đề về Database được tổ
chức vào tháng 11 năm 2014, với gần 30 người tham dự.
trình độ cao ở Việt Nam.”
Những trao đổi, thảo luận tại buổi Tech Talk đầu tiên đã
chứng minh những chủ đề căn bản và mang tính học thuật
Khi nhắc tới sứ mệnh này, mỗi thành viên trong Grokking đều chuyên sâu cũng rất được cộng đồng đón nhận. Năm 2015 có
có thể kể một câu chuyện riêng về việc vì sao họ thực sự luôn tổng cộng 4 Tech Talk được diễn ra với những chủ đề như: Build
luôn hướng tới sứ mệnh đó. Nhưng có lẽ,câu chuyện nổi bật big things from small component, Real-time Data pipeline and
nhất chính là câu chuyện về việc muốn biến Việt Nam thành Real-world service Architecture, Android from Linux perspec-
một Tech Hub của châu Á, chuyển dịch từ định vị trong suy nghĩ tive and Root from Android, Coding standard and performance

DIJSKTRA 5
optimization, Techology stack at MySquar, …
5. A.save!
Con số tham dự những buổi Tech Talk của Grokking luôn ổn 6. B.balance += amount
định và tăng dần từ 30, 40 lên tới 70, 80 bạn. Hầu hết những 7. B.save!
phản ứng chúng mình quan sát được đều rất tích cực, như mọi 8. end
người nán lại hỏi nhiều, kiên nhẫn chờ câu hỏi của mình được 9. end
giải đáp. Từ những sự kiện này, Grokking thực sự thấy được sự 10. end
hữu ích của việc đem những kiến thức nền tảng và khoa học
máy tính chia sẻ cho cộng đồng lập trình viên. Sau khi ứng dụng chạy được một thời gian thì quản lí hệ
thống phát hiện tài khoản của vài người dùng bị âm. Bạn có thể
Sau đây là chia sẻ của một số người tham dự về những tác động giải thích tại sao? Và có cách nào để xử lí vấn đề này.
mà Tech Talk mang lại:
Khi tiếp xúc với những bài toán được mô tả dưới góc độ vận
“Minh thấy ở Tech Talk, kiến thức thường có hàm lượng kỹ thuật hành/ kinh doanh như thế này, các bạn kĩ sư phần mềm đòi hỏi
cao, kiến thức đó có được sẽ đủ để mình tìm hiểu tiếp. Ý Minh là phải tự vận động tư duy để trả lời những câu hỏi: Mô hình kinh
khối kiến thức đó có thể giúp Minh tự tìm hiểu, học hỏi thêm, có doanh của hệ thống vận hành như thế nào? Khách hàng/ người
thể giúp Minh giải thích, suy luận khi gặp trường hợp tương tự. Ví dùng có thói quen ra sao? Nền tảng công nghệ nào có thể giải
dụ như cái talk Progres của anh Huy, những kiến thức cơ bản khi quyết được bài toán này? Những dữ kiện của bài toán này yêu
một database vận hành giúp Minh hiểu những thao tác nào làm cầu một hệ thống kĩ thuật có điều kiện ra sao? Muốn tiền hành
cho database phình to ra”. triển khai thì phải làm như thế nào? … Chính những câu mà các

“Trước giờ đối với mình, Grokking


Tech Talk có vai trò mở rộng tầm mắt
“ Kĩ sư Việt Nam thực sự rất giỏi, rất lành nghề nếu tính trên
là chủ yếu. Còn áp dụng thực tiễn thì
thường đến từ Ruby meetup và Full- phương diện outsourcing, nhưng điều làm kĩ sư Việt Nam thua
stack weekend nhiều hơn”. xa Singapore và Mỹ là thiếu tư duy nền tảng. ” | Nguyễn Văn
Quang Huy
“... đi để mở mang và có cái nhìn rõ
hơn cho hướng đi của mình”.

Dựa vào những lời nhận xét như vậy, cộng với việc quan sát bạn tự hỏi mình như vậy đã đem lại giá trị nhiều hơn cho các
hướng đi của các cộng đồng khác, chúng mình đi tới kết luận: bạn khi quay lại làm việc. Vì giờ đây các bạn đã có thể giao tiếp
để mang lại giá trị nhiều nhất, Grokking sẽ tập trung cung cấp tốt hơn với các bộ phận khác trong công ty.
những kiến thức kĩ thuật chuyên sâu cho các bạn lập trình
viên. Điều này cũng hòa hợp với một niềm tin khác của chúng RÈN LUYỆN KHẢ NĂNG TƯ DUY HỆ THỐNG VÀ GIAO
mình, đó là việc phân biệt một bạn lập trình viên lành nghề và TIẾP HIỆU QUẢ CHO CÁC LẬP TRÌNH VIÊN
một bạn lập trình viên giỏi sẽ nằm ở chỗ: lập trình viên giỏi sẽ
không bị phụ thuộc vào một loại ngôn ngữ, công nghệ cụ thể Với mục tiêu cung cấp thêm nhiều kiến thức cho các bạn lập
mà còn có khả năng giải quyết bài toán bằng tư duy kĩ thuật trình viên bồi bổ, luyện não nhiều hơn nữa, bên cạnh Tech Talk,
có hệ thống. chúng mình lập nên trang Facebook Page và trang engineering.
grokking.org để chia sẻ với tần suất nhiều hơn. Đây chính là lúc
KHÁM PHÁ CÁCH NHỮNG KIẾN THỨC KĨ THUẬT mà Grokking nhận ra một phương án tiếp theo có thể giúp nâng
CHUYÊN SÂU ĐƯỢC ỨNG DỤNG TRONG THỰC TẾ cao trình độ của các bạn kĩ sư phần mềm lên đáng kể: tập trung
vào cách các bạn tư duy và giao tiếp.
Một điều chúng mình nhận ra khi theo dõi các Grokking Tech Để giải thích về điều này, chúng mình xin được kể về hoạt
Talk là: thay vì cách thể hiện lí thuyết bình thường, thì việc chia động xây dựng nội dung cho trang Facebook của Grokking.
sẻ các bài toán thực tế trước rồi từ đó quay lại giải đáp những Những mẩu nội dung này có thể là các bài viết ngắn, hoặc phân
kiến thức cơ bản được ứng dụng để giải quyết những bài toán tích dài về một chủ đề bất kì liên quan tới khoa học máy tính
này, tư duy của người tham dự sẽ được “kích thích” nhiều hơn. và kĩ sư phần mềm. Lúc đầu, các bạn trong nhóm nội dung của
Ví dụ như thế này: Grokking sẽ giúp tổng hợp những bài viết này từ trên mạng. Tất
cả các bạn đều là các lập trình viên trẻ, mong muốn trau dồi
Trong ứng dụng chuyển tiền của 1 ngân hàng Việt Nam, có một kiến thức của mình thông qua hoạt động này của Grokking.
bạn lập trình như sau: Một vấn đề nảy ra trong quá trình làm việc của nhóm xây
dựng nội dung là thứ nhất, các bạn tuy biết về một kiến thức
1. def transfer(A, B, amount): nào đấy nhưng lại không biết viết xuống để cho người khác
2. DB.transaction do hiểu dễ dàng. Các bạn thường không biết một người khác đọc
3. if A.balance > amount bài mình sẽ nảy ra những câu hỏi gì tiếp theo để đưa ra thông
4. A.balance -= amount tin giải đáp một cách hệ thống khiến cho họ thỏa mãn. Chúng

6 DIJSKTRA
mình tin rằng, việc “giao tiếp không tới” này cũng có thể xuất Grokking Online Magazine.
hiện khi các bạn phải thuyết phục đồng nghiệp trên công ty, Tuy vậy, chúng mình vẫn muốn khám phá thêm những cách
khi bàn luận với cùng bạn bè, hay khi hỏi ý kiến mentor. Tóm thức mới và hiệu quả hơn để đạt được sứ mệnh của mình. Trong
lại thông tin các bạn thu vào và đưa ra càng không hệ thống và tương lai, Grokking sẽ tiếp tục thử nghiệm và phát triển thêm
phân mảnh, hiệu quả công việc sẽ càng không cao. hiều hoạt động mới - như ấn phẩm DIJIKSTRA này là một ví dụ
Để khắc phục điều này, cách hoạt động của nhóm đã được - để tìm ra những hoạt động tốt nhất phục vụ cộng đồng kĩ sư
thay đổi một chút. Thay vì chỉ nghiên cứu cá nhân và viết bài, phần mềm tại Việt Nam.
mỗi thành viên trong nhóm giờ sẽ phải thực hiện hẳn một bài Mỗi hoạt động mới đưa ra đều dựa trên giả thuyết, niềm tin
trình bày trước các bạn khác, làm cho các bạn hiểu được về vấn nào đó của Grokking về cách phát triển một kĩ sư phần mềm
đề mình đang nói, trả lời giải đáp thắc mắc của các bạn nếu có, xuất sắc, và chúng mình sẽ cần rất nhiều đóng góp, nhận xét
sau đó mới viết lại thành bài hoàn chỉnh. Đây là một quá trình để củng cố niềm tin, chứng minh giả thuyết và nâng cao chất
mất khá nhiều thời gian và công sức, tuy nhiên, nó khiến cho lượng của các hoạt động trong tương lai.
các bạn tham gia luyện tập khả năng tư duy hệ thống và giao Nếu bạn là một kĩ sư phần mềm thuộc mọi trình độ, nền
tiếp hiệu quả. Nhờ có nó mà cách các bạn viết bài sâu hơn hẳn, tảng, hãy chia sẻ cho chúng mình biết, bạn đang cần gì và thiếu
không những thế, chúng mình còn quan sát thấy những dấu gì nhé.
hiệu thay đổi tích cực ở nhóm các bạn làm nội dung: đọc nhiều
hơn, hỏi nhiều hơn, chăm tới văn phòng hơn. Có bạn còn quyết Grokking cũng sẵn sàng chào đón sự hợp tác, giúp đỡ của
định cày hết cả quyển sách về ORACLE để thuyết trình. Một bạn những nhà quản lí, những doanh nghiệp hoặc tổ chức cùng quan
trong team nội dung đã chia sẻ: “Các kiến có được từ việc viết tâm tới chất lượng của kĩ sư phần mềm Việt Nam. Hãy liên lạc với
bài giúp mình đào sâu hơn, mở rộng những hiểu biết hiện tại, chúng mình tại email core@grokking.org nếu bạn muốn kết nối.
thậm chí là khi tìm kiếm về nó, còn phát hiện ra nhiều công cụ/
kiến thức liên quan khác.”

NHỮNG DỰ ĐỊNH TRONG TƯƠNG LAI

Sau khi đã xác định những yếu tố đem lại giá trị cốt lõi của
Grokking bao gồm việc cung cấp kiến thức kĩ thuật chuyên sâu,
bổ sung góc nhìn từ khía cạnh non-tech và rèn luyện khả năng
tư duy, giao tiếp có hệ thống, hiện Grokking đang có 4 hoạt
động chính ổn định: Grokking TechTalks, Grokking Research,

DIJSKTRA 7
Quản lý danh mục sản
phẩm (QLDMSP) là một
trong các thành phần
quan trọng nhất của một
hệ thống eCommerce.
Cùng với quản lý đơn
hàng và giao vận, QLD-
MSP tạo thành ba trụ cột
chính. Chính vì vậy việc
xây dựng hệ thống QLD-
MSP có vai trò quan trọng
trong kiến trúc tổng thể
của toàn hệ thống.

8 DIJSKTRA
1- XÂY DỰNG MÔ HÌNH (MODEL) ĐỂ LƯU TRỮ có màu sắc khác nhau; hay một chiếc váy có nhiều kích cỡ
THÔNG TIN VỀ SẢN PHẨM khác nhau.
Đối với các hệ thống eCommerce thì sản phẩm (product) là
đối tượng hiển thị chính các thông tin để người dùng thực 2- THIẾT KẾ TẦNG NGHIỆP VỤ (BUSINESS LAYER)
hiện việc mua bán. Các nghiệp vụ sẽ được phát triển xoay quanh mô hình đã
Một sản phẩm có nhiều thuộc tính đa dạng về số lượng, được xây dựng. Đây là tầng (layer) phức tạp nhất, chiếm
loại thuộc tính, kiểu dữ liệu. Mỗi thuộc tính có các yêu cầu phần lớn khối lượng công việc. Nghiệp vụ quản lý sản phẩm
khác nhau về tính chất dữ liệu như: độ dài, kiểu kí tự, các tập trung vào việc thay đổi các thuộc tính đa dạng của sản
yêu cầu về nghiệp vụ… Do đó mô hình sản phẩm (product phẩm.
model) là một mô hình không có cấu trúc cố định (schema-
less structure).
Cách tiếp cận phổ biến để giải quyết vấn đề này là sử
dụng mô hình dạng EAV - Entity Attribute Value. Đây là mô Khi thiết kế tầng này, người kỹ sư cần đảm bảo các mục tiêu
hình được Magento, Wordpress sử dụng để lưu trữ các cấu thiết kế như:
trúc đa dạng không định trước. Đặc điểm của cấu trúc EAV • Đảm bảo nguyên lý không lặp lại (Don’t Repeat Yourself)
là tách phần lưu trữ giá trị thuộc tính (attribute value) khỏi một cách tốt nhất, giúp các nghiệp vụ được phân tách rõ
phần cấu trúc các thuộc tính (attribute) của mô hình. Nhờ ràng, cô đọng và tập trung.
đó có thể định nghĩa được nhiều loại cấu trúc thuộc tính • Có thể mở rộng, sửa đổi các thành phần một cách độc
khác nhau của sản phẩm. lập.
Trong sơ đồ trên, bộ thuộc tính (attribute set) là bảng • Linh hoạt trong việc phát triển.
dùng để lưu một tập hợp các thuộc tính. Các thuộc tính • Có khả năng dễ dàng kiểm tra và bảo trì
được phân biệt với nhau bởi mã thuộc tính và loại kiểu dữ
liệu. Một thuộc tính có thể thuộc nhiều bộ thuộc tính khác
nhau. Một sản phẩm chỉ thuộc một bộ thuộc tính. Các giá
trị thuộc tính (attribute value) của sản phẩm tương ứng với
các thuộc tính được đặc trưng bởi kiểu dữ liệu và mã thuộc Các mục tiêu đó sẽ ảnh hưởng tới các cách thiết kế mô hình
tính. Giá trị thuộc tính có kiểu dữ liệu được định nghĩa bởi ứng dụng khác nhau. Phần dưới đây sẽ phân tích từng mô
thuộc tính. hình thiết kế phần mềm để đưa ra sự lựa chọn phù hợp
nhất.
Bằng cách tổ chức như vậy, hệ thống có thể thêm các bộ
thuộc tính mới dễ dàng, cũng như bổ sung các thuộc tính 2.1- Mô hình Model-View-Controller (MVC)
vào các bộ thuộc tính đã có. Mô hình MVC là mô hình phổ biến thường được lựa chọn để
Ngoài ra một điểm khác cần lưu ý khi thiết kế mô hình xây dựng ứng dụng. Đó là mô hình đơn giản, dễ tiếp cận và
sản phẩm đó là: một sản phẩm có nhiều hình ảnh, có thể giúp các kỹ sư nhanh chóng đưa ra được các tính năng mới.
thuộc nhiều danh mục (category) cũng như có thể có nhiều Theo mô hình MVC, thì phần quản lý danh mục (catalouge)
biến thể khác nhau (có quan hệ liên hệ với nhiều product sẽ có kiến trúc như sau:
khác). Ví dụ: điện thoại iphone có nhiều dòng sản phẩm

DIJSKTRA 9
vai trò cung cấp các nghiệp vụ ra bên ngoài xoay qua-
nh các domain model của hệ thống.
• Thiết kế riêng tầng hạ tầng (infrastructure) chứa các
logic về truy xuất dữ liệu, thao tác với cơ sở dữ liệu,
hàng đợi thông điệp (message queue).
Với việc tổ chức như thế này, các tầng ứng dụng, tầng

Với mô hình MVC, mô hình sản phẩm (product model)


sẽ chứa tất cả các định nghĩa thuộc tính của sản phẩm,
thông tin truy xuất cơ sở dữ liệu (database), cách thực thi
các nghiệp vụ. Thông thường mô hình MVC sẽ sử dụng mẫu
thiết kế (pattern) Active Record để ánh xạ (map) với cơ sở
dữ liệu.

Đây là cách làm đơn giản nhưng cũng có các hạn chế sau:
• Mô hình sản phẩm trở nên quá nặng nề khi chứa
quá nhiều logic về định nghĩa thuộc tính, truy xuất
dữ liệu, thực thi nghiệp vụ…
• Do không phân tách được các tầng nghiệp vụ và dữ
liệu nên khó thực hiện kiểm tra từng đơn vị riêng
biệt (unit test).
• Việc thay đổi logic truy xuất dữ liệu và logic nghiệp
vụ khó khăn do các thành phần bị phụ thuộc vào
nhau.
• Tính đóng gói của nghiệp vụ không đảm bảo. Các
nghiệp vụ sẽ chỉ được cài đặt theo mô hình CRUD. Vì
vậy càng về sau sự trùng lặp logic càng xảy ra nhiều.
nghiệp vụ và tầng truy xuất dữ liệu sẽ được chia tách
Do các hạn chế nêu trên nên đây không phải là mô hình riêng biệt và chỉ tương tác với nhau thông qua giao diện.
phù hợp với các ứng dụng logic phức tạp như eCommerce Các nghiệp vụ sẽ xoay quanh mô hình sản phẩm. Tầng
do sẽ dẫn tới chi phí bảo trì cao cho hệ thống sau này.. truy xuất dữ liệu sẽ truy xuất hoặc lưu trữ các đối tượng
thông tin về sản phẩm.
2.2. Mô hình ba lớp (domain driven design)
Hướng tiếp cận tiếp theo là phân tích và thiết kế theo Nhưng việc áp dụng mô hình ba lớp xoay quanh mô
phương pháp Domain Driven Design. hình sản phẩm cũng gây ra trở ngại cho việc xây dựng mô
hình cho các nghiệp vụ đọc dữ liệu.
Đặc trưng của mô hình này là:
• Phân tách tầng nghiệp vụ (domain layer) ra khỏi tầng Các nghiệp vụ này rất đa dạng và cách làm hiệu quả
ứng dụng (application layer) và tầng truy xuất cơ sở dữ nhất là sử dụng các câu truy vấn SQL trực tiếp. Nhưng
liệu (data access layer). Tầng nghiệp vụ sẽ trở thành nếu việc truy xuất bị thắt chặt vào các mô hình ORM
nơi trung tâm chứa tất cả các logic nghiệp vụ. (Object-Relational Mapping) sẽ làm ảnh hưởng tới hiệu
• Trong tầng nghiệp vụ, cần tập trung vào thiết kế mô năng, cũng như gây khó cho việc thay đổi các logic truy
hình sao cho mô hình phản ánh đầy đủ nhất tính chất xuất dữ liệu. Đồng thời nó cũng ảnh hưởng tới tốc độ
nhất quán của nghiệp vụ. phát triển khi việc cài đặt các nghiệp vụ truy vấn đa dạng
• Chia tầng nghiệp vụ thành hai thành phần riêng biệt: phục vụ phía ứng dụng giao diện bị cản trở và phụ thuộc
Domain Model và Domain Service. Domain service có vào việc thiết kế mô hình và tầng Repository.

10 DIJSKTRA
MỘT HỆ THỐNG QLDMSP TỐT PHẢI ĐÁP ỨNG CÁC MỤC TIÊU SAU

• Phần ghi dữ liệu: được thực hiện qua việc gửi các
2.3. Mô hình CQRS lệnh (command) tới các hàm xử lý (handler) thông
Mô hình CQRS (Command Query Responsibility Segrega- qua các tuyến lệnh (command bus. Bộ xử lý lệnh
tion) là sự mở rộng của mô hình ba lớp trong DDD. (Command handler) đóng vai trò tương tự domain
Đặc trưng quan trọng của CQRS là việc tách hai phần service sẽ tương tác với các mô hình để thực hiện
logic đọc và ghi dữ liệu ra thành hai thành phần riêng biệt các nghiệp vụ thay đổi dữ liệu.
độc lập với nhau: • Phần đọc dữ liệu: được thiết kế riêng không lệ thuộc
vào các mô hình của phần ghi dữ liệu. Do đó có thể
linh hoạt trong việc truy xuất cơ sở dữ liệu cũng như
sử dụng các nguồn dữ liệu (data source) khác nhau
để tối ưu về tốc độ truy xuất.
Mô hình CQRS đã khắc phục các hạn chế đã nêu ở mục
2 bên trên.
CQRS sẽ giúp mang lại các lợi thế lớn:
• Cho phép phát triển và tối ưu phần đọc dữ liệu tách
biệt với phần ghi dữ liệu
• Việc mô hình hoá các nghiệp vụ ghi dữ liệu dưới
các lệnh (command) cho phép che đậy tốt các logic
nghiệp vụ, giúp việc mở rộng hệ thống dễ dàng hơn.
Đồng thời các lệnh đó cũng có thể dễ dàng chuyển
đổi giữa xử lý đồng bộ và bất đồng bộ thông qua lớp
trừu tượng là tuyến lệnh (command bus) mà không
cần phải thay đổi mô hình. Điều này sẽ giúp cung
cấp một mô hình nhất quán, xuyên suốt trong bộ
kiến trúc.

Qua phân tích trên, ta có thể nhận thấy cả ba mô hình


trên đều có ưu nhược điểm riêng:
• Mô hình MVC đơn giản, nhưng có nhiều hạn chế khi
giải quyết nghiệp vụ phức tạp cũng như gây trở khi
cho công đoạn kiểm tra (test) và mở rộng hệ thống
sau này.
• Mô hình ba lớp DDD phù hợp cho việc xử lý nghiệp
vụ phức tạp nhưng có nhiều hạn chế khi tối ưu phần
đọc dữ liệu.
• Mô hình CQRS mở rộng từ mô hình ba lớp, giải quyết
tốt việc chia tách đọc ghi, nhưng cũng đòi hỏi phải
thiết kế phức tạp hơn.

Đối với các hệ thống eCommerce lớn thì mô hình CQRS


là mô hình phù hợp nhất vì nó giúp giải quyết cả hai đòi hỏi
lớn là xử lý nghiệp vụ phức tạp và đáp ứng hiệu năng cao.
Phần tiếp theo sẽ phân tích sâu hơn về mặt hệ thống và
một biến thể mở rộng của CQRS là CQRS - ES (Command
Query Responsibility Segregation - Event Sourcing).

DIJSKTRA 11
3. THIẾT KẾ VỀ HỆ THỐNG (stream). Các thành phần cần xử lý dữ liệu (consumer) chỉ cần
Một trong các đòi hỏi lớn của việc quản lý danh mục sản đăng ký nhận sự kiện từ ống dữ liệu (subscribe event bus) là
phẩm là phải thiết kế để đáp ứng các nhu cầu về hiệu năng có thể nhận được các sự kiện để xử lý.
và tích hợp với các hệ thống khác. Để đáp ứng các yêu cầu
tốt, thì phải được thiết kế từ tổng thể ngay từ đầu. Có vậy Các sự kiện được lưu trữ trong cơ sở dữ liệu mysql. Tất cả
mới tạo ra sự phát triển liền mạch, nhất quán, giúp đảm bảo các thay đổi trong cơ sở dữ liệu đều được MySql lưu vào một
tính ổn định cũng như tiến độ làm việc. log file, gọi là binlog. Bằng việc sử dụng binlog của mysql, thì
hệ thống có thể bắt được mọi event phát sinh để gửi đi.
3.1. Mô hình CQRS - ES
Mô hình Event Sourcing - ES là mô hình thiết kế mà trạng Kafka là một bộ phận điều phối thông điệp (message bro-
thái của đối tượng (object) sẽ được lưu trữ dưới dạng chuỗi ker) theo mô hình lưu trữ kiểu log (log-based) cho phép lưu
các sự kiện thay đổi. Nó khác với mô hình thiết kế thông trữ và gửi đi các sự kiện với hiệu suất cao nhưng vẫn đảm bảo
thường vốn chỉ lưu trữ trạng thái cuối cùng của đối tượng. đúng với thứ tự gửi vào. Vì vậy nó là lựa chọn tốt nhất để làm
tầng lưu trữ cho event bus.

3.3. Kiến trúc tổng thể

Đến đây bức tranh của hệ thống đã trở nên rõ ràng. Từng
mảnh ghép từ mô hình, nghiệp vụ tới tích hợp đã đầy đủ. Có
thể tóm tắt lại: hệ thống sẽ xây dựng nghiệp vụ quanh mô
hình sản phẩm; cấu trúc theo mô hình CQRS - ES; sử dụng
MySql Binlog; Kafka để publish các sự kiện thay đổi một cách
ổn định; dựa trên event bus sẽ xây dựng các cấu trúc lưu trữ có
tốc độ truy xuất cao như Elastic, MongoDb, cũng như tích hợp
với các hệ thống khác.
Khi đối tượng bị thay đổi, hệ thống sẽ tạo ra các phiên
bản sự kiện (versioned event) để lưu trữ dữ liệu thay đổi của
đối tượng. Các sự kiện (event) sẽ được lưu trữ bằng cách 4. KẾT LUẬN
chèn thêm mới (appending only) vào một cấu trúc bảng gọi Thiết kế hệ thống quản lý danh mục sản phẩm trong
là kho lưu trữ sự kiện (event store). Việc lưu trữ thông tin eCommerce đòi hỏi phải đạt được cùng lúc nhiều mục tiêu,
dưới dạng các phiên bản sự kiện này mang lại các lợi ích: với một tầm nhìn xuyên suốt và nhất quán. Từ mức ứng dụng
• Lưu trữ được lịch sử thay đổi của các đối tượng. cho tới mức hệ thống đều phải có sự gắn kết liền mạch. Tất cả
• Nếu các sự kiện được gửi tới các hệ thống khác, các hướng tới hai mục tiêu quan trọng phải đạt được:
hệ thống đó có thể tự tái hiện lại trạng thái cuối -Xử lý được các nghiệp vụ phức tạp
cùng chính xác của đối tượng gốc, do đó dễ dàng -Đảm bảo hiệu năng và độ ổn định của hệ thống.
tích hợp với các hệ thống khác.
• Dựa trên các sự kiện đã được tạo ra, có thể xây dựng Phương pháp phân tích thiết kế Domain Driven Design, mô
phần lưu trữ riêng cho khâu đọc (read side), để tối hình CQRS - ES, cơ chế replicate ổn định của MySql, sự đảm
ưu hóa tốc độ truy xuất dữ liệu. bảo thứ tự message của Kafka, cũng như các database được
thiết kế tối ưu cho thao tác đọc như Elastic, Mongo... là các
3.2. Event Bus - Kafka - MySql Binlog nhân tố chính đảm bảo chất lượng của hệ thống.
Các phiên bản sự kiện (versioned event) của đối tượng
nếu được gửi đi sẽ giúp hệ thống dễ dàng tích hợp với nhiều
hệ thống khác. Event Bus là tên gọi logic của một đường
truyền chứa tất cả các phiên bản sự kiện dưới dạng luồng

12 DIJSKTRA
Đọc và thảo luận bài viết online:

https://engineering.grokking.org/

DIJSKTRA 13
Lock free
programming

Vấn đề với lock

Là một lập trình viên từng làm việc với phần mềm
đa nhiệm (multi-thread), khái niệm lock chắc chắn
không hề xa lạ với bạn. Khi nhiều luồng (thread) cùng làm
dẫn đến giảm hiệu năng của ứng dụng, cũng như mắc phải
các sai lầm về logic dẫn đến deadlock hay là luồng bị chết
việc với một cấu trúc dữ liệu chung (shared data structure) đói (starvation) do không có tài nguyên về CPU.
thì chúng ta cần có một cơ chế để giới hạn quyền truy cập, Dưới đây chúng ta hãy thử duyệt qua một vài điểm yếu
chỉ cho phép một luồng (thread) duy nhất truy cập và sửa nữa của việc sử dụng lock:
đổi dữ liệu đó. Cơ chế phổ biến nhất cho việc này chính là Dead lock là chuyện xảy ra khi 2 ứng dụng cùng đợi tài
lock. nguyên lẫn nhau dẫn đến gậy ra vòng lặp vô tận.
Priority inversion là khi một tiến trình (process) có độ
Tranh chấp lock (Lock contention) chính là điểm mấu ưu tiên thấp lại lock một tài nguyên thuộc về một tiến
chốt dẫn đến hiệu năng không được như mong muốn khi trình có độ ưu tiên cao hơn.
lập trình song song. Convoying problem nói về vấn đề gặp phải khi một loạt
tiến trình phụ thuộc chung vào một tài nguyên nhưng tiến
Mặc dù lock là một kĩ thuật rất phổ biến và không tránh trình chạy chậm nhất lại đang giữ lock đầu tiên, khiến cho
khỏi trong hầu hết các bài toán lập trình nhưng làm việc những tiến trình chạy nhanh hơn phải chờ.
tốt với các kĩ thuật lock là không hề dễ dàng và dễ dẫn đến Async-signal safety vấn đề này thường xảy ra trong
các sai lầm, trong đó sai lầm phổ biến nhất là các lập trình lập trình hệ thống khi một hàm hệ thống (system call) có
viên có xu hướng lock quá nhiều một cách không cần thiết thể bị ở trạng thái gián đoạn (interrupt) bởi một tín hiệu

14 DIJSKTRA
holder) những năm 1977 với tựa đề là “Concurrent Reading
and Writing” [1]. Trong bài báo này, tác giả đề cập đến một
Về Kipalog cấu trúc dữ liệu cho lock-free gọi là non-blocking buffer
Kipalog (viết tắt của keep-a-log) là một dự án cũng như giải thích thêm những giới hạn của cấu trúc đó.
được tạo nên với quan niệm: kiến thức mà không
chia sẻ là kiến thức chết. Tại đây bạn có thể viết Như đã nói ở trên, lock free cần sự hỗ trợ của phần
bất kì kiến thức kĩ thuật nào bạn muốn giữ lại, cứng, thông qua các phép toán cơ bản (primitive) đơn
miễn là kiến thức đó có ích với ai đó, kể cả chỉ một giản mà phần cứng hỗ trợ. Các phép toán này còn gọi là
mình bạn. Từ lúc thành lập Kipalog đã thu hút ATOMIC OPERATION (hay gọi là các thao tác “nguyên tử”,
được hàng ngàn bài chia sẻ kiến thức hữu ích. Ki- tức là không thể chia nhỏ hơn được nữa). Điểm đặc biệt
palog team hy vọng đây sẽ trở thành nơi mà bất của các thao tác này đó là khiến cho một luồng không thể
kì ai yêu thích kĩ thuật cũng sẽ ghé qua, và để lại quan sát được một hành động diễn ra giữa chừng (half-
chút kiến thức có ích cho người khác thông qua complete). Một số ví dụ về các phép toán đó như là CAS
việc viết bài cũng như bình luận. (Compare and set), LL/CS (Load linked, store condition),
MCAS (Multi-word CAS), CAS2, CAS/N.

COMPARE AND SET (CAS) là phép toán mà trước khi


thay đổi một biến số nào đó thì CPU sẽ phải so sánh nó với
giá trị trước khi hàm CAS được gọi, nếu giá trị khác nhau
(do đã bị thay đổi bởi một luồng khác) thì sẽ không cho
phép thực hiện phép thay đổi đó.

Ngoài ra thay vì thiết kế một giải thuật tổng quát, thì


thường các nhà thiết kế giải thuật sẽ thiết kế các cấu trúc
(signal) nào đó như sigkill hay sighup. dữ liệu lock free (lock-free data structures) để thay thế. Và
các giải thuật chỉ cần dựa trên các cấu trúc dữ liệu này thì
Vậy điều gì xảy ra khi bạn có một hàm xử lý (handler) cũng đã giải quyết được kha khá các bài toán song song.
cho tín hiệu sigkill mà khi đang thực thi hàm đó thì một Dưới đây chúng ta sẽ thử xem qua một vài cấu trúc dữ liệu:
tín hiệu sigkill khác lại được gửi đến. Bạn sẽ nghĩ ngay đến
việc khóa lại việc xử lý của hàm xử lý này, tuy nhiên việc đó
sẽ gây ra deadlock tức thời (immediate deadlock) bởi bản 1. LOCK-FREE STACK (LIFO QUEUE)
thân hàm xử lý sẽ cố để lấy cái lock mà chính bản thân nó
đang giữ.

Một thao tác được gọi là Async-Signal-Safe khi mà nó


đảm bảo không làm phiền đến các tác vụ khác khi mà
chúng đang bị gián đoạn, tuy nhiên vô cùng đáng buồn là
hai tác vụ malloc và free lại không nằm trong danh sách
các thao tác thuộc nhóm Async-Signal-Safe này.

• Thao tác Push


Về lock free programming
(hay lockless programming) void push(int t) {
Như cái tên của nó, lock-free (hay lockless) là các kĩ Node* node = new Node(t);
thuật lập trình song song nhằm đảm bảo tài nguyên có thể do {
được chia sẻ hoặc thay đổi một cách an toàn mà không node->next = head;
cần khởi tạo hay giải phóng lock, cũng như không cần sử } while (!cas(&head, node, node->next));
dụng bất kì kĩ thuật lock khác như semaphore hay mutex. }

Là một kĩ thuật hướng đến sự hoàn hảo trong lập trình


đa luồng (multi thread programming), lock-free là một kĩ
thuật rất khó và không thể thực hiện được nếu thiếu sự hỗ
trợ của phần cứng.

Một trong những bài báo lâu đời và nổi tiếng về kĩ thuật
lập trình lock-free là của Leslie Lamport (Turing award

DIJSKTRA 15
• Thao tác Pop

• Thread 1 gọi CompareAndSet nhìn thấy giá trị X đã


bool pop(int& t) { bị đổi, sau đó thử lại.
Node* current=head; • Thread 2 thay đổi lại giá trị X là A.
while(current) { • Thread 1 thực hiện lại và thành công với Compar-
if(cas(&head, current->next, current)) { eAndSet.
t = current->data;
return true; Vấn đề ở đây chính là việc Thread 1 “tưởng” là mình đã
} gán thành công khi biến X không bị thay đổi từ bên ngoài
current = head; nhưng thực ra X đã bị thay đổi mà Thread 1 không hề biết.
} Khi stack dạng lock-free gặp phải vấn đề này thì sẽ có khả
return false; năng bạn đã gọi thao tác pop 2 lần trên cùng một node và
} sẽ bị tình trạng segfault.

Ở đây câu lệnh cas(*Node x, *Node oldValue, *Node


newValue) sẽ so sánh giá trị của biến X với oldValue (giá trị
cũ). Nếu giá trị của biến X bằng với giá trị oldValue thì hàm
cas sẽ dược thực thi, gán giá trị newValue vào cho biến X.
Đối với trường hợp giá trị của biến X không bằng với giá
trị oldValue thì hàm cas sẽ không được thực thi (do đã có
thread khác tác động lên biến X dẫn đến giá trị thay đổi).

Bạn có thể thấy một cấu trúc dữ liệu stack dạng lock
free chỉ đơn thuần là một stack có áp dụng các phép toán
atomic kết hợp với vòng lặp while.

2. DANH SÁCH LIÊN KẾT DẠNG LOCK-FREE


Danh sách liên kết dạng lock-free (lock-free linked list)
là một ví dụ rất tốt để chứng minh vấn đề hiệu năng giữa
việc sử dụng lock hay không sử dụng lock. Để vượt qua vấn đề này thì chúng ta có thể thêm một
biến là “update count” dựa vào khái niệm “doubleword
Với danh sách liên kết (linked list) thì đôi khi bạn sẽ CAS” (cần sự hỗ trợ phần cứng).
phải duyệt qua một quãng đường dài để tìm kiếm một
phần tử nào đó. Vì vậy nếu sử dụng lock thông thường thì
bạn sẽ phải lock toàn bộ danh sách khi cần duyệt!! Cho Chú ý và kết luận
nên việc vận dụng cấu trúc dữ liệu Lock-free trong tình Lock free không phải là thuốc chữa cho bài toán tranh
huống này sẽ giúp tiết kiệm thời gian rất nhiều. chấp tài nguyên. Việc nhiều thread cùng tranh chấp một
tài nguyên vẫn có thể xẩy ra, chỉ khác là ở tần suất thấp
Cách hiện thực danh sách liên kết dạng lock-free khá hơn, và được giải quyết tốt hơn (về mặt giải thuật + sự hỗ
phức tạp do có liên quan đến thao tác xóa nên các bạn có trợ về phần cứng). Starvation (chết đói) , hay là hiện tượng
thể tham khảo thêm chi tiết trong bài viết “Generic Con- khi một vài thread không nhận được resource đủ để chạy
current Lock-Free Linked List“ [2]. vẫn có thể xảy ra.
Để áp dụng lock free thì bạn cần lưu ý hai yếu tố:
Ngoài ra có một bài báo khác khá nổi tiếng về danh • Bài toán đủ đơn giản.
sách liên kết dạng lock-free với tiêu đề “A Pragmatic Imple- • Bạn tự nghĩ ra được một thuật toán lock free để áp
mentation of Non-Blocking Linked-Lists” [3] mà bạn đọc dụng cho một vài trường hợp hẹp.
có thể tham khảo thêm. Lock free sẽ làm tăng hiệu năng cho ứng dụng nhưng
để hiện thực đúng là hoàn toàn không dễ (vấn đề ABA là
một ví dụ).
Bài toán ABA
Với lock free sử dụng atomic operation sẽ xảy ra một
hiện tượng rất thú vị gọi là ABA, hiện tượng đó được diễn
giải như dưới đây:
• Thread 1 nhìn vào một biến chia sẻ X và định thay
đổi nó. Lúc thread 1 nhìn thì X có giá trị là A.
• Thread 1 tính toán một vài thứ thú vị dựa trên sự Đọc và thảo luận bài viết online:
thật là X có giá trị là A https://engineering.grokking.org/
• Thread 2 chạy, biến đổi X thành giá trị là B.

16 DIJSKTRA
Đây là một sơ đồ bao gồm các mảng kiến thức được tổng hợp bởi IEEE Computer Society,
một tổ chức quy tụ những kỹ sư giàu kinh nghiệm làm việc trong ngành phần mềm, nhằm
cung cấp một góc nhìn tổng quan cho những người làm phần mềm chuyên nghiệp về
những mảng kiến thức mà một người cần nắm.

Bạn đã biết được bao nhiêu mảng kiến thức được mô tả dưới đây?

DIJSKTRA 17
LÊ NGUYÊN DŨNG | Thuộc lứa 8x cuối
cùng, hiện là kỹ sư backend cho một ứng
dụng OTT quen thuộc với người dùng
Việt Nam, đang ẩn cư tại Sài Gòn.

Năm 1989, Tim Berners-Lee phát minh ra HTTP. Năm 1996, HTTP/1.0 được tổ chức RFC thông qua trở thành một chuẩn
(standard), HTTP/1.1 cũng hình thành cùng năm đó, đây là một trong những cột mốc quan trọng bậc nhất khiến thế giới
công nghệ phát triển như vũ bão và định hình như ngày hôm nay. Sau 26 năm kể từ ngày phát minh và gần 20 năm kể từ
ngày phiên bản 1.0 xuất hiện, tháng 5 năm 2015, tổ chức RFC đã thông qua đặc tả HTTP/2, đánh dấu thay đổi lớn nhất kể
từ ngày hình thành tới nay của giao thức HTTP.
Nội dung của bài viết này sẽ không đi sâu vào chi tiết đặc tả của HTTP/2, thay vào đó người viết sẽ cố gắng nhìn nhận vấn
đề cốt lõi của việc nâng cấp này thông qua tập trung phân tích hai cơ chế: kết nối và truyền dữ liệu.

HTTP/1 thông dụng nhất.


Tuy nhiên cách làm này rất không tối ưu vì thời gian
Đầu tiên, chúng ta quan sát lại cách làm của HTTP/1: thiết lập kết nối mới tốn rất nhiều thời gian do phải thực
1. KẾT NỐI CÓ VÒNG ĐỜI NGẮN hiện quá trình bắt tay 3 bước (three-hand-shaking), chưa
kể nếu có các lớp xử lý bảo mật như TLS sẽ càng làm tăng
độ trễ của việc thiết lập kết nối này.

2. KẾT NỐI CÓ VÒNG ĐỜI DÀI HẠN (KEEP-ALIVE CONNECTION)

Hình: HTTP/1 connection có vòng đời ngắn

Trong dạng xử lý này, mỗi kết nối (connection) sẽ yêu


cầu một tài nguyên độc lập. Kết nối sẽ được tạo mới khi
cần yêu cầu một tài nguyên và đóng lại sau khi nhận được
dữ liệu trả về. Đây là dạng làm việc đơn giản và cũng là Hình: Connection keep-alive

18 DIJSKTRA
Với keep-alive connection, có thể thực hiện nhiều lượt Nếu dữ liệu trả về không có thứ tự mà đi lộn xộn, thì do
yêu cầu tài nguyên khác nhau với cùng một kết nối. cùng sử dụng 1 connection chung, đầu nhận response sẽ
không thể phân biệt được phần dữ liệu là thuộc request
Tuy nhiên, có thể nhận thấy một khoảng thời gian chờ nào.
sau khi thực hiện một request, trong lúc đợi response về Điều này khiến HTTP pipelining phải tuân thủ một điều
hoàn tất, sẽ không có một request nào khác được phép là phía client chỉ sau khi nhận trọn vẹn một response của
thực hiện. Điều này gây lãng phí tài nguyên, do băng thông request này mới được nhận tiếp response từ request khác,
vẫn còn đó trong khi request tài nguyên khác sẽ không thể việc này gây ra nguy cơ về hiệu năng khi có một response
request ở cùng kết nối (connection), và nếu tạo ra kết nối bị mất hay bị xử lý chậm.
mới thì lại trở lại vấn đề với mỗi request một kết nối.

3. HTTP/1 PIPELINING

Hình: HTTP pipelining Hình: Head-of-line blocking trong HTTP pipelining

Giải pháp cho phép một loạt request được gọi mà Vấn đề này được gọi là head-of-line blocking. Nếu vì
không cần response phải hoàn thành, sau đó sẽ nhận các một lý do nào đó request tới trước được phía server xử lý
response. Một giải pháp khá mượt, nhưng nhìn sâu hơn chậm hơn request sau thì các request sau nó cũng không
vấn đề một chút, đầu tiên ta quan sát lại HTTP request và được trả về ngay mà buộc phải đợi.
response.
Vì vấn đề này mà hầu hết các trình duyệt dù có hỗ trợ
Một cú pháp request điển hình như sau: sẵn HTTP pipelining cũng đều mặc định ở trạng thái tắt
GET /index.html HTTP/1.1 (disabled). Ở góc nhìn web server cũng không khá hơn
Host: www.example.com mấy, một số web server sẽ gặp vấn đề khi xử lý kết nối dưới
dạng HTTP pipelining.
Cú pháp response dạng:
HTTP/1.1 200 OK Những vấn đề với HTTP pipelining khiến việc cải tiến
Date: Mon, 23 May 2005 22:38:34 GMT tốc độ ở góc nhìn kết nối và truyền tải bị dừng lại. HTTP/1
Server: Apache/1.3.3.7 (Unix) (Red-Hat/Linux) cứ vậy vận hành với phiên bản 1.1 cho tới khi giao thức
Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT SPDY xuất hiện, đây là nền tảng cho việc xây dựng HTTP/2.
ETag: “3f80f-1b6-3e1cb03b”
Content-Type: text/html; charset=UTF-8Content- Năm 2009, Google giới thiệu giao thức SPDY, về cơ bản
Length: 138 đây là một giao thức ở tầng TCP sử dụng binary thay vì text
Accept-Ranges: bytes như trên HTTP/1. Giao thức cũng hỗ trợ sẵn cơ chế về nén
Connection: close dữ liệu, các lớp bảo mật, chế độ ưu tiên ... để tăng tốc độ
<html> truyền tải dữ liệu web.
<head>
<title>An Example Page</title> Năm 2015, trên nền tảng của SPDY, HTTP/2 được tổ
</head> chức RFC công nhận như một chuẩn. Tiến trình phổ cập
<body> HTTP/2 thay thế HTTP/1 đang diễn ra trên toàn cầu.
Hello World, this is a very simple HTML document.
</body>
</html>

DIJSKTRA 19
HTTP/2
2. VẤN ĐỀ
a. Head-of-line blocking gây ra bởi TCP
Ý tưởng của HTTP/2 giúp tránh được HOL giữa các
request, tuy nhiên lại mắc phải một dạng HOL khác gây ra
bởi giao thức TCP.

HTTP/2 truyền nhiều request (stream) trên cùng một


TCP connection. Nhưng TCP sẽ không biết về điều này.
Dưới góc nhìn của TCP chỉ có những packet được đánh số
thứ tự. Nhiệm vụ của TCP là đảm bảo tất cả packet được
truyền đi đầy đủ, và đúng thứ tự. Do đó nếu có packet nào
bị mất do truyền tải ở tầng IP thì tầng TCP sẽ huỷ toàn bộ
các packet phía sau, và bắt đầu truyền lại từ packet bị mất.

Trong trường hợp những packet này thuộc những
stream khác nhau, thì khi mất mát gói tin của một stream
Hình: Kiến trúc HTTP/2 thì các stream còn lại sẽ bị ảnh hưởng. Và head-of-line
blocking lại xuất hiện.
HTTP/2 được xây dựng trên tư tưởng mỗi TCP connec-
tion sẽ có nhiều stream, mỗi packet được truyền tải trong
stream sẽ là một frame, các frame này sẽ có đầy đủ các
thông tin định danh stream.

Hình: HTTP/2 nhiều stream dùng chung một connection


Hình: Head-of-line blocking do cơ chế bảo vệ flow của TCP
Khi sử dụng, mỗi request sẽ sử dụng một stream độc
lập, mỗi frame đều có thông tin định danh cho stream b. Stream dùng chung thuật toán chống nghẽn
riêng, nên việc thứ tự truyền/nhận của request/response Thuật toán chống nghẽn được thiết kế nhằm giúp TCP
không còn là vấn đề, dữ liệu của frame nào sẽ được đưa sử dụng băng thông tối đa mà nó có thể, tùy vào lượng
vào stream của nó, tương ứng với đó là request/response mất mát gói tin mà thuật toán sẽ tự điều chỉnh lượng băng
tương ứng. Như vậy vấn đề head-of-line blocking được giải thông truyền đi.
quyết.
Trong HTTP/2, nhiều stream sẽ dùng chung trên một
kết nối, nên sẽ phải sử dụng chung một trạng thái chống
nghẽn. Việc này sẽ gây ra vấn đề nếu một gói tin thuộc
stream tương ứng bị mất, thì thuật toán chống nghẽn sẽ
điều chỉnh làm chậm băng thông của kết nối lại, kéo theo
các stream còn lại của kết nối này cũng sẽ bị chậm theo.

QUIC - QUICK UDP INTERNET CONNECTIONS

1. TỔNG QUÁT
Để khắc phục vấn đề head-of-line blocking gây ra bởi
TCP, cách duy nhất là thiết kế HTTP/2 trên nền một giao
thức khác. QUIC là 1 giao thức xây dựng trên nền UDP,
một giao thức thông dụng và có thể dễ dàng tương tác ở
Hình: Vấn đề Head-of-line blocking được giải quyết trong userland.
HTTP/2

20 DIJSKTRA
Tư tưởng thiết kế giao thức QUIC là sự kết hợp giữa TCP việc sử dụng rộng rãi giao thức này còn rất hạn chế. Hiện
và tinh thần của HTTP/2 chỉ có hai trình duyệt hỗ trợ giao thức này là Chromium và
• Đảm bảo không mất mát, đúng thứ tự gói tin: Opera.
Tương tự TCP
• Cải thiện thuật toán chống nghẽn: Sử dụng thuật Việc cố gắng xây dựng lại một giao thức lõi của internet
toán CUBIC của Google là một diễn biến lạ lẫm, họ thử nghiệm QUIC
• Tự sửa lỗi gói tin trên những sản phẩm nội bộ của mình (các dịch vụ web và
• Hỗ trợ lớp bảo mật TLS trình duyệt), nhưng Google đủ lớn để biến những cuộc thử
nghiệm về công nghệ khiến cả thế giới công nghệ phải ồn
ào và học hỏi, thậm chí trở thành chuẩn. Trường hợp đó
đã đúng với Ajax, BigTable, SPDY ... và biết đâu đó là QUIC
trong tương lai.

Hình: QUIC = TLS + TCP + SPDY

Mặc dù trong UDP, khái niệm kết nối không tồn tại,
nhưng dựa trên tinh thần của TCP, QUIC xây dựng lại kết
nối cho mình, tuy nhiên tầng truyền tải dữ liệu sẽ độc lập
giữa các stream. Điều này giúp loại bỏ head-of-line block-
ing gây ra khi các stream truyền tải dùng chung kết nối.
Một điều thú vị là kết nối của QUIC sẽ tốt hơn TCP trong
một số trường hợp. Ví dụ khi kết nối mạng của bạn đang sử
dụng đột ngột bị ngắt và kết nối lại, trong khi kết nối của
TCP sẽ bị mất và buộc phải khởi tạo kết nối mới, thì QUIC
do xây dựng trên nền tảng UDP - một giao thức phi kết nối
(connectionless) nên về lý thuyết thì kết nối sẽ vẫn tiếp tục
truyền nhận dữ liệu bình thường dù sẽ chậm đi một chút.

QUIC cũng sử dụng thuật toán chống nghẽn cho từng


stream riêng biệt, loại bỏ vấn đề thuật toán chống nghẽn
gây ra cho HTTP/2.

Đọc và thảo luận bài viết online:

https://engineering.grokking.org/

Hình: Giao thức QUIC

2. LỜI KẾT
QUIC hiện tại là một phần của dự án Chromium, chưa
có một đóng gói độc lập nào để sử dụng giao thức này.
Điều này khiến việc sử dụng QUIC rất khó khăn. Mặc dù rất
nhiều các dịch vụ của Google hiện tại đã dùng QUIC nhưng

DIJSKTRA 21
POSTGRESQL BUFFER
hoạt động như thế nào?

GIỚI THIỆU Trong PostgreSQL, hệ thống đảm nhận việc này có tên
Hầu hết các hệ thống cơ sở dữ liệu SQL hiện nay đều là Buffer Manager.
lưu trữ dữ liệu ở trên ổ đĩa. Tuy nhiên, như chúng ta đã biết
thì truy xuất từ điã sẽ chậm hơn khoảng 80 lần so với RAM. CẤU TRÚC CỦA BỘ QUẢN LÝ ĐỆM
Dù bạn có thay thế đĩa cứng bằng ổ SSD thì vẫn sẽ chậm Bộ quản lý đệm gồm có 3 thành phần: buffer table, buf-
hơn 4 lần so với RAM. fer descriptors và buffer pool. Trong bài viết này chúng ta
sẽ chỉ đề cập đến buffer pool.
Các hệ cơ sở dữ liệu SQL xử lý việc này bằng kỹ thuật Buffer pool chính là bộ nhớ tạm mà chúng ta đã nói
buffer. Buffer hoạt động dựa trên nguyên tắc: đưa 1 phần qua ở kỹ thuật buffer. Buffer pool được hiện thực dưới
thông tin thường dùng chứa thẳng trên RAM để có tốc độ dạng 1 mảng được lưu trữ trên RAM. Mỗi ô của mảng này
truy xuất nhanh. Những lần sử dụng sau thì sẽ không phải sẽ chứa một lượng “dữ liệu thô”, và index của ô này được
truy xuất ổ đĩa để lấy dữ liệu nữa. gọi là buffer_id.

22 DIJSKTRA
Buffer_tag
Ai đã từng làm việc với SQL đều biết là dữ liệu của chúng
ta được chứa trong các bảng (table). Tuy nhiên bảng là một
khái niệm mang tính hình tượng để chúng ta dễ suy nghĩ. Dữ
liệu thật sự của mỗi bảng sẽ được chia nhỏ ra và chứa trong
các trang (page) có kích thước bằng nhau.

Mỗi trang (page) được đặt cho 1 mã định danh gọi là


buffertag. Buffertag này bao gồm 3 con số, mà thông qua
nó sẽ định danh page này thuộc về table nào, và là page thứ
mấy trong số các page đang chứa dữ liệu của table.

Dữ liệu trong page chính là dữ liệu thô sẽ được lưu trữ


trong bộ nhớ tạm, cụ thể là buffer pool layer của buffer được quản lý bởi Buffer descriptor.
manager.
Khi dữ liệu trong buffer pool bị thay đổi
Quy trình hoạt động của Bộ quản lý vùng đệm Khi cơ sở dữ liệu nhận được 1 yêu cầu thực hiện thay
đổi dữ liệu của bảng, những điều chỉnh sẽ được áp dụng
trực tiếp lên trang tương ứng trong vùng đệm (chứ ko phải
là phiên bản gốc ở điã cứng). Lúc này, trang tương ứng
trong vùng đệm đã bị thay đổi sẽ được đánh dấu là bẩn
(dirty).

Những thông tin mới này 1 lúc nào đó sẽ phải được lưu
trữ cố định xuống điã cứng. Hành động này gọi là Flush
dirty page.
Khi 1 câu truy vấn SQL được gửi đến, các tiến trình sẽ xử
lý logic của câu truy vấn và sẽ biết được dữ liệu cần thiết Đảm nhận nhiệm vụ này sẽ là 2 tiến trình chạy nền là
hiện đang được lưu ở trang nào. Hệ thống sẽ mang buffer_ checkpointer và background writer.
tag của trang tìm được đến kiểm tra với bộ quản lý đệm xem
trang này đã có sẵn trong vùng đệm hay chưa. MỞ RỘNG
Nếu trang chưa được lưu trong vùng đệm thì bộ quản lý Như các bạn đã biết vùng đệm nằm trên RAM, dữ liệu
sẽ yêu cầu truy xuất trực tiếp xuống điã cứng để lấy, sau đó của RAM sẽ mất hết nếu hệ thống xảy ra sự cố như mất
lưu nó vào 1 trong các ô nhớ của vùng đệm. Vị trí của ô đó điện. Vậy nếu trang trở nên bẩn (dirty), chưa kịp lưu cố
(buffer_id) sẽ được trả về cho tiến trình yêu cầu. định xuống đĩa cứng mà sự cố xảy ra thì đồng nghĩa là
Ngược lại, nếu trang đang được lưu trong vùng đệm thì chúng ta sẽ bị mất những dữ liệu mới này. Điều này dẫn
bộ quản lý sẽ trả về buffer_id của ô hiện đang chứa trang đến cần phải có 1 thành phần khác đảm nhiệm việc này,
này. đó là WAL.
Tiến trình sau khi nhận được buffer_id có thể thực hiện
việc truy xuất trực tiếp dữ liệu mà nó cần. Mô tả chi tiết của WAL sẽ nằm ngoài phạm vi của bài
viết này, nhưng nếu giải thích một cách ngắn gọn thì ý
Khi vùng đệm bị đầy tưởng của WAL sẽ là: Nếu 1 hành động nào đó làm thay
Buffer pool được lưu trữ trên RAM, 1 lúc nào đó nó cũng đổi trạng thái của dữ liệu, sự thay đổi đó sẽ được ghi nhận
sẽ phải đầy. Do đó chúng ta cần 1 thuật toán để xác định (log) lại trước cả khi buffered page được cập nhật. Như
nên bỏ đi trang nào để lấy chỗ cho trang mới. vậy, nếu sự cố xảy ra thì hệ thống sẽ xem xét lại các thông
tin đã được ghi nhận lại (log) chưa được xử lý và do vậy sẽ
Có nhiều thuật toán khác nhau để làm việc này. Post- đảm bảo dữ liệu được nguyên vẹn.
greSQL từ bản 8.1 trở đi sử dụng thuật toán Clock Sweep
thay cho LRU ở các phiên bản trước.
Ý tưởng của thuật toán Clock Sweep là: ưu tiên loại bỏ
page nào ít được truy xuất nhất (usagecount), và tại thời
gian xem xét, page đó đang không bị process nào truy xuất
(unpinned_). Đọc và thảo luận bài viết online:

https://engineering.grokking.org/
Thông tin về số lượng truy xuất, số lượng tiến trình đang
truy xuất trang đó gọi là metadata của buffer slot đó, và

DIJSKTRA 23
DATA STRUCTURE & ALGORITHM

FLOATING POINT
& SAI SỐ
TRONG TÍNH TOÁN
Nguồn ảnh internet

Về tác giả:
PHÚ TRẦN - hiện đang công tác tại Axon Enterprise Inc. ở vị trí Research Engineer. Từng
có 3 năm kinh nghiệm làm hệ thống nhúng tiêu tốn năng lượng thấp, trách nhiệm của
mình hiện tại là làm sao chạy được các thuật toán AI trên hardware nhanh nhất và hiệu
quả nhất. Sở thích cá nhân: chụp hình và đi du lịch …. để chụp hình!

Đọc và thảo luận bài viết online:

https://engineering.grokking.org/

24 DIJSKTRA
TẠI SAO CHÚNG TA CẦN FLOATING POINT?
Với kiểu dữ liệu fixed point, dấu chấm thập phân (decimal
point) là cố định:

trong đó: decimal là số bit biểu thị phần nguyên, frac là số bit

T rong khoa học máy tính, đặc biệt là trong


ngôn ngữ C/C++, ta có nhiều sự lựa chọn
về kiểu dữ liệu để biểu thị một số nguyên từ
biểu thị phần thập phân.

số nhị phân (từ int, đại diện cho số nguyên Lấy ví dụ về một kiểu dữ liệu fixed point 8 bit, phần decimal
âm và dương với khoảng giá trị từ -32768 đến là 5 bit và phần frac là 3 bit. Ta có:
32767 trên hệ thống 16 - bit, cho tới unsigned Kiểu dữ liệu fixed point như trên là rất đơn giản và phù hợp
long long, đại diện cho số nguyên dương từ 0 với những ứng dụng có yêu cầu độ chính xác tương đối. Nhưng
đến 2^64-1). Như vậy, đối với số thực, người đối với các ứng dụng yêu cầu độ chính xác rất cao hoặc rất thấp,
ta làm thế nào? nó sẽ gặp nhiều giới hạn và không sử dụng hiệu quả được các
bit đang có.
Floating point là câu trả lời cho câu hỏi trên,
nó được tạo ra nhằm mục đích biểu thị một số Chính vì thế, chúng ta cần đến kiểu dữ liệu floating point
thực trên máy tính. Thế thì tại sao lại là float- - dấu chấm động - để biểu thị một số thực bằng mã nhị phân.
ing point mà không phải là fixed point?
Tuy nhiên floating point cũng có hạn chế nhất định của nó,
cái mà có thể gây ra lỗi không mong muốn trong quá trình cod-
ing. Trước khi bắt đầu, các bạn hãy thử xem đoạn code sau đây:

int main(int agrc, char ** arg)


{
float a = 1e10f;
float b = 1e10f;
float c = 0.1f;
float result_1 = a - b + c;
float result_2 = a + c - b;
printf(“a - b + c = %.4f\n”, result_1);
printf(“a + c - b = %.4f\n”, result_2);
return 0;
}

Theo bạn, kết quả in ra sẽ là gì? Có thể nhiều bạn sẽ ngạc


nhiên sau khi chạy thử chương trình:
a - b + c = 0.1000
a + c - b = 0.0000

Bài viết này sẽ làm rõ vấn đề tại sao kết quả lại là như trên.

ĐỊNH DẠNG CHẤM ĐỘNG THEO CHUẨN IEEE 754


Theo tiêu chuẩn IEEE 754 về số floating point, có tổng cộng 3
trường để biểu thị một số float, lần lượt là:
• Sign bit: bit dấu, luôn là 1 bit và là bit có trọng số cao
nhất (most significant bit)
• Exponent bits: phần mũ, cơ số luôn là 2
• Fraction bits: phần thập phân, hay còn là mantissa

DIJSKTRA 25
bit fraction, ta lại càng có độ chính xác cao hơn.

PHÉP LÀM TRÒN


Bởi vì kiểu dữ liệu floating point có hữu hạn số bit phần
thập phân, nếu số thực có số chữ số thập phân lớn hơn
Các thành phần của số floating point và số lượng bit số bit cho phép, những phần thập phân mà floating
point không biểu thị được sẽ được bỏ đi, và số thực sẽ
Tuỳ theo từng loại giá trị mà một số floating point muốn được làm tròn.
biểu thị, ta có mối liên hệ giữa 3 phần trên khác nhau:
IEEE 754 quy định có 4 chế độ làm tròn khác nhau:
• Normalized form Round to nearest: chế độ mặc định, kết quả được
◆◆ Sign: 0 hoặc 1 làm tròn tới số floating point gần nhất. Nếu nằm giữa
◆◆ Exponent: bất kì số nào, ngoại trừ trường hợp 2 số floating point thì sẽ chọn số có bit thấp nhất là 0.
[11..1]m hoặc [00..0]m Round toward 0: kết quả được làm tròn tới số float-
◆◆ Fraction: bất kì số nào ing point gần nhất và gần giá trị 0
◆◆ Số thực = (-1)sign x 2exponent-biasx(0.F1F2F3...Fn) trong đó Round toward +∞: hay còn gọi là ceiling, kết quả
bias = 2m-1 - 1 được làm tròn tới số floating point gần nhất và lớn hơn
• Denormalized form số thực
◆◆ Sign: 0 hoặc 1 Round toward -∞: hay còn gọi lại floor, kết quả được
◆◆ Exponent: luôn luôn [00..0]m làm tròn tới số floating point gần nhất và nhỏ hơn số
◆◆ Fraction: bất kì số nào, ngoại trừ [00..0]n thực
◆◆ Số thực = (-1)signx21-biasx(0.F1F2F3..Fn)
Một số ví dụ cho thấy cách hoạt động của các chế độ
• Zero làm tròn ( giả sử ta làm tròn đến phần nguyên):
◆◆ Sign: 0 hoặc 1, tương ứng 0+ và 0-
◆◆ Exponent: luôn luôn [00..0]m
◆◆ Fraction: luôn luôn [00..0]n

• Infinity
◆◆ Sign: 0 hoặc 1, tương ứng +∞ và -∞
◆◆ Exponent: luôn luôn [11..1]m
◆◆ Fraction: luôn luôn [00..0]n Các kiểu làm tròn số float được quy định bởi IEEE 754

• NaN (not a number) SAI SỐ DO PHÉP LÀM TRÒN


◆◆ Sign: 0 hoặc 1 Như ta thấy, floating point không biểu thị chính xác
◆◆ Exponent: luôn luôn [11..1]m một số thực, mà nó chỉ có thể xấp xỉ thông qua phép làm
◆◆ Fraction: bất kì số nào, ngoại trừ [00..0]n tròn. Tương tự như các kiểu dữ liệu khác, ta cũng có các
phép toán cơ bản trên số float, ví dụ: cộng, trừ, nhân,
Chúng ta đã thấy tiêu chuẩn IEEE 754 đã mã hoá một số chia, so sánh... và, không loại trừ, kết quả của các phép
thực bằng hệ nhị phân như thế nào. Dưới đây là một số kiểu toán này cũng sẽ được làm tròn như vậy. Vì vậy, khi ta
dữ liệu floating point đã được định nghĩa trước và các thông thay đổi thứ tự thực hiện các phép toán hoặc thay bằng
số của chúng: phép toán tương đương nhau, kết quả mỗi trường hợp
sẽ khác nhau.

Một ví dụ về việc thay đổi thứ tự thực hiện phép toán:


int main(int agrc, char ** arg)
{
float a = 0.2f;
Một số kiểu floating point thông dụng được định nghĩa trong float b = 0.3f;
IEEE 754 float c = 0.4f;
float sum_1 = (a + b) + c;
(*): tối đa bao nhiêu số chữ số thập phân sau dấu phẩy float sum_2 = a + (b + c);
có thể được biểu thị, hay nói cách khác là độ chính xác. Với printf(“Sum_1 is %0.10f \\ Sum_2 is
n fraction bits, ta có được tối đa số chữ số thập phân được %0.10f\n”, sum_1, sum_2);
xác định bằng công thức: decimaldigits =log10 2n + 1 . Lấy ví dụ return 0;
như chúng ta có số bit fraction n = 1, như vậy phần thập phân }
chúng ta có thể có tối đa là 1 chữ số. Nếu có 9 bit fraction, ta
có độ chính xác đến 3 chữ số thập phân. Như vậy, càng nhiều

26 DIJSKTRA
Biên dịch đoạn code trên Linux bằng gcc:
gcc -o my_prog my_program.cpp -O0
cộng:
Kết quả khi chạy chương trình: FMA(X,Y,Z) = round(XY + Z)
Sum_1 is 0.8999999762 \ Sum_2 is 0.9000000358
Một điểm cộng với phép FMA là do chỉ làm tròn 1 lần ở kết quả
Do các số float a, b, c đều là xấp xỉ của 0.2, 0.3, 0.4. Sự cuối nên nó sẽ nhanh hơn nếu ta dùng phép nhân và cộng bình
khác nhau giữa 2 kết quả đến từ sự khác nhau về thứ tự thường.
làm tròn: Trên thị trường hiện nay đã có các dòng CPU và GPU hỗ trợ phép
FMA trực tiếp, đi kèm là các tập lệnh FMA cho một phép tính hoặc
a = 2-3 x 1.100110011001100110011012 cho lệnh SIMD (single instruction, multiple data):
b = 2-2 x 1.001100110011001100110102 • AMD: từ dòng Bulldozer (2011), Piledriver(2012),...
c = 2-2 x 1.100110011001100110011012 • Intel: từ dòng Haswell (2013), Broadwell,...
• ARM: ARM Cortex M4F, ARM Cortex A5, ARM Cortex A7,...
Trường hợp (a + b) + c: • NVIDIA: các GPUs có kiến trúc từ Fermi (2010) trở về sau
a + b = 2-1 x 1.00000000000000000000000010002
round(a + b) Một ứng dụng quan trọng của FMA, đó là tăng tốc phép tính
= 2-1 x 1.000000000000000000000002 nhân ma trận:
round(round(a + b) + c)
= 2-1 x 1.110011001100110011001102

Trường hợp a + (b + c):


b + c = 2-1 x 1.01100110011001100110011100002
round(b + c)
= 2-1 x 1.011001100110011001101002
round(a + round(b + c))
= 2-1 x 1.110011001100110011001112

Một ví dụ khác về việc thay đổi phép toán tương đương


cũng có thể làm khác kết quả:
Phép nhân ma trận dùng FMA
int main(int agrc, char ** arg)
{ TRẢ LỜI CÂU HỎI MỞ ĐẦU
float a = 0.1f; Đến đây, chắc các bạn cũng đã nắm rõ khái quát floating point
float sum = 0; là gì, cách nó xấp xỉ một số thực như sao, cũng như sai số tiềm ẩn
for(int i = 0; i < 10; i ++) trong floating point mà chúng ta cần lưu ý khi code. Từ đó chúng ta
{ có thể giải thích câu hỏi được đưa ra đầu bài như sau:
sum += a;
} a = 233 x 1.001010100000010111110012
float product = a * 10; b = 233 x 1.001010100000010111110012
printf(“Sum is %0.10f \\ Product is %0.10f c = 2-4 x 1.100110011001100110011012
\n”, sum,
product); Trường hợp a - b + c:
return 0; a - b = 2-126 x 0.00000000000000000000000000000000000002
} round(a - b)= 2-126 x 0.000000000000000000000002
round(round(a - b) + c)
Kết quả sau khi biên dịch: = 2-4 x 1.100110011001100110011012
Sum is 1.0000001192 \ Product is 1.0000000000 = 0.1f

Ở đây, sum được tính bằng cách cộng với a 10 lần, tức Trường hợp a + c - b:
là trong đó có 10 lần làm tròn số. Còn đối với product, kết a + c = 233 x 1.001010100000010111110010000000000000112
quả chỉ được làm tròn 1 lần sau phép nhân 10, dẫn đến ít round(a + c) = 233 x 1.001010100000010111110012
có sai số hơn so với sum. round(round(a + c) - b)
= 2-126 x 0.000000000000000000000002
PHÉP TÍNH FUSED MULTIPLY-ADD VÀ ỨNG DỤNG = 0.0f
Để làm giảm sai số do phép làm tròn, phép toán fused
multiply-add (FMA) được thêm vào IEEE754 vào năm 2008.
Bản chất của FMA là chỉ làm tròn 1 lần sau kết quả nhân-

DIJSKTRA 27
Bạn sẽ làm gì khi muốn triển khai một tính năng đến một nhóm nhỏ người dùng thay vì toàn bộ người
dùng trong hệ thống? | HUY NGUYỄN

Một vài ứng dụng trong thực tế của kỹ thuật này:


Feature Control: tắt/bật tính năng cho toàn bộ hệ
thống, hoặc một vài khách hàng cụ thể
Feature Rollout: bật một tính năng từ từ cho tập người
dùng của mình, có thể trước mắt cho 1 vài người dùng cụ
Feature Toggle (hay Feature Flags) và Fea- thể, rồi sau đó bật tiếp cho những người dùng trong một
ture Rollout là một kĩ thuật phổ biến giúp nước/khu vực nào đó.
bạn có thể quản lý được hành vi của phần
mềm của mình mà không cần phải đổi BẬT/TẮT TOÀN CỤC
code & deploy lại. Trong bài viết này mình Trường hợp cơ bản nhất của Feature Toggle là giúp bạn
sẽ đi qua một vài tính năng từ cơ bản đến bật/tắt 1 tính năng mà không cần phải deploy lại code. Ví
nâng cao, đồng thời chia sẽ cách tiếp cận dụ, chúng ta có tính năng XYZ như sau:
để design và implement một hệ thống Fea-
ture Toggle/Feature Rollout nhỏ.

Lúc này, bạn có thể code & deploy tính năng xyz đó
trước, sau đó chọn thời điểm thích hợp để bật nó lên cho
toàn bộ hệ thống. Hoặc ngược lại, khi bạn phát hiện ra lỗi,
hoặc hệ thống quá tải, bạn có thể tắt bớt 1 vài tính năng

28 DIJSKTRA
phụ chỉ với 1 vài cú click chuột. và dùng nó để kiểm tra:
Thiết kế đằng sau đơn giản là một bảng trong cơ sở dữ
liệu chứa các tính năng của bạn, cùng với 1 biến cờ quy
định trạng thái bật/tắt của tính năng.

Lúc đó, với mỗi user_id, ta sẽ dùng 1 hàm hash để đẩy


người dùng vào 1 tập từ 1-100, và so sánh với giá trị
rollout_percent của mình…

BẬT/TẮT CHO KHÁCH HÀNG CỤ THỂ


Bây giờ mình thảo luận đến một vài trường hợp phức tạp
hơn khi mà bạn:
1. Chỉ muốn bật tính năng cho 1 vài khách hàng thử
nghiệm (hoặc là khách hàng cao cấp)
2. Muốn bật cho toàn bộ hệ thống, nhưng tắt cho 1 vài
khách hàng đặc biệt (khách hàng chưa đăng ký sử dụng LÚC NÀO THÌ LÀM GÌ?
tính năng này) Nếu để ý kĩ các ví dụ trên, thì không phải lúc nào bạn cũng
cần hết những tính năng nói trên:
Trường hợp bật/tắt cho khách hàng cụ thể sẽ phù hợp với
các ứng dụng B2B (ví dụ: Intercom, Hubspot), khi mà người
xài thuộc các tài khoản công ty khác nhau.
Có thể nhận ra rằng 2 trường hợp trên giống như 2 Trường hợp triên khai theo % của user sẽ phù hợp hơn với
mệnh đề đảo ngược nhau, lúc đó, bạn có thể cải thiện hệ các ứng dụng B2C (ví dụ Quora, Facebook, Kipalog) khi mỗi
thống bằng cách thêm vào 1 cột exception_list để chứa tập người xài là 1 user độc lập.
khách hàng đặc biệt này: Nói vậy để thấy là tuy cũng chỉ là cơ chế feature toggle,
feature rollout, nhưng mỗi doanh nghiệp khi thiết kế sẽ có
nhiều bài toán con khác nhau, ảnh hưởng đến cách bạn
thiết kế tính năng này.

CẢI THIỆN TỐC ĐỘ (PERFORMANCE IMPROVEMENT)


Ở trên ta dùng database để lưu các toggles, như vậy mỗi
Lúc này thì: lần gọi hệ thống phải truy vấn vào cơ sở dữ liệu. Với những
toggled = false, exception_list = [1, 2]: tắt hệ thống có nhiều người dùng, việc này sẽ làm chậm hệ
toàn bộ, vào bật cho khách hàng ID 1 và 2. thống lại rất nhiều và trở nên không thực tế.
toggled = true, exception_list = [1, 2]: bật Nhận thấy việc dữ liệu toggles ở trên không thường
cho toàn bộ khách hàng, chỉ tắt cho khách hàng ID 1 và 2. xuyên thay đổi nhiều (chỉ đổi khi admin vào sửa nội dung),
nên ta có thể dùng caching (như Redis, hoặc lưu thẳng vào
memory) để tránh việc phải có nhiều database calls. Và
ta chỉ cần làm mới bộ đệm khi mà ai đó vào admin để cập
nhật lại toggle settings.
Một cách triển khai khác là ta hoàn toàn có thể hiện
thực trực tiếp bằng Redis mà không cần phải thông qua
SQL database. Lúc này ta phải coi như dữ liệu trong Redis
của bạn là persistent data và có cơ chế backup thích hợp.

KẾT LUẬN
Ở trên mình đã giới thiệu các bạn hướng tiếp cận và giải
quyết bài toán Feature Toggle / Feature Rollout. Tuy nhìn
Trong ảnh: UI features toggles của Holistics (dựa trên nền đơn giản nhưng khi đi sâu vào nó có những yêu cầu đặc
ActiveAdmin). thù khác nhau, cho nên mỗi công ty sẽ có cách tiếp cận/
thực thi khác nhau.
TOGGLE CHO % TẬP NGƯỜI DÙNG (HAY LÀ FEATURE
ROLLOUT)
Giả sử bây giờ, bạn vừa deploy 1 tính năng mới và muốn
release thử nghiệm cho 5% người dùng của mình thôi thì
phải thiết kế như thế nào?
Đọc và thảo luận bài viết online:
Một cách đơn giản là thêm vào 1 cột rollout_percent,
https://engineering.grokking.org/

DIJSKTRA 29
KĨ SƯ PHẦN MỀM GIỎI THÌ PHẢI NHƯ THẾ NÀO?

S
au một thời gian làm kĩ sư phần mềm ở nhiều môi
trường, cũng như qua trải nghiệm phỏng vấn & tiếp
xúc với rất nhiều bạn lập trình viên khác, có một
nhận định chủ quan mà mình muốn đưa ra như sau:

Người làm phần mềm có 3 loại:

1- Người làm nghiên cứu (Computer Scientist) -


thường làm việc ở trường ĐH và các viện nghiên cứu,
thường có Master hoặc PhD. Kiến thức chuyên sâu của họ
về khoa học máy tính rất tốt, tư duy giải quyết vấn đề
cao. Họ thường không tham gia lập trình các dự án phần
mềm lớn nên code thường không đẹp và sẽ gây nhiều khó mềm như Google, Facebook, Twitter luôn muốn tuyển vào.
khăn cho dự án, nhưng nếu trọng tâm của họ là nghiên cứu
chuyên sâu thì không vấn đề gì cả. Người làm nghiên cứu thì tiếp tục nghiên cứu vì đó là
đam mê của họ. Còn người ở nhóm Application Devel-
2- Lập trình viên ứng dụng (Application Developer) oper nên/cần phải phát triển lên được trình độ của Soft-
- thường chuyên viết ứng dụng web, mobile, tuy nhiên họ ware Engineer, vì đó đơn giản là con đường phát triển
thường thiếu các kiến thức về khoa học máy tính, thuật mà các bạn phải lên tới được.
toán, cấu trúc dữ liệu. Một phần có thể do các bạn không có Theo cảm nhận chủ quan mình thấy thì Việt Nam
điều kiện được tiếp xúc vì ít người dạy, một phần thì do hầu mình có nhiều người trong nhóm lập trình viên ứng
hết tính chất công việc đang làm ở Việt Nam không cho các dụng, nhưng rất ít bạn ở mức độ kĩ sư phần mềm. Do
bạn cảm thấy những cái này quan trọng. vậy, nhìn ngoài vào thì ai cũng nói ở Việt Nam có nhiều
lập trình viên, nhưng đến khi vào phỏng vấn thì rất rất
3- Kĩ sư phần mềm (Software Engineer) - là người có khó kiếm được bạn vừa ý.
cái nhìn tổng quát tốt về mọi thứ, vừa có kiến thức vững về
khoa học máy tính như người làm nghiên cứu, vừa có khả (Lưu ý: Tên đặt ra có tính chất khái quát hoá, ko hàm
năng lập trình cực tốt. Đây là nhóm mà các công ty phần chỉ chức danh của các bạn trong công việc hiện tại)

30 DIJSKTRA
VẬY TRỞ THÀNH KĨ SƯ PHẦN MỀM GIỎI Thêm nữa, ở Việt Nam nhiều bạn nghĩ tư duy hệ thống
(GOOGLE/FACEBOOK ENGINEER LEVEL) (system design/system architecture) là 1 vị trí độc lập, nâng
THÌ CẦN NHỮNG GÌ? cao kinh nghiệm một hồi mới cần tới. Quan điểm của mình
thì đây là tư duy mà một kĩ sư phần mềm nào đều cần phải
Đây là 1 biểu đồ các kiến thức nền tảng (fundamentals) có, nếu chưa có thì bạn chỉ ở mức thợ thôi chứ chưa phải
mà mình tổng quát ra được, nhằm giúp các bạn định vị tốt là kĩ sư. Nếu bạn phỏng vấn vào các vị trí lập trình viên của
hơn những điều các bạn đang có/cần bổ sung. Facebook/Google, bạn sẽ thấy những câu hỏi phỏng vấn
đều sẽ kiểm tra tổng quát hết những kiến thức nêu trên (trừ
Nửa trên là những kiến thức thực tế cần thiết khi đi làm, khi bạn là sinh viên mới ra trường, lúc đó câu hỏi phỏng vấn
bao gồm hiểu công nghệ, hiểu quy trình phát triển phần sẽ xoay quanh lập trình thuật toán & cấu trúc dữ liệu).
mềm và kĩ thuật lập trình (clean coding, code refactoring,
v.v) Bạn có và chưa có gì trong những phần nhỏ của biểu
đồ trên?
Nửa dưới là những kiến thức gốc về khoa học máy tính
mà các bạn cần nắm. Cần lưu ý là mình muốn nhấn mạnh
tầm quan trọng của tư duy kĩ thuật có hệ thống (technical
framework of thinking), hay một cách khác là tư duy giải
quyết vấn đề (problem solving), tư duy thiết kế hệ thống
(system design). Tư duy này là khả năng kết nối những kiến
thức lẻ độc lập (lego blocks) mà các bạn học được bên dưới
với nhau để đưa ra hướng giải quyết vấn đề.

Để ý thấy là thường các bạn lập trình viên ứng dụng sẽ


tập trung vào nửa trên, và các bạn nghiên cứu sẽ tập trung
vào nửa dưới của biểu đồ trên.

DIJSKTRA 31
32 DIJSKTRA
Đ
ứng trước giai đoạn được xem là bước
khởi đầu của cuộc cách mạng công
nghiệp 4.0, chúng ta có thể dễ dàng nhận
thấy Việt Nam đang tiếp cận những cơ hội lớn,
sẵn sàng cho sự chuyển mình đầy tích cực và
nhanh chóng trên toàn diện, không chỉ kinh tế, đánh giá là hai năm khởi điểm của hoạt động
mà cả văn hóa, xã hội, giáo dục và công nghệ. offline tự phát của giới công nghệ ở Việt Nam,
Đáng kể và dễ dàng nhận thấy nhất trong lĩnh thông qua diễn đàn meetup.com.
vực công nghệ thông tin chính là việc hình thành Meetup.com là một trang thông tin online, giúp
và phát triển các hội, nhóm, tổ chức mang tính người dùng tự tạo ra các nhóm “meetup”, quy tụ
cộng đồng và có sự kết nối cao những năm gần những người có cùng mối quan tâm về một chủ
đây. Sự hình thành này bắt đầu vào năm 2012, đề nào đó như du lịch, ngoại ngữ, thiền,...Tuy
vừa đem tới những lợi ích, hy vọng cho cộng đồng nhiên, khác với những diễn đàn thông thường,
công nghệ, vừa meetup.com chú
bộc lộ nhiều điểm trọng vào các hoạt
yếu, khó khăn. động offline, yêu
Nhưng cho tới bây cầu các thành viên
giờ, người viết cho tham gia phải gặp
rằng đây mới chỉ là mặt trực tiếp và
khởi đầu cho một giao lưu tương tác
chuyển động mạnh nhóm với nhau tại
mẽ và tiềm năng một địa điểm cụ
hơn nữa, hứa hẹn thể. Việc meet-up
là một động lực xuất hiện tại Việt
giúp thúc đẩy sự Nam gắn khá chặt
năng động và sáng với việc một số lập
tạo trong lĩnh vực công nghệ tại Việt Nam. trình viên người nước ngoài khởi xướng các hoạt
động cộng đồng vào năm 2012. Một ví dụ điển
Bài viết này được dựa trên quan sát cá nhân của hình là JS HCM meetup, sáng lập bởi Nicolas
người viết, vốn đã từng tổ chức hoặc tham dự vào Embleton, một người nước ngoài đang ở VN. Sau
các cộng đồng công nghệ từ năm 2012 tới thời đó, lần lượt iOS, Ruby meetup cũng ra đời trong
điểm hiện tại (năm 2018). giai đoạn này, với sự tham dự của nhiều lập trình
viên ngoại quốc, hay là người Việt đang công tác
Lịch sử hình thành và phát triển tại nước ngoài (Ruby Vietnam).

2012-2013, những meetups đầu tiên xuất Có thể nhận thấy một vài đặc điểm về đặc thù
hiện, tạo tiền đề cho các hoạt động giao lưu trực của giai đoạn này:
tiếp (offline)

Dựa vào một vài thông tin về các hoạt động của
những meet-up mà bản thân người viết đã từng
tham gia trong thời gian này, 2012-2013 được

DIJSKTRA 33
làm việc chung (co-working space). Một trong
những co-working space đầu tiên ở Sài Gòn được
biết đến chính là SaigonHub. Việc hình thành
các co-working space có thể nói là tiền đề cho
sự phát triển mạnh của các meetup ngay sau
đó. Vốn dĩ, bản thân co-working space là một
mô hình mới, nơi cung cấp không gian để làm
việc cho cá nhân hoặc các văn phòng của công ty
startup vừa và nhỏ. Để co-working space tồn tại,
người sáng lập phải phối hợp tổ chức thêm nhiều
hoạt động/ sự kiện, hoặc cho thuê không gian
sự kiện với giá rẻ hoặc thậm chí miễn phí. Chính
điều này đã vô tình khiến cho các hoạt động của
các meetup - vốn do những người tổ chức không
có chuyên môn tổ chức sự kiện - diễn ra dễ dàng
và thường xuyên hơn.
Cũng giống như các mô hình tiên phong khác,
SaigonHub sau khi đối mặt với nhiều khó khăn
như chi phí cao, thị trường vẫn chưa kịp đón
nhận, chưa có nhiều sự kiện được tận dụng và
tổ chức, mô hình còn mới … .Cuối cùng, nhóm
Nội dung đơn giản và chưa có chiều sâu. Các sáng lập của SaigonHub đã quyết định đóng cửa
hoạt động thường thấy của các meetup thời điểm co-working space này vào tháng 4/2014, một
này đều chủ yếu xoay quanh người chia sẻ (speak- điều đáng tiếc. Tuy không thể tiếp tục hoạt động
ers). Các bài nói trong giai đoạn này hầu hết đều sơ nhưng với sự hình thành của mình, SaigonHub
sài và mang tính phi hình thức. Hầu hết diễn giả là đã tạo nên một nền tảng không nhỏ cho các co-
những người đến từ mạng lưới quan hệ cá nhân của working space ngày càng quy mô và chất lượng
các thành viên ban tổ chức. Thêm vào đó, chiếm hơn hoạt động sau này.
một phần không nhỏ các thành viên đến tham gia
meetup với mục đích chính là để trau dồi ngoại ngữ,
thay vì chuyên môn. 2014 - đầu 2016: phát triển

Quy mô nhỏ. Hầu hết quy mô của các meetup chỉ Sang năm 2014, những mô hình meetup đầu
dao động ở quy mô từ 1-30 người. Địa điểm tổ chức tiên vẫn tiếp tục được duy trì. Tuy nhiên, một số
thường là ở các quán cà phê nhỏ. khác phải dừng lại do thiếu cơ chế hoạt động bài
bản và có tính tổ chức. Dẫu vậy, 2014-2015 có thể
Mang tính tự phát và không bền vững. Hầu hết được xem là hai năm chứng kiến sự chuyển mình
các meetup giai đoạn này đều được thành lập dựa tích cực dần của cộng đồng.
trên yếu tố quen thân của một nhóm người làm nền
tảng. Phần lớn các thành viên sẽ biết nhau từ trước, Có hai nguyên khách quan dẫn đến sự phát
hoặc sẽ dần quen thuộc với nhau thông qua các hoạt triển này. Đầu tiên là về yếu tố con người, những
động. cá nhân tham gia tổ chức các meetup giai đoạn
đầu dần trở nên trưởng thành hơn, trong đó có
Chưa có nhân lực tổ chức bài bản. Các hoạt động một vài cá nhân xuất sắc. Kế đến, những công
giai đoạn này đa số đều là do chính bản thân các
bạn lập trình viên đứng ra tự tổ chức nên hầu như
đều không có yếu tố bài bản như các công ty sự kiện
chuyên nghiệp cũng như không có mô hình truyền
thông hiệu quả đến cho cộng đồng. Đó là lý do các
meetup đa phần đều hoạt động cầm chừng với quy
mô nhỏ lẻ và mang tính rời rạc, thiếu sự gắn kết.

Ngoài ra, nhắc đến sự phát triển của meetup thì


không thể không kể đến vai trò của các không gian

34 DIJSKTRA
ty nhận thấy tiềm năng của việc phát triển cộng
đồng công nghệ và bắt đầu ủng hộ, hỗ trợ tổ chức
các hoạt động cộng đồng dần nhiều hơn. Trong số các công ty đã góp phần hỗ trợ cộng
đồng trong giai đoạn này, Sillicon Straits Saigon
Các meetup diễn ra thường xuyên hơn trong được xem là một trong các nhân tố nổi bật khi đồng
giai đoạn này, dù chưa thật sự “thoát ra” được thời đứng ra tổ chức và cung cấp địa điểm cho các
những vấn đề bất cập của giai đoạn trước đó. Đây hoạt động của cộng đồng nói chung. Các hoạt động
là thời điểm mà nhiều nhóm cộng đồng mạnh như Startup Weekend, Angel Hack đều được tổ chức
như Ruby Vietnam, Grokking,.. được hình thành ở đây. Ngoài ra, những mô hình mới như Geeky Week-
và bắt đầu phát triển mạnh trong giai đoạn mới. end ra đời, đánh dấu thời điểm sôi động và bùng nổ
Cùng lúc đó, Dreamplex, một co-working space của các cộng đồng công nghệ. Mỗi buổi meet-up của
ở phân khúc cao cấp cũng được thành lập trong Geeky Weekend thường quy tụ từ 80 tới 200 lập trình
giai đoạn này. Dreamplex đã hỗ trợ địa điểm cho viên với ước chừng ít nhất 30 người thường xuyên
khá nhiều hoạt động cộng đồng, với cơ sở vật tham dự.
chất tiện nghi, khang trang. Đây là một nguồn Đây cũng là năm bản thân Grokking định hình
động lực cho khá nhiều người làm cộng đồng lúc hướng phát triển và đi đến quyết định thành lập tổ
bấy giờ. chức phi lợi nhuận Grokking Vietnam.

2016: năm khởi nghiệp Những bài học được rút ra

Được chính phủ xem như là năm khởi nghiệp, Với cơ hội được làm việc xuyên suốt với những cá
năm 2016 chứng kiến nhiều cột mốc quan trọng nhân và tổ chức suốt từ giai đoạn đầu cho đến thời
của cộng đồng công nghệ ở Việt Nam. Các tuyên điển hiện tại , người viết xin phép được chia sẻ một
bố đầu tư, hỗ trợ hệ sinh thái khởi nghiệp được vài bài học được rút ra từ quan sát và kinh nghiệm
đưa ra, các diễn đàn, hội chợ được tổ chức. Các thực tiễn, với hy vọng sẽ cung cấp cho bạn đọc góc
phương tiện truyền thông cũng góp phần đem nhìn gần gũi và rõ ràng hơn về những cộng đồng
những tin tức về thế giới công nghệ và startup đang hoạt động cũng như các cộng đồng và hội
tới mọi người một cách dồn dập và đầy hào hứng nhóm vừa thành lập.
hơn. Cùng lúc đó, hoạt động cộng đồng cũng bắt
đầu có sự thay đổi về chất mạnh mẽ hơn, khi một
số tổ chức, cá nhân bắt đầu thực hiện những ý
tưởng mới với kế hoạch phát triển dài hạn và có
tính bền vững cao.

DIJSKTRA 35
Một mục tiêu, sứ mệnh rõ ràng. Nếu những ai đã
từng tham gia vào khâu tổ chức các hoạt động cộng
đồng nói chung từ 1-2 năm trở lên, hẳn đều trải qua
cảm giác này: bị mất phương hướng, cảm giác buồn
chán và dễ bỏ cuộc. Vượt qua cái cảm giác hứng
thú ban đầu, hầu hết công việc liên quan đến cộng
đồng sẽ đòi hỏi tính nhẫn nại và bền bỉ. Điều này
cần được bắt nguồn từ sứ mệnh mà bản thân người
tổ chức tự đặt ra cho mình. “Ăn cơm nhà, vác tù và
hàng tổng” vốn dĩ chưa bao giờ là một công việc dễ
dàng, nhưng chỉ cần có một sứ mệnh đủ mạnh, tự
khắc động lực và sự bền bỉ sẽ tới.

Đảm bảo tính nhất quán cho nội dung. Bản thân
người viết nhìn thấy nhiều hội nhóm được lập ra Cởi mở trong việc ghi nhận ý kiến đóng góp
một cách liên tục. Có nhóm ban đầu là 50 người, sau từ cộng đồng, nhưng đừng lệ thuộc vào nó.
đó lên vài trăm, sau đó cũng chìm dần. Quá trình Xây dựng cộng đồng là một công việc mang tính
chìm có khi trong vài tuần là thấy ngay, cũng có khách quan, bạn sẽ phải thường xuyên lấy ý kiến
khi trong vài tháng đến một năm. Điểm chung của đóng góp từ cộng đồng. Vậy đâu là điểm dừng?
những nhóm thảo luận bị chìm này thường rơi vào Theo người viết, bạn nên xác định rõ mình nên
tình huống: nội dung loãng do các thành viên chia nghe ý kiến đóng góp từ ai. Một thực tế đáng
sẻ nội dung không định hướng. Bản thân người tổ buồn là góp ý thì dễ, nhưng chịu trách nhiệm với
chức cộng đồng cần đảm bảo được tính nhất quán ý kiến đóng góp của bản thân mình thì khó. Khi
cho cộng đồng của mình. Những nội dung gì là nên bạn đặt câu hỏi: Cần phải làm gì trong lần hoạt
chia sẻ và những nội dung là không nên chia sẻ. động tiếp theo? Bạn dễ dàng nghe ý kiến đóng
góp về ý tưởng. Nhưng hãy tự hỏi, liệu những
Đòi hỏi sự chuẩn bị và tính chuyên nghiệp cao hơn. người đề xuất ý tưởng có tham gia chính hoạt
Khác với giai đoạn đầu, khi các hoạt động động đó không? Theo kinh nghiệm của cá nhân
cộng đồng còn đang manh nha, nội dung còn sơ xài, người viết, phần lớn câu trả lời là “không”. Hãy
dần dần, việc tổ chức các hoạt động cộng đồng sẽ lắng nghe, hãy tôn trọng sự phản hồi, nhưng với
đòi hỏi mang tính chỉnh chu và bài bản hơn. Đặc một tâm thái có chọn lọc.
biệt, cần phân biệt rõ ràng giữa sự đơn giản, gọn
gàng của một sự kiện (có được nhờ kinh nghiệm tổ Hãy kiếm người đồng tổ chức. Giống như khởi
chức, tối ưu hóa từng khâu chuẩn bị) với sự qua loa, nghiệp vậy, người đồng hành cùng bạn trong việc
sơ sài. Sự nhầm lẫn này rất dễ xảy ra, đặc biệt là đối xây dựng cộng đồng là vô cùng quan trọng. Sẽ
với những hoạt động có vẻ dễ tổ chức như một buổi rất tốt nếu như người đồng tổ chức của bạn có
gặp gỡ kết nối quy mô nhỏ (coffee talk) đơn thuần. những kỹ năng mà bạn còn thiếu hoặc còn yếu, vì
đây sẽ là phần bổ sung quan trọng, định hình cho
Phát triển về lượng, hay là chết. Đứng lại, tức là một tổ chức hoàn hảo hơn.
thụt lùi. Điều này rất đúng, đặc biệt là cho lĩnh vực
công nghệ nói chung và việc tổ chức cộng đồng nói Và cuối cùng, hãy kiên nhẫn.
riêng. Bản thân người viết đã từng tự hỏi: việc xây
dựng một cộng đồng meetup ổn định về số lượng
người tham gia liệu có khả thi hay không? Và kết
luận bản thân tự rút ra đó là đối với cộng đồng: chất
lượng nội dung và người tham dự phải đảm bảo, số
lượng phải tăng dần. Số lượng tăng dần nhanh, hay
chậm, còn tùy thuộc độ kiên nhẫn và tầm nhìn mà
người tổ chức tự đặt ra cho mình. Nhưng song song
với đó, chất lượng tốt chính là điều then chốt quyết
định ý nghĩa của việc cộng đồng tồn tại. Nếu không
đảm bảo được hai yếu tố này, bản thân cộng đồng
sẽ dần dần co cụm lại thành một nhóm nhỏ những
người quen biết, rồi dần dần sẽ mất hút.

36 DIJSKTRA
Đối với một người kỹ sư phần mềm, việc không ngừng ôn luyện kiến thức là điều không thể thiếu.
Đến với chuyên mục Góc thử thách, mỗi kỳ team Grokking sẽ giới thiệu đến các bạn một vài câu đố
nho nhỏ giúp các bạn có cơ hội review lại vốn kiến thức của mình.
Các bạn nào muốn thảo luận đáp án vui lòng ghé thăm diễn đàn thảo luận của Grokking nhé:
discuss.grokking.org

CÂU 1: [OS] CÂU 4: [DATABASE INDEX]


Parallelism & Concurrency, chọn tất cả câu sai: Chọn tất cả các câu đúng về database indexes trong
PostgreSQL:
A. Nếu máy tính chỉ có 1 CPU core thì khi chạy
chương trình sẽ không đạt được parallelism A. Database index được biểu diễn bằng b-tree
B. Nếu máy tính chỉ có 1 CPU core thì khi chạy B. Khi thêm index vào, tốc độ truy xuất dữ liệu sẽ
chương trình sẽ không đạt được concurrency có khả năng nhanh hơn trong khi đó tốc độ insert/
C. Parallelism chỉ đạt được khi chương trình chạy ở update không đổi
các processes khác nhau C. Partial Index là kỹ thuật được sử dụng để đánh
D.Khi viết parallel program sẽ không bị vấn đề về index trên một tập con dữ liệu trong bảng.
race condition D. Index (column_a, column_b) tương đương với
index (column_b, column_a)
CÂU 2: [NETWORK] E. B-Tree Index có thể sử dụng với những query
Cho địa chỉ IP 162.16.168.196/28, hỏi IP 162.16.168.30 như LIKE, SIMILAR TO
có nằm cùng đường mạng hay không?
CÂU 5:
A. Có Chọn những câu đúng về docker:
B. Không
A. Lệnh docker inspect <container name> dùng để
xem logs trong quá trình vận hành của một con-
CÂU 3: [OS] tainer.
Chỉ ra những tính chất của một process (Chọn tất cả B. Lệnh docker ps sẽ liệt kê danh sách những con-
những câu đúng): tainer đã shutdown.
C. Lệnh docker-compose run sẽ khởi động tất cả
A. Bên trong 1 process có thể có nhiều thread những containers.
B. Bên trong một thretad có thể có nhiều process D. Tham số --ipaddress trong lệnh docker run sẽ
C. Các process không sử dụng chung một không gán địa chỉ IP cho container.
gian vùng nhớ E. Có thể map nhiều port bên trong các container
D. Các process giao tiếp với nhau qua IPC với một port của server.

DIJSKTRA 37
780.926
là tổng số nhân lực trong ngành
công nghiệp CNTT tính đến năm
2016. Trong đó, 27,4% là tỉ lệ
lao động đang tham gia lĩnh vực
công nghiệp phần mềm, công
nghiệp nội dung số và dịch vụ CNTT.

Tổng số doanh nghiệp CNTT


cả nước năm 2016 ước tính
là 24.501 doanh nghiệp tăng

L à cuốn sách kinh điển về quản lý phát triển phần mềm. Dù


được viết vào khoảng năm 60-70 nhưng vẫn có nhiều bài học
bổ ích cho đến tận hôm nay.
13,13% so với năm 2015.

Tổng doanh thu lĩnh vực Công

“ Thêm người vào một dự án phần mềm đã bị trễ càng làm nó trễ hơn”,
đây là một trong các ý được đề cập trong sách, nghe qua có vẻ ngược
đời nhưng thực tế luôn như vậy. Dự án phần mềm thường phức tạp,
nghiệp CNTT năm 2016 ướctính
đạt 1.500.009 tỷ đồng (tương
đương 67,693 tỷ USD) tăng 11,49%
trong đó việc trao đổi thông tin giữa những thành viên sẽ tốn khá so với năm 2015, trong đó công
nhiều thời gian. Chắc là bạn cũng đã từng tự hỏi là tại sao phải mất nghiệp phần cứng là 58,838 tỷ
ngần ấy thời gian chỉ để thảo luận, họp, giới thiệu việc cho người USD, công nghiệp phần mềm là
mới thay vì đơn giản là viết code? 3,038 tỷ USD, công nghiệp nội
dung số là 739 triệu USD và dịch
Ngoài ra, trong sách còn đề cập đến những mô hình phát vụ CNTT (trừ buôn bán, phân phối)
triển phần mềm mới như Agile Development, Extreme là 5,078 tỷ USD.
Programming giúp chia nhỏ công việc, chia nhỏ nhóm
để tránh cồng kềnh, giúp quá trình triển khai dự án trở
nên tinh gọn và thích nghi với sự thay đổi nhiều hơn. Về đào tạo và phát triển nguồn
nhân lực CNTT, số lượng các trường
Nếu công việc của bạn liên quan đến phát triển địa học ,cao đẳng có đào tạo về
phần mềm, dù là lập trình viên hay là quản CNTT, điện tử, viễn thông, an toàn
lí, đang làm việc cho dự án lớn hay dự thông tin năm 2016 là 250 trường,
án khởi nghiệp thì cuốn sách này với tổng số chỉ tiêu tuyển sinh đại
cũng đều bổ ích. học, cao đẳng các ngành CNTT-TT
là trên 68.000 sinh viên. Tuy nhiên,
tỷ lệ thực tế tuyển sinh đại học,
cao đẳng đạt 77,12% và tỷ lệ tốt
nghiệp đại học, cao đẳng ngành
CNTT-TT đạt 93,88%.

Đối với đào tạo nghề, cả nước có


khoảng 164 trường cao đẳng nghề,
trung cấp nghề đào tạo về CNTT,
điện tử, viễn thông và an toàn thông
tin, với tổng chỉ tiêu tuyển sinh
là 18.311 sinh viên, tỷ lệ thực tế
tuyển sinh đạt 68,27% và tỷ lệ
tốt nghiệp là 52,4%.

(Theo Sách Trắng CNTT-TT Việt Nam


38 DIJSKTRA năm 2017 do Bộ TT&TT phát hành)
In: 500 bản. Khổ 20.5 x 29.5 cm.
In tại: Công ty CP in Gia Định-
9D Nơ Trang Long, P. 7, Q. Bình Thạnh, TP. HCM.
Số ĐKKHXB: 660 - 2018/ CXBIPH / 1 - 38 / ĐoN, Cục Xuất bản,
In và phát hành xác nhận ngày: 01/03/2018,
Quyết định xuất bản số: 70B/QĐ-ĐoN, do NXB Đồng Nai cấp ngày
13/3/2018.
In xong và nộp lưu chiểu: quý 2/2018.

Nhà xuất bản Đồng Nai


1953J (210 cũ) Nguyễn Ái Quốc, TP Biên Hòa, Đồng Nai
Ban Biên tập: (02513) 825 292
P Kinh doanh: 946 521
P Kế toán: 946 520
Fax: (02513) 946 530 - Email: nxbdongnai@hcm.vnn.vn

DIJSKTRA 39
40 DIJSKTRA

You might also like