Categories
Miscellaneous

Bàn về mục đích đọc sách

Sáng nay khí trời mát mẻ, lại là dịp đầu tháng nên kiếm một đề tài nhẹ nhàng và gần gũi để viết trong thời gian chờ anh em đồng nghiệp vào làm. Mình định viết về đề tài sách cũng khá lâu nhưng chưa biết bắt đầu thế nào, chợt nhớ đến cách đây ít lâu có đọc một bài blog về việc nếu chúng ta ngưng sử dụng các mạng xã hội (facebook, twitter,..) thì có thể dành thời gian đó đọc khoảng 200 cuốn sách trong một năm. Wow!!!

Nếu đọc những bình luận của bài viết đó, cũng như bình luận từ những trang dẫn link (VD: Reddit, Hackernews..) thì thấy có nhiều luồng bình luận, đại khái là có 2 nhóm chính xoáy vào việc tác dụng của việc đọc sách là đọc nhiều cũng chả có tác dụng gì và một nhóm là đọc có tác dụng. Tất nhiên, mình ủng hộ nhóm đọc sách có tác dụng và đọc càng nhiều càng có tác dụng nhiều. Chẳng thế mà Warren Buffer đọc mỗi ngày 800 trang, Bill Gates mỗi năm đọc hơn 50 cuốn.

Như nhiều bạn cũng biết là Tuấn thích đọc sách và chia sẻ về sách. Để tránh các bạn trẻ (kể cả bạn già) bị ảnh hưởng bởi tư tưởng đọc sách không có tác dụng và đọc nhiều sách là vô ích nên Tuấn mới quyết định làm loạt bài “Bàn về sách” gồm 4 phần:

  • Bàn về mục đích của sách (bài viết bạn đang xem)
  • Bàn về mua sách
  • Bàn về đọc sách
  • Bàn về hậu đọc sách

Trong bài này, mình sẽ chia sẻ về mục đích của việc đọc sách và giúp các bạn không bị lạc lối trong đống sách. Như hầu hết chúng ta đã được “dạy dỗ”, mục đích đọc sách từ khi học lớp 1 đến tốt nghiệp đại học (hoặc cao học) là đọc sách giúp tăng khả năng thi đậu và lấy lòng bạn bè, thầy cô, giáo sư. Không thể phủ nhận là cho đến ngày nay, một vài kiến thức trong sách giáo khoa đang nằm trong tiềm thức của bạn đôi khi “hiện” về giúp bạn một số tình huống nào đó mà bạn ít ngờ được.

Khi mình dùng từ sách, các bạn có thể hiểu là mình đang đề cập đến những ấn phẩm để đọc, in thành nhiều trang và đóng thành tập như sách, truyện, manga, comic, tạp chí, sách tranh…

Nhìn chung, mình phân loại mục đích của việc đọc sách thành 3 mục đích chính:

  1. Đọc sách để giải trí
  2. Đọc sách để học hỏi
  3. Đọc sách để làm kinh tế

Đọc sách để giải trí

Đây là mục đích dễ dàng nhận thấy được khi các bạn đọc các sách văn học như truyện ngắn, tiểu thuyết…mục đích là giải trí nên đọc thể loại này không chú trọng vào kiến thức thu gặt được mà chú trọng vào cảm xúc, mô tả không gian được tác giả dựng lên, từ không gian kì ảo trong các truyện thần tiên, không gian bí ẩn trong các thể loại kinh dị, trinh thám hay không gian đời thường như các truyện ngôn tình hiện đại…

Chính vì mục đích giải trí nên nhiều nhà-đọc-sách-thượng-đẳng thường chỉ trích, chê bai các bạn thích đọc văn học, tiểu thuyết. Tuy nhiên, có thể họ chưa đọc thử hoặc không có thời gian để đọc thể loại sách này. Nếu đọc sách sẽ thấy những bộ phim chuyển thể từ sách ít khi nào hay bằng sách. Bởi đọc sách truyện mô tả, buộc bạn phải duy trì một khối lượng trí nhớ gần như là dài hạn cho toàn bộ nhân vật, kèm theo đó là lưu giữ được mạch truyện.

Bên cạnh đó, một kỹ năng mà mình đánh giá cao nhất là khả năng tưởng tượng không gian, bối cảnh cho các tình tiết trong sách. Mình có đọc một cuốn sách có đề cập đến một nghiên cứu cho thấy những người có khả năng hình dung, tưởng tượng được một hình học không gian thì có khả năng tư duy logic tốt hơn và khuyến khích trẻ em, thanh thiếu niên tiếp cận để phát triển khả năng tượng hình.

Ngoài ra, có nhiều sách là truyện ngắn, tiểu thuyết đọc thấy ly kì nhưng lại đem lại cho bạn nhiều kiến thức về vùng miền, lĩnh vực mà ngữ cảnh cuốn sách mang lại như những câu chuyện về du lịch, trinh thám công nghệ…

Do đó, đừng xem thường những cuốn sách viết ra với mục đích giải trí, đôi khi tác dụng nó mang lại thấm sâu hơn vào tiềm thức mà bạn không hề biết được.

Đọc sách để học hỏi

Đây là mục đích mà nhiều người-đọc-sáchngười-không-đọc-sách nghĩ tới thường xuyên cho việc đọc sách. Và cũng chính mục đích này dẫn đến không biết bao nhiêu tranh cãi về tác dụng của đọc nhiều sách. Nguyên nhân sâu xa của việc tranh cãi này nằm ở việc chúng ta đánh đồng và nhầm lẫn giữa việc đọc, hiểu và nhớ. Họ (những người chỉ trích) nói rằng đọc nhiều sách mà không nhớ, không hiểu gì hết thì thà khỏi đọc cho rồi vì đọc xong có nhớ gì đâu.

Bản thân hành động đọc sách là một hành động đơn thuần, dùng mắt, miệng để đưa câu chữ chạy qua não và hy vọng những con chữ này lưu lại ở não càng lâu càng tốt (gọi là nhớ) và biết được cách sử dụng, ý nghĩa của những câu chữ chạy qua (gọi là hiểu). Bạn có nhớ ngày xưa mình học thuộc lòng bảng cửu chương thế nào chứ và ngày nay vẫn dùng?

Nếu không nhớ, không hiểu thì coi như là không đọc là một quan điểm sai lầm của nhiều cán-bộ-lão-thành-bận-mưu-sinh, bởi vì ngoài việc lưu vào tiềm thức, nó sẽ thúc đẩy thay đổi hành động mỗi ngày. Không tin bạn có thể thử vào nhà sách tìm 10 cuốn sách về tình yêu mà đọc, đảm bảo bạn sẽ ngọt ngào hơn. Hoặc kiếm những thể loại truyện kinh dị, chém giết đẫm máu mà đọc, đảm bảo não bạn sẽ hoạt động hết công suất. Và kể cả nó cũng ảnh hưởng vào giấc mơ đấy, thử đi. Đây chính là tác dụng đọc sách ảnh hưởng tiềm thức.

Các bạn có thể nói lĩnh vực tiềm thức là một lĩnh vực bí ẩn, chưa khám phá kỹ nên mình lấy ví dụ khác cho việc đọc rồi quên mà đem lại tác dụng. Đây là lý do chính mà mình thích đọc nhiều sách, chính là vén bức màn ngu dốt. Có một nghịch lý kỳ lạ là con người càng ít đọc (ít học) thì lại càng thấy mình ít ngu dốt hơn những người đọc nhiều (học nhiều) !!!. Càng đọc càng thấy mình ngu dốt. Đấy chính là tư tưởng của hiệu ứng Dunning–Kruger mà mình có một bài viết cách đây 10 năm.

Việc đọc nhiều sách không phải chỉ để nhớ, học thuộc lòng, hiểu tường tận mà đôi khi đơn giản chỉ là đễ bớt ngu về một thứ gì đó, như là những địa danh ở Nhật hoặc những kiến thức trong ngành y học, vật lý học… mà nếu không đọc thì cả đời cũng không nghĩ là có những cái như vậy.

Một khi bức màn ngu muội của bạn được vén ra ngày một nhiều, mà mình hay nói là bức màn vô minh của mình ngày càng được vén ra thì mình nhìn mọi thứ với con mắt thông cảm và dễ hiểu hơn và lại thích đọc ngấu nghiến hơn nữa. Do đó, đừng nghe ai nói là đọc sách nhiều không có tác dụng, đó là lời khuyên từ những người không bao giờ đọc sách và cảm thấy ganh tỵ với những người có thời gian đọc sách và ngày càng bớt ngu muội.

Đọc để làm kinh tế

Đây là nhóm nhỏ, nhưng không kém phần quan trọng. Có một số ngành nghề kiếm tiền trực tiếp từ việc đọc sách. Nhưng nhóm đọc để làm kinh tế  mình nói đến là những người đọc sách rồi “thông báo” lên Facebook, Twitter…PR, lấy chút danh tiếng từ cộng đồng. Thực ra bạn đọc sách hay, khoe lên mạng để người khác biết là việc bình thường (mình cũng hay khoe lên Facebook kiếm vài xu nổi tiếng mà).

Mình vẫn luôn đánh giá cao những người khoe sách lên mạng xã hội bất kể bạn có đọc cuốn sách đó hay chưa. So với những người suốt ngày khoe điện thoại, quần áo, xe cộ, gái gú…thì khoe sách vẫn tốt hơn nhé. Hãy khoe khi còn có thể, ít ra bạn cũng đã mua sách, có công suy tư về sách và suy tư cho cộng đồng, giúp sách đi xa hơn đến mọi người.

Như vậy, thông qua bài này mình đã chia sẻ những góc nhìn cá nhân về việc đọc sách và đọc nhiều sách. Bản thân mình đặt mục tiêu năm nay sẽ đọc 100 cuốn nên sẽ cố gắng nhiều hơn trong việc cân bằng cuộc sống, công việc và…đọc sách. Nếu bài viết có phần đụng chạm đến những anh hùng không cần đọc sách vẫn giỏi và hết vô minh thì cho mình tạ lỗi. Bài tiếp theo sẽ bàn về mua sách, Tuấn sẽ chia sẻ những kinh nghiệm cá nhân trong việc lựa chọn và mua sách thế nào.

Categories
Review sách software Tech Startup Technology

Review sách “Product-Led Growth” của Wes Bush

Hôm nay review đến mọi người cuốn sách tiếng Anh mà đọc không rời mắt và hoàn thành sau một ngày chỉ với vài tiếng và có thể nói đọc nhanh hơn cả tiếng Việt. Bởi tính chất hấp dẫn và hữu ích của sách này nên dành hẳn 2 tiếng để làm sketch note và chia sẻ với mọi người để cùng tham khảo cũng như giúp các bạn dễ dàng quyết định mua sách này. Đó là cuốn “Product-Led Growth: How to Build a Product That Sells Itself” của Wes Bush.

Sách này gồm 3 phần và phần nào cũng cực kỳ hấp dẫn. Phần đầu nói về việc đánh giá và so sánh giữa công ty product-led và sales-led để giúp bạn đưa ra quyết định tiếp cận phù hợp với mô hình tổ chức cũng như đặc thù sản phẩm và thị trường. Phần tiếp theo nói về phương pháp tiếp cận khách hàng và phần cuối là phương pháp tối ưu hệ thống bán hàng, marketing.

Nếu bạn nào đang hoặc sắp tham gia lĩnh vực cung cấp phần mềm, đặc biệt là Saas như Tuấn thì sẽ không nên bỏ qua cuốn sách này vì có rất nhiều thông tin cực kỳ bổ ích. Từ lên chiến lược phát triển sản phẩm, chiến lược giá cũng như chiến lược marketing để mang lại khách hàng, doanh thu và lợi nhuận cho công ty.

Bên dưới là ghi chú cho từng phần từ sách, và mỗi chương trong sách cũng sẽ được chụp cận cảnh để giúp bạn thấy rõ hơn các nội dung chi chú của Tuấn. Xin thứ lỗi nếu chữ viết không rõ, tuy nhiên, nếu thấy nội dung hay thì bạn có thể mua để ủng hộ tác giá, sách có rất nhiều ví dụ và nội dung hay mà phần ghi chú mình chia sẻ trên đây không đề cập như các chương liên quan đến những sai lầm mắc phải khi cải tiến..

Ghi chú về phần 1

– So sánh mô hình giữa chiến lược sales-led và product-led để cho thấy hai cách tiếp cận khác nhau của việc phát triển sản phẩm.

Sanh sánh 2 mô hình sales-led và product-led và vì sao trong một công ty theo product-led thì các bộ phận đều hướng tới sản phẩm (product).
Dựa vào đặc thù sản phẩm và mô hình kinh doanh mà có các chiến thuật tiếp thị khác nhau để đem lại lợi thế cạnh tranh.
Hai hướng tiếp cận bán hàng khác nhau đó là Top-Down và Bottom-Up. Đối với doanh nghiệp làm Saas thì tốt nhất là theo chiến lược Bottom-Up bởi sẽ dễ dàng tiếp cận với tập khách hàng lớn, tiết kiệm chi phí và có thể dự đoán được doanh thu.

Ghi chú về phần 2

Mô hình UCD hướng đến khách hàng để đưa ra những thông tin phù hợp đến khách hàng.
Hiểu được các giá trị của sản phẩm bạn mang lại cho khách hàng.
Các chiến lược giá để giúp bạn đưa ra những bảng giá tính năng phù hợp nhất cho sản phẩm của mình và kèm theo nhiều phương pháp định lượng, định tính để giúp bạn ra bảng giá phù hợp nhất.

 

Phương pháp tối ưu để đem lại giá trị như đã truyền thông đến khách hàng.

Ghi chú về phần 3

Đây là phần được đánh giá là hay nhất và có nhiều kiến thức thực tế nhất để làm theo và áp dụng nhằm tối ưu hệ thống marketing và bán hàng.
Mô hình ICE để tìm ra những tính năng sẽ đem lại hiệu quả cao nhất giúp cải tiến sản phẩm.
Áp dụng The Bowling Alley Framework để tăng số lượng khách hàng.
Một số phương pháp để tối ưu doanh thu trung bình trên một người dùng (ARPU)
Phân loại churn và một số phương pháp giúp giảm tỷ lệ churn để hạn chế ảnh hưởng đến việc thất thoát doanh thu.

 

Đọc thêm về sách này tại https://www.amazon.com/Product-Led-Growth-Build-Product-Itself/dp/1798434520.

Hiện tại Tuấn vẫn luôn tìm kiếm những bạn có kinh nghiệm trong lĩnh vực marketing và growth, đặc biệt cho các sản phẩm phần mềm Saas. Nếu bạn quan tâm có thể email tới [email protected] để trao đổi thêm nhé.

Categories
Review sách software Technology

Review sách “The Mythical Man-Month” của Frederick P. Brooks

Tuần này mình sẽ review một cuốn sách khá hay dành cho các project manager có tựa là “The Mythical Man-Month”. Cuốn sách này lần đầu xuất bản 1975, tính ra cũng được 45 năm. Tuy đã viết từ lâu như vậy nhưng hầu hết những kinh nghiệm, quan sát và kết luận vẫn còn đúng cho ngành phát triển phần mềm hiện nay.

Brooks là một cây đa cây đề trong ngành phần mềm và thời điểm viết sách này (1975) là ông đang quản lý team phần mềm tại IBM. Cá nhân mình lập trình hơn 15 năm và quản lý nhiều dự án thì thấy những tư tưởng của tác giả đến nay vẫn dùng được. Sách viết từ 1975 nên tiếng Anh thời đó đọc tra từ điển cũng đuối vì có nhiều từ, mẫu câu đã cũ hoặc khá hàn lâm, đọc cũng nhức não mới hiểu nổi ý nghĩa.

Sách gồm 17 chương, trong đó có 4 chương mới được viết thêm vào 1995 nhân kỷ niệm 20 năm xuất bản. Sách này chình là khởi nguồn cho định luật Brooks cũng khá nổi tiếng là “Adding manpower to a late software project makes it later” (Đưa thêm người vào 1 dự án đang trễ, sẽ chỉ khiến nó càng trễ hơn).

Sách bao gồm những bài luận ngắn, riêng lẻ về các đề tài xoay quanh việc quản lý dự án phần mềm như về tài nguyên hệ thống, phần cứng, đội nhóm, nhân sự, dự án, tài liệu nội bộ, manual cho người dùng, sự thay đổi trong cấu trúc tổ chức, cũng như những khó khăn trong xây dựng phần mềm mà sẽ không có phương pháp triệt để nào giải quyết dứt điểm.

Chương mình thích hơn hết là Chương 2 (The Mythical Man-Month, cũng là tựa sách luôn) và chương 16 (No Silver Bullet – Essence and Accident in Software Engineering). Chương 2 là khởi nguồn cho định lý Brooks, liên quan đến việc phân tích sự liên hệ giữa nhân sự và thời gian (Man-month) và chỉ ra những trường hợp nào thì việc tăng người mới hiệu quả và cũng giải thích tại sao không hiệu quả trong những trường hợp khác. Chương 16 bàn về khó khăn khi triển khai cũng đưa ra nhiều góc nhìn và quan điểm khiến cho việc phát triển phần mềm sẽ luôn gặp khó khăn bởi có nhiều vấn đề là không thể thay đổi hay có giải pháp tối ưu để giải quyết.

Ngoài hai chương này ra, thì các chương khác bàn về documentation, manual cũng rất hay. Có hai khái niệm khác được đề cập và đến nay thấy hữu ích là “Conceptual Integrity” (yêu cầu cho thiết kế hệ thống) và “Second-System Effect” (các bạn startup sẽ thấy chương này hữu dụng vì nó chỉ ra hiệu ứng second-system, khiến cho việc bạn xây dựng những hệ thống quá phức tạp, ảnh hưởng đến thời gian release dự án bởi vì bạn…quá giỏi giang trước đó – thành công của First system).

Bên dưới là nội dung tóm lượt của Chapter 2 (The Mythical Man-Month) mình copy ra đây để các bạn lấy ý tưởng.

2. The Mythical Man-Month

2.1 More programming projects have gone awry for lack of calendar time than for all other causes combined.

2.2 Good cooking takes time; some tasks cannot be hurried without spoiling the result.

2.3 All programmers are optimists: “All will go well.”

2.4 Because the programmer builds with pure thought-stuff, we expect few difficulties in implementation.

2.5 But our ideas themselves are faulty, so we have bugs.

2.6 Our estimating techniques, built around cost-accounting, confuse effort and progress. The man-month is a fallacious and dangerous myth, for it implies that men and months are interchangeable.

2.7 Partitioning a task among multiple people occasions extra communication effort-training and intercommunication.

2.8 My rule of thumb is 1/3 of the schedule for design, 1/6 for coding, 1/4 for component testing, and 1/4 for system testing.

2.9 As a discipline, we lack estimating data.

2.10 Because we are uncertain about our scheduling estimates, we often lack the courage to defend them stubbornly against management and customer pressure.

2.11 Brooks’s Law: Adding manpower to a late software project makes it later.

2.12 Adding people to a software project increases the total effort necessary in three ways: the work and disruption of repartitioning itself, training the new people, and added intercommunication.


Sách có thể mua trên Amazon. Chúc mọi người một tuần vui vẻ.

Categories
Technology

Xây dựng hệ thống Log cho Microservices

Hôm qua mình có làm speaker chia sẻ về kiến trúc hệ thống Log của Teamcrop.com, thấy nhiều bạn hưởng ứng và quan tâm quá nên mình khai trương blog năm mới bằng một bài viết ngắn nói về chủ đề này.

Xây dựng hệ thống log được đánh giá rất quan trọng, đặc biệt đối với các hệ thống đang trong giai đoạn tăng trưởng người dùng và mở rộng tính năng. Có nhiều hướng tiếp cận khác nhau để triển khai hệ thống log, từ việc sử dụng các dịch vụ Saas có sẵn, không cần cài đặt hay server gì như các hệ thống Loggly, DataDog, Papertrail…cho tới các open source như Graylog, ELK (ElasticSearch, Logstash, Kibana) Stack, Grafana…Tuy nhiên, do đặc thù của dữ liệu, số lượng log và tốc độ truy xuất mà Teamcrop buộc phải thiết kế một hệ thống log riêng để giải quyết các vấn đề về chi phí lưu trữ và vận hành.

Để xây dựng hoặc tìm hiểu một hệ thống Log, chúng ta cần thấy được các thành phần của hệ thống Logging bởi performance và tính tiện dụng đều dựa vào mô hình hệ thống Log. Mình tạm chia một hệ thống Log thành ba thành phần cơ bản là Collector, Storage và Dashboard.

  • Collector là phân hệ chịu trách nhiệm thu thập dữ liệu log từ các nguồn cung cấp (syslog, access log, error log, api request, sql query..)
  • Storage là thành phần sẽ lưu trữ dữ liệu log, có thể là tạm thời hoặc vĩnh viễn, ví dụ như RabbitMQ (tạm thời), File System (tạm thời), MySQL, Clickhouse…
  • Dashboard là thành phần sẽ truy xuất vào storage và hiển thị dữ liệu bao gồm data table, biểu đồ, dashboard…đến đối tượng cần coi log.

Để dễ dàng tiếp cận với các vấn đề của Log, trước tiên chúng ta cần phân loại log vì mỗi loại log sẽ có đặc tính khác nhau về số lượng cũng như cách truy xuất, sử dụng. Mình tạm phân loại Log thành 2 loại: Business và Operation Log.

Business Log

Business Log là những loại log giúp hỗ trợ các hoạt động và quyết định của doanh nghiệp. Như các Usage Log liên quan đến sử dụng các tính năng trên giao diện để bộ phận marketing, product dễ dàng ra quyết định liên quan đến kinh doanh và phát triển sản phẩm. Đối với loại log này thì hiện tại có ông trùm và được sử dụng khá nhiều là Google Analytics. Nếu cần open source thì có thể sử dụng Matomo (tiền thân là Piwik) để cài đặt trên server của bạn, tính năng của Matomo cũng gần như Google Analtyics.

Một loại Business Log khác mà mình đề cập trong phần chia sẻ là Critical Function Log dành cho những nghiệp vụ quan trọng, giúp đảm bảo an toàn cho hệ thống và khôi phục được trong trường hợp sự cố xảy ra và có thể tạo được dữ liệu. Log này quan trọng vì trong một kiến trúc Microservices thì có thể do cấu hình, cài đặt hoặc lỗi hệ thống khiến cho 1 service có thể bị cô lập và không gọi được các service khác trong quá trình thực thi. Ví dụ như tạo đơn hàng (service Đơn hàng) sẽ gọi các service như Sản phẩm, Tồn kho, Khách hàng, Thu chi…để hỗ trợ quá trình tạo đơn hàng. Nếu trong quá trình tạo đơn hàng mà toàn bộ các service khác không thể truy cập thì service Đơn hàng sẽ có một cơ chế an toàn riêng để đảm bảo dữ liệu request lên (raw POST data) được backup tạm thời phòng trường hợp cực hạn này. Số lượng tính năng áp dụng cơ chế log này là không lớn.

Loại log cuối cùng trong nhóm Business Log mà mình muốn đề cập là Auditing Log. Loại log này khá là quan trọng và nếu bạn đang phát triển các hệ thống Enterprise không thể bỏ qua. Auditing Log giúp doanh nghiệp có thể dễ dàng phát hiện các hoạt động bất thường, quan trọng (như xóa, import, export dữ liệu…) để kịp thời có hướng xử lý. Auditing Log còn có thể thiết kế như một hệ thống Change Log để lưu lại lịch sử thay đổi dữ liệu của 1 record (như đơn hàng, khách hàng…). Nếu có tìm hiểu về Microservices thì các bạn sẽ thấy cách thức lưu change log này của Auditing Log khá giống với pattern Event Sourcing (ES) trong mô hình CQRS/ES.

Trong hầu hết trường hợp thì chúng ta ít khi tập trung vào tự xây dựng business log bởi đối với loại này phải được phân tích kỹ và chỉ định cụ thể dịch vụ nào, tính năng nào cần được log (Auditting, Critical, Usage) để tiến hành lập trình nâng cấp.

Operation Log

Nhóm log thứ hai được đánh giá là có tác động to lớn đến quá trình tối ưu, cải tiến hệ thống là Operation Log. Một số loại log thuộc nhóm này bao gồm: Operating System, General Log, API Request, SQL Query và Distributed Tracing.

Operating System Log là nhóm log cơ bản giúp theo dõi và đánh giá tình hình chung của hệ thống như ổ cứng, memory, cpu, network IO…đối với nhóm log này thường đi kèm với hệ thống monitoring và bên Teamcrop sử dụng NodeQuery.com để theo dõi vì hệ thống NodeQuery khá tốt và đơn giản, kèm với giao diện dashboard rất dễ dùng và cơ chế alert hiệu quả. NodeQuery cũng được rất nhiều công ty trên thế giới sử dụng.

Loại log tiếp theo trong nhóm Operation Log là General Log, bao gồm những Log liên quan đến hoạt động của Nginx, PHP…và những custom log message do bạn ghi xuống trong quá trình vận hành hoặc debug hệ thống. Cùng với API Request Log, SQL Query Log thì mình tự xây dựng cơ chế log riêng bởi số lượng và tần suất log rất cao, việc sử dụng các hệ thống khác hoàn toàn không hiệu quả về hiệu suất và kinh tế.

API Request Log là loại log để theo dõi toàn bộ các request vào hệ thống Microservices. Giúp bộ phận lập trình biết được performance của các request như thời gian thực thi một tính năng (execution time) cũng như memory cấp phát cho các tính năng.

SQL Query Log cũng là loại log có mục đích khá giống với API Request Log, giúp lập trình viên và DB Admin có thể theo dõi được tình hình truy vấn database, câu truy vấn nào chưa tối ưu, table nào được truy cập nhiều, tình trạng tỷ lệ master/slave trong mô hình replicate có duy trì ở mức ổn định hay không…

Cuối cùng là một loại log cực kỳ cần thiết trong quá trình vận hành một hệ thống Microservices, đó là Distributed Tracing. Hầu hết các bạn khi chuyển sang kiến trúc Microservices, sẽ hay bị trình trạng service gọi lồng vào nhau, A –> B —> C —> D thì khi có một lỗi hoặc bottleneck nào đó ở một service bên trong (vd service C) thì rất khó phát hiện và debug bởi đặc thù phân tán của kiến trúc Microservices. Để giải quyết vấn đề này thì kỹ thuật Distributed Tracing sẽ giúp ích rất nhiều. Teamcrop sử dụng Zipkin Library PHP dùng để format dữ liệu theo đặc tả OpenTracing và backend sử dụng Jaeger (dự án Open source của Uber).

Đó là toàn bộ những chia sẻ của Tuấn tại buổi meetup đầu năm 2020 ngày 09/01/2020. Bên dưới là phần Slide trình bày (có cải tiến cho dễ hiểu hơn).


Dưới đây là schema của 3 table tương tứng với 3 loại log (General Log, API Request Log và SQL Query Log) được tạo trong database ClickHouse:

CREATE TABLE log_request (
  lr_date Date,
  lr_datetime DateTime,
  lr_hour UInt8,
  lr_minute UInt8,
  lr_service String,
  lr_method String,
  lr_controller String,
  lr_action String,
  lr_companyid UInt32,
  lr_userid UInt32,
  lr_status UInt16,
  lr_exectime Float32,
  lr_memory Float32,
  lr_ip String,
  lr_depth UInt8,
  lr_source String,
  lr_traceid String,
  lr_tracespanid String
) ENGINE = MergeTree(lr_date, (lr_datetime, lr_hour, lr_minute, lr_service, lr_method, lr_controller, lr_action, lr_companyid, lr_userid, lr_status, lr_exectime, lr_memory, lr_ip, lr_depth, lr_source, lr_traceid, lr_tracespanid), 8192);;


CREATE TABLE log_sql (
  ls_date Date,
  ls_datetime DateTime,
  ls_hour UInt8,
  ls_minute UInt8,
  ls_hosttype String,
  ls_host String,
  ls_querytype String,
  ls_table String,
  ls_exectime Float32,
  ls_companyid UInt32,
  ls_userid UInt32,
  ls_traceid String,
  ls_tracespanid String
) ENGINE = MergeTree(ls_date, (ls_datetime, ls_hour, ls_minute, ls_hosttype, ls_host, ls_querytype, ls_table, ls_exectime, ls_companyid, ls_userid, ls_traceid, ls_tracespanid), 8192);


CREATE TABLE log_syslog (
  ls_date Date,
  ls_datetime DateTime,
  ls_hour UInt8,
  ls_minute UInt8,
  ls_message String,
  ls_tag String,
  ls_host String,
  ls_source String
) ENGINE = MergeTree(ls_date, (ls_datetime, ls_hour, ls_minute, ls_message, ls_tag, ls_host, ls_source), 8192);

P.S: Teamcrop.com là hệ thống phần mềm quản lý bán hàng và nhân sự, nếu bạn nào quan tâm thì có thể dùng thử và ủng hộ một startup hoàn toàn Việt Nam nhé. Nếu bạn nào hứng thú với PHP hoặc kiến trúc Microservices, thì có thể cùng tham gia xây dựng Teamcrop với Tuấn, mọi thông tin gửi vào email trong trang cuối của Slide ở trên nhé.

Categories
Miscellaneous

New Year’s Resolution of 2020

Năm 2019 đã đến những giờ phút cuối, đến hẹn lại lên thì thời điểm này lại ngồi nhìn lại một năm đã trải qua và tự đánh giá để rút tỉa kinh nghiệm cũng như sau này nếu có giảm trí nhớ thì cũng biết mình đã từng trải qua những gì.

2019 – Tiếp tục tiến tới

Về kinh doanh thì 2019 tạm gọi là “đủ ăn” chứ không dư dả gì vì đúng là năm bản lề tăng trưởng. Ít ra, sau 6 năm thành lập thì công ty vẫn tồn tại tốt và biểu đồ có chiều hướng đi lên dần đều chứ không đi xuống tịt ngòi. Công ty vẫn kiên định với 2 mảng kinh doanh chính là Software-as-a-Service (SaaS) và Outsourcing, cả 2 mảng đều tập trung vào tầm nhìn từ ban đầu của công ty là “Số hóa vận hành của doanh nghiệp”.

Trong nhánh SaaS thì Teamcrop, Basecrop thì vẫn tăng trưởng đều. Đặc biệt, hệ thống tăng trưởng tốt nhất đó là Movecrop. Chatcrop thì đã chấm dứt sớm sau khoảng 3 tháng giới thiệu vì mình cũng không đặt nặng vào mảng chatbot và messaging, bu bám các social platform. Bạn Helpcrop cũng sớm ra đi sau đó ít lâu sau khi không có traction. Với phương châm “Try very fast, Fail very fast” thì không có thiệt hại gì đáng quan tâm bởi các dự án đã fail.

Trong nhánh Outsourcing thì tập trung chính vào mảng xây dựng các hệ thống thương mại điện tử trên nền tảng web & mobile app. Bắt đầu nhận các dự án liên quan đến AI/Machine Learning.

Về gia đình thì con cái khỏe mạnh, vợ chồng hòa thuận, ai cũng được làm được cái mình thích là vui rồi. Vẫn phương châm 9am-5pm nên có nhiều thời gian ở nhà hơn. Đặc biệt là năm nay là kỷ niệm tròn 10 năm quen được bà xã. Đáng gọi là thành công vang dội rồi.

Về cộng đồng thì cuối năm cũng tham gia được sự kiện nho nhỏ để chia sẻ đến bà con công việc của mình. Năm nay hoạt động cộng đồng khá ít vì tuổi cũng lớn và tập trung xây dựng nền tảng hơn. Để dành nhiều thời gian cho công ty và bản thân hơn.

Về bạn bè thì vẫn những người bạn cũ đã quen biết, không biết thêm nhiều bạn bè mới, nhưng quả thực “Quý hồ tinh bất quý hồ đa”, có được những người bạn hiện tại cũng là một phần may mắn của Tuấn vì với tính khí khùng điên như mình mà mấy chế vẫn giữ được bình tĩnh thì các bạn thật vĩ đại.

Về cá nhân thì vẫn vui vẻ, được làm việc trong một môi trường thân thiện, hòa đồng và đọc được khá nhiều sách. Năm nay đọc nhiều sách tiếng Anh và chuyên ngành hơn, dù không đạt chỉ tiêu 100 cuốn sách (chỉ khoảng 70 cuốn) và sẽ cố gắng đọc nhiều hơn trong 2020. Cũng đi du lịch nước quài được 2 lần để đạt yêu cầu tối thiểu của việc đi chơi.

Tóm lại thì 2019 là một năm đạt một số thành tựu nho nhỏ, từ hoạt động kinh doanh đến phát triển bản thân, nên 12 tháng vừa qua khá ưng ý và không có gì hối tiếc.

Hứa hẹn vào 2020

Nối tiếp sự tăng trưởng của 2019 thì hy vọng 2020 sẽ mang lại nhiều thành tựu hơn, từ kinh tế đến trình độ phát triển bản thân. Dù biết rằng các chỉ tiêu đặt ra có thể khó đạt được, nhưng vẫn mạnh dạn đặt ra một số chỉ tiêu để đeo đuổi như:

  • Triển khai 10 dự án Outsourcing
  • Đọc 200 cuốn sách
  • Công ty tăng 50% nhân sự.
  • Viết blog mỗi tuần 1 bài.
  • Tham gia meetup chia sẻ 1 lần / tháng
  • Đi du lịch quốc tế 4 lần, và cố gắng có 1 lần đi Mỹ
  • Ra mắt 3 dự án mới trong mảng công nghệ.
  • Phấn đấu đạt một chứng chỉ quốc tế nào đó.

Và cuối cùng, chúc mọi người một năm 2020 tràn đầy sức khỏe, may mắn và thành công. Happy New Year!

Categories
DevOps

Speed up Microservices 4: Asynchronous Big Task

Nối tiếp nội dung về tối ưu cho kiến trúc Microservices, lần này mình sẽ đề cập đến một bài toán cũng gặp rất nhiều và có thể coi là giải pháp khác của bài trước là Export dữ liệu. Nếu như ở bài trước, việc export dữ liệu được diễn ra ở Frontend (JS) bao gồm tải dữ liệu có phân trang và đóng gói excel thì có những hạn chế sau:

  • Nếu dữ liệu nhiều sẽ ảnh hưởng đến frontend vì memory có giới hạn
  • Quá trình export này là đồng bộ, tức là nếu đóng tab hoặc reload trang là tải lại từ đầu
  • Tính năng cần xuất dữ liệu này chưa có giao diện frontend, kéo theo thêm việc làm (làm trang danh sách) nếu chỉ muốn export.

Do những hạn chế trên nên cách đây ít lâu vẫn còn 1 vài tính năng Export dữ liệu phải được thực hiện ở phía server và rất khó đưa xuống Frontend vì yếu tố phức tạp của lấy dữ liệu và số lượng dữ liệu lớn. Những tính năng export kiểu cũ này kéo theo hạn chế rõ ràng là script sẽ chạy lâu và luôn kích hoạt cơ chế slow log vì có những script chạy cả tiếng đồng hồ chưa xong file excel để export và Memory chiếm vài GB cho 1 process. Nếu chỉ cần vài khách hàng vào thực hiện tính năng Export thì sẽ dẫn đến hệ thống treo, và trong môi trường không kiểm soát được thì làm sao có những yêu cầu dạng “cậu chỉ được export vào lúc X giờ”…

Do những hạn chế của cả 2 hình thức công việc như trên nên Teamcrop đã hoàn thiện giải pháp khá tối ưu, hiệu quả và an toàn cho người và của, và đó chính là nội dung của bài chia sẻ này.

Big Task là gì?

Trước tiên, cần phải định nghĩa Big Task là gì để dễ dàng thảo luận. Big Task ám chỉ những task khi thực hiện sẽ tốn khá nhiều thời gian và tài nguyên (Memory, CPU..). Ví dụ như những tính năng export tồn kho hàng chục ngàn sản phẩm, SKU, import hàng ngàn sản phẩm, đơn hàng, hoặc đi spam email, sms…

Một số đặc điểm của hệ thống BigTask mà Teamcrop đã xây dựng là:

  • Có thể chia nhỏ
  • Kiểm soát được tiến độ công việc (Bao nhiêu % hoàn thành..)
  • Bất đồng bộ: người dùng có tắt trình duyệt hay tắt máy thì hệ thống vẫn cứ làm việc
  • Có khả năng retry

Big Task được vận hành thế nào?

Tất nhiên, mỗi task bây giờ được định nghĩa là một row trong Database, mỗi task sẽ có 3 giai đoạn:

  • Bước 1: Chuẩn bị
  • Bước 2: Xử lý dữ liệu
  • Bước 3: Kết thúc

Bước chuẩn bị thường được trigger bởi người dùng và từ giao diện frontend, như submit form chứa thông tin. Ở bước chuẩn bị này chính là giai đoạn quan trọng nhất, bao gồm khởi tạo tổng số record cần xử lý (để kiểm soát progress), ghi nhận các cấu hình cần thiết cho task như số lượng record cần xử lý 1 trang, các dữ liệu cài đặt khi người dùng submit form và một bước quan trọng là khởi tạo 1 file excel chỉ có header (không có dữ liệu) ở môi trường local.

Bước xử lý dữ liệu là công việc chính liên quan đến nhiệm vụ, như lấy dữ liệu để insert vào file excel theo từng batch, ví dụ nếu task được giao mỗi trang lấy 100 record thì chỉ lấy 100 record và đẩy nhiệm vụ trang tiếp theo vào Messsage Queue (ví dụ RabbitMQ), hệ thống Queue worker sẽ chịu trách nhiệm thực thi trang tiếp theo dựa vào nội dung trong message đã được đẩy vào queue.

Bước kết thúc chính là đảm bảo dữ liệu đã đầy đủ và đưa các file cần thiết vào hệ thống, đối với Teamcrop là gọi File Service để lưu file tạm ở trên, thông báo và kết thúc task để đánh dấu task hoàn tất.

Như vậy, với sự giúp đỡ của kiến trúc Message Queue thì những task lớn có thể chia nhỏ và tiến trình được kiểm soát, đặc biệt là giúp cho hệ thống không có những script chạy quá lâu và tốn quá nhiều tài nguyên. Hiện tại bên Tuấn đã bắt đầu migrate dần các task dạng này vào mô hình Big Task của mình để tăng performance của hệ thống.

Hy vọng bài viết này sẽ giúp các bạn đối phó với một trong những bài toán đau đầu khi scale.

 

Categories
DevOps

Speed up Microservices 3: Export dữ liệu ra Excel

Chào mọi người, nối tiếp bài trước là tận dụng caching ở trình duyệt để tăng tốc cho microservices. Ở bài này mình sẽ chia sẻ một case study khá thông dụng trong các dự án “vừa vừa”, đó là nhu cầu export dữ liệu ra file excel. Nếu như các bạn thường xuyên làm việc liên quan đến các hệ thống quản lý dữ liệu thì data table / grid sẽ xuất hiện khá nhiều, kéo theo tính năng thường xuyên được yêu cầu là export dữ liệu (ra file Excel).

Categories
Web Programming

MySQL ngoại truyện

Cuối tuần vừa rồi mới vừa clear gần 50% table trong database của Teamcrop, đây là những table của những tính năng không còn sử dụng và đã trải qua thời gian deprecated (chờ xử trảm), thấy có lẽ nên viết một bài về database nhân dịp đầu năm mới cũng như khai blog 2019.

Cũng giống như nhiều đàn anh, đàn chị thời nay, mình đã sớm tiếp xúc với PHP từ 2003 khi xu hướng diễn đàn lớp, diễn đàn trường, diễn đàn vớ vẫn nở rộ. Những đoạn code đầu tiên là những mod diễn đàn viết bằng PHP, cũng như những câu truy vấn database MySQL đầu tiên cũng xuất hiện từ thời điểm này. Bài viết mang tính chất cổ súy MySQL nói riêng (RDBMS nói chung) nên nếu ai không biết nó là gì thì nên tìm hiểu hoặc làm với nó ít ít rồi hẳn đọc tiếp và đối tượng bài viết có thể là DB Administrator hoặc Developer có nhiệm vụ làm việc với MySQL, hầu hết chúng ta – web developer cũng là những người maintain database schema.

Làm việc với MySQL hơn 15 năm (và hiện nay vẫn chỉ tin và dùng MySQL), nên ít nhiều có chút kinh nghiệm khi sử dụng cũng như hình thành những quy trình, đường lối cho cá nhân và team khi tham gia xây dựng dự án. Mỗi khi có Web developer mới tham gia vào công ty thì những kiến thức này lại được truyền đạt, tuy nhiên đó giờ vẫn chưa có một tài liệu cụ thể nên bài blog này cũng là một phần phục vụ việc training này.

Tại sao lại gọi là ngoại truyện?

Hầu hết những gì mình chia sẻ ở đây có thể các bạn sẽ rất ít thấy đề cập ở các sách hay giáo trình về MySQL. Thậm chí có những thứ có thể được coi là đi ngược với những gì bạn biết về MySQL.

Để dễ chia sẻ thông tin, mình sẽ tách thành 3 giai đoạn khi các bạn làm việc với MySQL, đó là trước khi có dữ liệu (data), trong khi có dữ liệu và khi không còn dữ liệu. Ở mỗi giai đoạn sẽ có những kinh nghiệm khác nhau và phù hợp với ngữ cảnh để mọi người tiện theo dõi.

1. Trước khi có dữ liệu

Theo quan sát và kinh nghiệm, rất nhiều bạn khá hời hợt và xem thường giai đoạn này, tức giai đoạn phân tích và thiết kế database, hay nói 1 cách dân dã là tạo bảng (CREATE TABLE..). Rất nhiều vấn đề phát sinh bởi việc thiết kế bảng hời hợt, thậm chí là thiết kế sai, kéo theo technical debt sẽ ngày càng lớn và thậm chí là phải bỏ cả tính năng / bảng đang sử dụng để refactoring lại thành tính năng mới, tạo table mới và migrate dữ liệu từ bảng cũ sang bảng mới.

Ngoài việc thiết kế bảng đúng, duy trì tính dễ hiểu (understandable), dễ bảo trì (maintainable) và đồng nhất (consistent) cũng là một số yếu tố luôn được cân nhắc khi thiết kế một table. Bên dưới là một số “guideline” mà ai muốn tham gia vào team của Tuấn sẽ được training và bắt buộc phải theo:

Về database:

  • Trong một Database, tất cả tên bảng phải có tiền tố giống nhau (prefix). Ví dụ: crp_, abc_…
  • Để tăng khả năng chuyển đổi DBMS và tương thích với các hệ SQL, không sử dụng các khái niệm “phức tạp” của database như Store procedure, View, Constraint
  • Không sử dụng khái niệm ràng buộc khóa chính, khóa ngoại cài đặt trong DBMS. Chỉ sử dụng khái niệm này trong quá trình trao đổi thông tin giữa các developer và thiết kế bảng.
  • Áp dụng kiến trúc Microservices để chia nhỏ database theo từng domain/context riêng để giúp giảm tải chung cho toàn Database. Ví dụ: Mỗi service sẽ cần 1 kiến trúc / server DB riêng để vận hành riêng biệt.
  • Những phiên bản MySQL khác nhau sẽ có một số config khác nhau kéo theo những lỗi không ngờ tới khi nâng cấp phiên bản.
  • Không sử dụng docker / VM cho MySQL Server.

Về bảng (table):

  • Khi đặt tên bảng, tên cột thì không sử dụng chữ HOA hoặc ký tự đặc biệt. Cho phép a-z, 0-9 và underscore (gạch dưới “_”).
  • Tên bảng luôn là tiếng anh và sử dụng từ số ít. Ví dụ: crp_product, crp_news
  • Nếu tên bảng là tổ hợp nhiều từ, thì mỗi từ cần cách nhau gạch dưới (underscore). Ví dụ: abc_product_category, abc_order_detail
  • Trừ các cột khóa ngoại, các cột dữ liệu riêng của một bảng luôn có tiền tố giống nhau, và tổng hợp từ chữ cái đầu tiên của tên bảng (không bao gồm tiền tố database). Ví dụ: bảng abc_product_category thì các cột của bảng này phải có tiền tố là “pc_”, như “pc_id”, “pc_name”..
  • Tên cột ngoài tiền tố bảng thì là các từ tiếng anh, số ít và không có khoảng cách, các từ phải viết liền nhau. Ví dụ: p_countview, p_datecreated..
  • Khóa chính của một cột trong bảng luôn là tiền tố của bảng + “id”. Ví dụ: “pc_id”, “p_id”, “n_id”..
  • Khóa ngoại của một bảng sẽ được nằm đầu tiên trong danh sách cột của bảng này, trước cả cột khóa chính. Tên cột khóa ngoại phải giữ nguyên tên cột mà nó làm khóa chính trong bảng của nó. Ví dụ: u_id là User ID và là khóa chính trong bảng “abc_user”, thì khi làm khóa ngoại trong bảng “abc_product” thì nó vẫn là cột “u_id”.
  • Collation của database / table / text column là “utf8_general_ci”
  • Table luôn có engine mặc định là MyISAM (tối ưu cho SELECT dữ liệu)
  • Có thể tận dụng engine MEMORY để tối ưu truy vấn vì toàn bộ dữ liệu của table loại MEMORY sẽ nằm trong RAM thay vì ổ cứng.

Về kiểu dữ liệu của cột trong bảng:

  • Kiểu dữ liệu của khóa ngoại và khóa chính phải trùng khớp nhau (data type & data length)
  • Không sử dụng kiểu dữ liệu DATETIME trừ trường hợp lưu ngày sinh.
  • Không sử dụng kiểu dữ liệu ENUM trong trường hợp cần lưu theo logic này, chỉ cần lưu INT (11) hoặc SMALLINT(3) và trong Model của code sẽ khai báo constant.
  • Tất cả cột thời gian đều lưu Timestamp và kiểu dữ liệu INT(10).
  • Các cột dữ liệu thời gian luôn là những cột nằm cuối cùng của bảng. Hầu hết các bảng luôn có cột: datecreated (ngày tạo) và datemodified (ngày cập nhật).
  • Trường IP Address luôn là BIGINT (20), và sử dụng hàm ip2long() và long2ip() của PHP để encode/decode.
  • Giá trị tiền nên là DECIMAL (18), tốt nhất là DECIMAL (18,4)
  • Cẩn thận khi thiết kế dữ liệu cho việc lưu ký tự emoji.

Việc tuân thủ các guideline này sẽ giúp rất nhiều trong việc debug cũng như đoán được nguồn gốc, xuất xứ của 1 cột khi làm việc, và tạo sự nhất quán trong toàn team để dễ trao đổi, debug. Ví dụ bên dưới là thiết kế cho table user, product.

CREATE TABLE `crp_user` (
  `u_id` int(11) NOT NULL,
  `u_email` varchar(128) NOT NULL,
  `u_password` text NOT NULL,
  `u_ipaddress` bigint(20) NOT NULL,
  `u_status` smallint(3) NOT NULL,
  `u_datecreated` int(10) NOT NULL,
  `u_datemodified` int(10) NOT NULL,
  `u_datelastloggedin` int(10) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;


CREATE TABLE `crp_product` (
  `u_id` int(11) NOT NULL,
  `p_id` int(11) NOT NULL,
  `p_name` varchar(255) NOT NULL,
  `p_description` text NOT NULL,
  `p_price` decimal(18,4) NOT NULL,
  `p_status` smallint(3) NOT NULL,
  `p_ishot` tinyint(1) NOT NULL,
  `p_datecreated` int(10) NOT NULL,
  `p_datemodified` int(10) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Với những tiêu chí trên thì đảm bảo team bạn sẽ dễ dàng làm việc trên các bảng dữ liệu của các dự án.

2. Trong khi có dữ liệu

Sau quá trình thiết kế bảng hoàn tất và đã được đưa lên hệ thống, tính năng cũng đã được chạy và bạn bắt đầu có dữ liệu, không gì tuyệt hơn là có dữ liệu. Đến giai đoạn này, việc duy trì cho hệ thống đang chạy là ưu tiên hàng đầu, và một số chia sẻ ở giai đoạn này cũng nhằm giúp việc đảm bảo hệ thống DB không bị gián đoạn.

  • Không thay đổi tên cột trong bất kì tình huống nào.
  • Không xóa cột trong bất kì tình huống nào.
  • Chỉ đổi kiểu dữ liệu cột sang cùng loại và sang dung lượng lớn hơn. Ví dụ cho phép đổi từ VARCHAR(50) -> VARCHAR (100), SMALLINT(3) -> INT (11).
  • Cần áp dụng replicate database (Master / Slave) dữ liệu để giảm tải. Để tránh rắc rối không cần thiết, chỉ nên sử dụng 1 Master và có thể cho phép nhiều Slave.
  • Trong bất kì tình huống nào liên quan đến vấn đề đồng bộ giữa Master & Slave và liên quan đến lỗi đồng bộ binlog, tốt nhất là disable replicate, chỉ sử dụng Master, tìm ra nguyên nhân cụ thể để khắc phục và phần lớn vấn đề liên quan đến networking, ổ cứng mạng, tắt bất tử.
  • Lưu ý “Delay Gap” (thời gian bất đồng bộ dữ liệu) giữa Master và Slave(s).
  • Đồng bộ dữ liệu vào thời gian ít truy cập nhất
  • Backup dữ liệu định kì và upload lên một hệ thống / server khác hệ thống đang chạy. Bên mình kết hợp S3cmd để đẩy file backup sql lên Amazon S3 để backup mỗi ngày.
  • Tuyệt đối lưu ý đến max connection mặc định của MySQL là 150 để tránh lỗi MySQL connection.
  • Nếu cài đặt max connection lớn thì lưu ý việc MySQL server sẽ block IP do cơ chế security.
  • Hạn chế đến mức tối đa việc sử dụng JOIN TABLE để tăng khả năng refactoring, migration cũng như giảm thiểu vấn đề về performance / SQL execution. Chỉ JOIN khi đây là hoạt động bất khả kháng và không còn phương án nào tối ưu hơn cho việc truy vấn (tìm kiếm).
  • Không sử dụng JOIN cho các entity không liên quan đến nhau hoặc cùng 1 domain/service. VD: không join user & comment, product & comment..Có thể JOIN order & order detail.
  • Luôn có Cache layer ở tầng Application (Redis, memcached) để hạn chế truy vấn vào Database cũng như hỗ trợ việc hạn chế JOIN.

3. Khi dữ liệu không cần thiết

Hầu hết dự án nào cũng có những tính năng “không còn sử dụng” và có nhu cầu xóa bỏ luôn dữ liệu thì bạn cũng cần có những quy định cho việc này. Vì sao phải xóa dữ liệu? Theo thời gian, giữ liệu sẽ ngày một phình to, nếu vẫn cố giữ những dữ liệu không còn sử dụng thì sẽ kéo theo thời gian backup / migration / recovery lớn hơn, dẫn đến nhiều rủi ro tiềm ẩn không cần thiết, do đó, tốt nhất là xóa những gì không dùng. Hoặc nếu muốn giữ lại thì cũng nên tách data này sang 1 nơi mà không ảnh hưởng đến performance / rủi ro chung của toàn hệ thống.

Bên dưới là một số bước mà bên mình dùng để xóa dữ liệu, các bạn có thể tham khảo và áp dụng.

  • Bởi vì không có cài đặt ràng buộc tự động (Constraint) nên tầng Application cần có các tính năng (cronjob) tự động để xóa các dòng dữ liệu không cần thiết hoặc update các cột dữ liệu bị lỗi.
  • Đảm bảo các bảng cần xóa không được tham chiếu bởi bất kì tính năng nào. Nếu có tham chiếu thì cần đảm bảo tính năng này hiện đã không còn sử dụng.
  • Kiểm tra ngày cuối cùng mà bảng này có dữ liệu mới, hay modified date của bảng.
  • Không có bảng ngay mà chỉ đổi tên bảng và thêm tiền tố. Ví dụ: thêm OLD_, DEPRECATED_
  • Chờ tối thiểu 1 tháng -> 3 tháng và chỉ xóa các bảng có tiền tố định trước là sẽ xóa.
  • Hạn chế tối đa việc gõ tên bảng, nên copy tên bảng ra trước rồi copy vào CMD.
  • Khi xóa bảng thì không nên dùng MySQL Client / GUI để thao tác mà thông qua MySQL CLI và thực thi SQL mà thôi.
  • Theo dõi hệ thống support / CS tối thiểu 1 ngày để phát sinh những support ticket liên quan đến mất dữ liệu, lỗi tính năng do khách hàng report.

Trên đây là tất cả những quy trình, kinh nghiệm mà team mình áp dụng khi làm việc với MySQL. Hy vọng mọi người cũng có những quy trình để giúp bảo vệ dữ liệu tốt hơn và cải thiện quá trình lưu trữ và làm việc nhóm liên quan đến cấu trúc dữ liệu.

Categories
Miscellaneous

New Year’s Resolution of 2019

Cũng như các năm trước, 31/12 là dịp ngồi review lại những gì đã diễn ra trong năm và 2018 là một năm được đánh giá là “có thu hoạch” về một số mặt quan trọng trong sự nghiệp và đời sống. 

Categories
DevOps

Speed up Microservices 2: Tận dụng trình duyệt và cache

Cũng gần 9 tháng kể từ bài 1 ra mắt, trong bài này mình sẽ chia sẻ cách hệ thống Teamcrop đã tối ưu thế nào để tăng tốc cho hệ thống Microservices của mình. Cũng như bài 1 có đề cập, dữ liệu trong hệ thống microservices khá phân tán và khi cần lấy dữ liệu nếu không thiết kế tốt thì sẽ tốn rất nhiều thời gian cho các request lấy dữ liệu. Ví dụ lấy danh sách đơn hàng là một ví dụ rõ ràng nhất có nêu ở bài trước.

Teamcrop cũng lưu dữ liệu dạng này, trong một đơn hàng được lưu trong database thì chỉ lưu ID (Khóa ngoại) của các bảng như nhân viên, cửa hàng, nguồn đơn hàng…mà các thông tin này chỉ được cung cấp bởi các service liên quan như service Nhân viên, Store và Metadata. Để hiển thị thông tin như giao diện thì cần phải gọi thêm nhiều request (Restful) để fetch data từ các nguồn này và đây là cách hoàn toàn không hiệu quả bởi ảnh hưởng đến thời gian chờ của người dùng.

Trong kiến trúc của Teamcrop, các thông tin như nhân viên, cửa hàng, nhà kho, sản phẩm, … này được gọi là Tài nguyên công ty (Company Resource – CR) và hiện Teamcrop có khoảng gần 20 company resource.

Cách hoạt động của các Company Resource:

Các company resource cũng là dữ liệu và tất nhiên vẫn có các API như các resource khác, hầu hết đều được quản lý (CRUD) và có giao diện tương ứng để quản lý. Chỉ có một khác biệt là các company resource sẽ có thêm 1 web service cho phép lấy toàn bộ dữ liệu, gọi là api /fulldata. API này cho phép lấy toàn bộ dữ liệu resource, không phân trang.

Khi có một user truy cập vào website thì sẽ load toàn bộ các company resource và lưu trữ trong trình duyệt. Mình có thể setup thêm giao diện để thể hiện progress bar, khi nào toàn bộ company resource được load hết thì cơ chế router của web sẽ bắt đầu và tiến hành load giao diện tính năng đang truy cập. Hình dưới là ví dụ một action viết bằng PHP của việc lấy một company resource là Vendor (thương hiệu):

Company Resource sẽ ảnh hưởng thời gian tải trang

Nếu đọc đến đây thì sẽ có nhiều bạn thắc mắc là nếu mỗi truy cập đều phải load toàn bộ Company Resource thì sẽ chờ khá lâu bởi vì mỗi CR sẽ cần 1 request đến /fulldata và API này cũng phải lấy toàn bộ data của resource và response về.

Đối với phía server thì sẽ không có vấn đề nhiều vì mình sẽ tận dụng cache (Redis) để lưu kết quả vào memory và khi có request thì mình sẽ lấy từ cache ra mà thôi.

Ở phía client (trình duyệt) thì mới là vấn đề lớn, bởi dù server có nhanh thì có bao nhiêu company resource thì cũng sẽ tốn ngần ấy số request lên server để lấy /fulldata. Tuy nhiên, Teamcrop hầu như không tốn 1 request nào cho các company resource khi sử dụng…Service Worker của trình duyệt.

Đối với các API /fulldata thì script trong service worker của mình sẽ lấy từ cache trên trình duyệt ra mà không phải tốn 1 request nào lên server. Như vậy là tiết kiệm được mấy chục request và có được một số lượng data để hỗ trợ lấy dữ liệu.

Company Resource sẽ được lưu trữ thế nào?

Sau khi lấy được các dữ liệu company resource thì việc lưu trữ và sử dụng các dữ liệu này cũng là một vấn đề lớn. Bởi các company resource này sẽ được dùng cho việc tìm kiếm theo 1 ID (getById), tìm theo một số tiêu chí (search) và lấy toàn bộ danh sách (getList).

Để đảm bảo quá trình truy xuất, tìm kiếm thì nó phải nhanh cũng như gần gũi, dễ sử dụng nên mình đã chọn TaffyDB, được coi là một thư viện nhỏ gọn, In-memory Database, hỗ trợ tìm kiếm theo ID, điều kiện..và khá dễ dùng. Mỗi Company Resource sau khi lấy về sẽ trở thành 1 database và có thể truy xuất data thoải mái. Khá nhanh bởi vì nó là in-memory.

Như vậy thì từ giờ, mỗi khi có 1 dữ liệu có ID là ID của một company resource thì có thể tìm kiếm và lấy thông tin một cách nhanh nhất từ bộ nhớ của trình duyệt mà không phải tốn công JOIN bảng, request giữa các service hoặc client gửi request để lấy detail.

Tuy nhiên, một vấn đề lớn hơn đã xuất hiện đó là nếu dữ liệu company resource đã cache hoàn toàn ở trình duyệt thì khi có dữ liệu mới thì làm sao cập nhật (hay xóa cache). Đối với vấn đề này phát sinh 2 tình huống từ dễ đến khó, tình huống đầu tiên là xóa cache đối với người refresh lại trang web (reload) và tình huống thứ 2, đau đầu hơn là bởi vì Teamcrop là dạng Single Page App (SPA), nếu người dùng không reload trang thì làm sao cập nhật dữ liệu mới nhất. Mình sẽ xử lý lần lượt từng tình huống.

Xóa cache của Company Resource khi reload trang

Đối với trường hợp người dùng reload lại trang web thì chỉ cần thêm cơ chế versioning vào các company resource là giải quyết được.

Những thao tác thay đổi dữ liệu liên quan đến Company Resource (thêm, xóa, sửa) thì đều được gọi 1 API để nâng version của resource tương ứng.

Trước khi request các /fulldata API, hệ thống sẽ gửi request lấy thông tin version của các company resource, từ đó mới request để lấy full data. Do version được nối vào URL của fulldata nên Service Worker sẽ kích hoạt cơ chế cache theo URL, nếu version không đổi thì sẽ không request lên server, ngược lại thì sẽ request lên server.

Thậm chí còn làm tính năng nho nhỏ trên giao diện để debug version của các resource trong trường hợp không thể inspect được.

Xóa cache của Company Resource khi đang sử dụng và không reload

Đối với trường hợp một user vẫn “miệt mài” làm việc và không reload trang, bởi đặc thù của Single Page App là không reload mỗi khi chuyển tính năng nên xóa cache của company resource cho đối tượng này sẽ không theo cách thông thường. Bài toán đặt ra là làm sao trigger (thông báo) cho trình duyệt biết là có sự thay đổi là được bởi vì nếu được trigger thì chỉ cần gọi ajax lên Company Resource API sẽ lấy được bảng version của các resource và đối chiếu cái nào tăng thì lấy bản mới của /fulldata.

Suy nghĩ một hồi và nghĩ ngay đến giải pháp sử dụng Socket. Và Teamcrop sử dụng Pusher để cung cấp giải pháp socket bởi vì đây là một trong những dịch vụ tốt nhất hiện nay đối với dịch vụ socket.

Nhằm tận dụng cơ chế web socket sẵn có của Teamcrop (dùng cho cơ chế web notification) nên trình duyệt tiến hành “subscribe” để nghe trên một channel và mỗi khi version tăng thì server (PHP) của Teamcrop gửi một message cho trình duyệt đang lắng nghe ở một channel chung của công ty, tất nhiên thông qua Pusher API.

Sample code ở client (Javascript):

Sample code ở server (PHP):

Như vậy, mỗi khi company resource service nhận được yêu cầu nâng version thì sẽ trigger và client sẽ tự động cập nhật dữ liệu đang cache trên trình duyệt. Và giải quyết ổn thỏa bài toán cache data cho Company Resource.

Tiêu chí nào để trở thành Company Resource?

Như từ đầu đã chia sẻ, Company Resource sẽ lưu ở máy giúp  việc “phân giải” các ID khóa ngoại thành dữ liệu để hiển thị nhằm cải tiến performance chung của toàn hệ thống. Tuy nhiên, không phải tất cả tài nguyên đều có thể trở thành Company Resource.

Trước tiên, cần xác định rõ là Company Resource không phải là Transaction Data, ví dụ Đơn hàng, Khách hàng…không thể nào là ứng cử viên trở thành Company Resource bởi tính thay đổi cũng như số lượng của nó. Chỉ nên chọn những dữ liệu thường xuyên được tham chiếu, số lượng dữ liệu ít, tránh làm trình duyệt lưu quá nhiều dữ liệu vào bộ nhớ.

Lời kết, như vậy cùng với việc thay đổi mô hình microservice thì cũng phát sinh nhiều vấn đề mới liên quan đến kiến trúc này. Trên đây chỉ là một giải pháp cho một bài toán cụ thể mà Teamcrop gặp phải trong quá trình vận hành hệ thống của mình. Kỳ tiếp theo (kỳ 3) mình sẽ đề cập đến một bài toán cụ thể hơn là Export dữ liệu ra file (vd Excel). Bởi vì đặc thù là dữ liệu phân tán, nên export dữ liệu trong hệ thống cũng là một bài toán khá thú vị.

Tuấn có nhận tư vấn giải pháp liên quan đến triển khai, chuyển đổi kiến trúc sang Microservices. Ai cần thì đừng ngần ngại liên hệ nhé.