<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.4">Jekyll</generator><link href="https://thanhdancer.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://thanhdancer.com/" rel="alternate" type="text/html" /><updated>2025-11-01T17:16:06+00:00</updated><id>https://thanhdancer.com/feed.xml</id><title type="html">Dancing on the keyboard</title><subtitle>Nhiều khi chỉ muốn tìm nơi trút ra, mà không muốn phiền ai cả.</subtitle><entry><title type="html">Làn sóng AI trong giáo dục</title><link href="https://thanhdancer.com/review/2025/11/01/lan-song-ai-trong-giao-duc.html" rel="alternate" type="text/html" title="Làn sóng AI trong giáo dục" /><published>2025-11-01T00:00:00+00:00</published><updated>2025-11-01T00:00:00+00:00</updated><id>https://thanhdancer.com/review/2025/11/01/lan-song-ai-trong-giao-duc</id><content type="html" xml:base="https://thanhdancer.com/review/2025/11/01/lan-song-ai-trong-giao-duc.html"><![CDATA[<p><img src="/images/2025/11/01/T-a-m-AI-1-11.jpg" alt="Poster" />
Mình muốn chia sẻ một vài cảm nhận cá nhân sau khi tham dự buổi toạ đàm về cách các nhà giáo dục đang đối mặt với làn sóng AI. Sự góp mặt của dàn diễn giả - những người mình xin được gọi là thầy cô - khiến mình cảm thấy nhỏ bé, nhưng đồng thời cũng đầy cảm hứng. Dù chưa có dịp tìm hiểu kỹ về từng người, chỉ qua những ấn tượng ban đầu, mình có cảm giác như đang đứng trước bốn cánh cổng tri thức, mỗi cánh mở ra một hướng tiếp cận khác nhau trước thách thức mà AI mang đến.</p>

<h3 id="thầy-hồ-tú-bảo---tri-thức-ẩn-và-tri-thức-hiện">Thầy Hồ Tú Bảo - Tri thức ẩn và tri thức hiện</h3>
<p>Với nhiều năm nghiên cứu về trí tuệ và nhận thức, thầy Hồ Tú Bảo đã giúp mình và khán giả “điểm danh chỉ mặt” những vùng tri thức mà con người vẫn còn mù mờ, bằng một cách rất dễ hiểu. Trong kho tàng chia sẻ đồ sộ của thầy, mình đặc biệt ấn tượng với khái niệm tri thức ẩn và tri thức hiện.
Theo cách mình hiểu, tri thức hiện là những kiến thức có thể dữ liệu hoá, đo đạc và số hoá - thứ mà con người có thể truyền đạt cho máy. Còn tri thức ẩn lại thuộc về cảm xúc, trực giác, mùi vị, tâm trạng - những điều không thể mã hoá, và chính là phần “soul” khiến con người khác biệt với máy móc. Một quyết định “đúng đắn” - không chỉ “chính xác” - là kết quả của sự kết hợp hài hoà giữa hai loại tri thức ấy.</p>

<h3 id="thầy-nguyễn-phụ-hoàng-lân---tư-duy-đặt-câu-hỏi-và-khám-phá-tri-thức">Thầy Nguyễn Phụ Hoàng Lân - Tư duy đặt câu hỏi và khám phá tri thức</h3>
<p>Phong thái tự tin và nền tảng toán học vững chắc của thầy khiến mình tin rằng thầy là một “cây đa cây đề” trong giới học thuật. Thầy nói nhiều về cách đặt câu hỏi và tự học - những điều tưởng đơn giản nhưng lại là cốt lõi để mở ra tri thức.
Mình đặc biệt tâm đắc với quan điểm: để hiểu một vấn đề mới, ta phải “thử - nháp - dự đoán” để nhận ra quy luật. Tri thức không đến từ việc học thuộc, mà từ quá trình tự mình mày mò, sai và sửa. Những định lý mà mình nhớ nhất là những bài toán mà mình phải tự vật lộn để chứng minh.</p>

<h3 id="cô-lê-mai-hương---khi-ai-bước-vào-cánh-cổng-trường-học">Cô Lê Mai Hương - Khi AI bước vào cánh cổng trường học</h3>
<p>Với vai trò là một nhà quản lý giáo dục, cô Hương chia sẻ góc nhìn rất thực tế về việc AI đang len lỏi vào từng ngóc ngách của hệ thống giáo dục - từ giảng dạy, đánh giá cho đến vận hành. Cô giúp mình nhận ra rõ hơn cả cơ hội lẫn thách thức mà AI mang lại, cũng như cách các nhà trường đang thử nghiệm để ứng dụng công nghệ mà không đánh mất tinh thần giáo dục.</p>

<h3 id="cô-tống-liên-anh---giữ-bản-thể-co-người-giữa-cơn-bão-ai">Cô Tống Liên Anh - Giữ bản thể co người giữa cơn bão AI</h3>
<p>Cô Liên Anh đặt ra một câu hỏi khiến mình trăn trở: “Nếu phụ thuộc vào AI, liệu chúng ta có còn là chính mình?”.
Cô chia sẻ trải nghiệm tại Phần Lan - nơi con người được khuyến khích kết nối lại với thiên nhiên - như một lời nhắc nhở rằng, giữa guồng quay công nghệ, ta đừng quên gốc rễ bản thể con người. Từ đó, mình tự hỏi: có phải chúng ta đang quá tập trung và bị cuốn vào cơn bão này mà quên mất chính mình?</p>

<p>Xuyên suốt buổi toạ đàm, điều mình cảm nhận sâu sắc nhất là: dù có trong tay những công cụ mạnh mẽ như AI, con người vẫn cần rèn luyện trí óc và nuôi dưỡng tâm hồn. Chỉ khi đó, ta mới có thể sử dụng công cụ một cách hiệu quả, thay vì bị nó dẫn dắt, phụ thuộc hay tệ hơn là thoái hoá trí tuệ, méo mó nhân cách.</p>

<hr />
<p>P/S 1: Thiết kế toà nhà Viện nghiên cứu cao cấp về Toán đẹp quá &lt;3.<br />
P/S 2: Logo của VIASM giống với cục <a href="https://foundation.fandom.com/wiki/Prime_Radiant">Prime Radiant</a> trong Foundation của Isaac Asimov nhỉ?</p>]]></content><author><name></name></author><category term="review" /><category term="review" /><category term="thinking" /><category term="learning" /><summary type="html"><![CDATA[Mình muốn chia sẻ một vài cảm nhận cá nhân sau khi tham dự buổi toạ đàm về cách các nhà giáo dục đang đối mặt với làn sóng AI. Sự góp mặt của dàn diễn giả - những người mình xin được gọi là thầy cô - khiến mình cảm thấy nhỏ bé, nhưng đồng thời cũng đầy cảm hứng. Dù chưa có dịp tìm hiểu kỹ về từng người, chỉ qua những ấn tượng ban đầu, mình có cảm giác như đang đứng trước bốn cánh cổng tri thức, mỗi cánh mở ra một hướng tiếp cận khác nhau trước thách thức mà AI mang đến.]]></summary></entry><entry><title type="html">Ghen tuông - Chiếc bóng của yêu thương</title><link href="https://thanhdancer.com/opinion/2025/10/12/ghen-tuong.html" rel="alternate" type="text/html" title="Ghen tuông - Chiếc bóng của yêu thương" /><published>2025-10-12T00:00:00+00:00</published><updated>2025-10-12T00:00:00+00:00</updated><id>https://thanhdancer.com/opinion/2025/10/12/ghen-tuong</id><content type="html" xml:base="https://thanhdancer.com/opinion/2025/10/12/ghen-tuong.html"><![CDATA[<p><img src="/images/2025/10/12/danh-ghen.jpeg" alt="Đánh ghen - Tranh dân gian Đông Hồ" /></p>

<p>Ghen tuông là một cảm xúc thật kỳ lạ. <br />
Nó khiến ta vừa đau, vừa xấu hổ, nhưng cũng khiến ta nhận ra mình vẫn còn biết yêu, biết sợ mất đi điều quý giá. Ẩn sau ghen tuông là mong muốn rất con người: được yêu, được quan tâm, được là ai đó đặc biệt trong lòng người khác.</p>

<h2 id="khi-tình-yêu-trở-thành-sự-nắm-giữ">Khi tình yêu trở thành sự nắm giữ</h2>
<p>Trong tình yêu, thường thấy nhất ở tình yêu đôi lứa, con người thường mang theo bản năng chiếm hữu. <br />
Ta muốn người mình yêu chỉ thuộc về bản thân mình - như thể yêu là được toàn quyền giữ lấy. Ta nghĩ rằng: “Nếu người ấy yêu tôi, họ không thể yêu ai khác.”<br />
Nhưng <strong>tình yêu</strong> và <strong>sự sở hữu thật</strong> ra là hai thứ khác nhau. Sở hữu là muốn <strong>giữ lại</strong>, còn tình yêu thật sự là <strong>muốn trao đi</strong>.</p>

<p>Khi tình yêu bị nhốt trong chiếc lồng của sự sở hữu, nó không còn là dòng chảy tự nhiên nữa. Nó trở nên tù túng, khép kín, và dần héo úa. Ta không còn yêu người kia như cái cách họ tồn tại, mà chỉ yêu cảm giác họ mang lại cho ta. Và khi cảm giác ấy bị lung lay, khi ta bất an rằng cảm giác họ mang lại cho ta không đáp ứng đủ cho ta, nỗi sợ từ đó khởi sinh. Nỗi sợ ấy chính là bản chất của ghen tuông.</p>

<h2 id="nỗi-sợ-giấu-trong-trái-tim">Nỗi sợ giấu trong trái tim</h2>
<p>Thực ra, ghen tuông không xuất phát từ sự xấu xa, mà từ nỗi sợ.<br />
Sợ mất đi tình cảm, sợ không còn được quan tâm, sự không còn là “duy nhất”. Cái sự sợ hãi ấy bắt nguồn từ cảm giác <strong>chưa đủ đầy bên trong</strong> - khi ta cần tình yêu của người khác để chứng minh giá trị của mình. Hay rộng hơn, ta cần một sự nuôi dưỡng cảm xúc từ ngoại cảnh.</p>

<p>Vì thế, khai ai đó ghen, điều họ thực sự cần không phải là thêm lời hứa, mà là <strong>sự an toàn nội tâm</strong> - cảm giác rằng, ngay cả khi bị quên lãng, họ vẫn đủ để được yêu thương, vẫn có thể tự yêu chính mình.</p>

<h2 id="bản-chất-tình-yêu-là-ánh-sáng">Bản chất tình yêu là ánh sáng</h2>
<p>Tình yêu đẹp nhất là khi nó được tự do lan toả.<br />
Giống như ánh sáng mặt trời, nó toả ra vì bản thân nó là ánh sáng, chứ không cần sự tán dương khen thưởng chấp nhận đáp trả từ bất kỳ ai.</p>

<p>Khi ta yêu mà không mưu cầu, không muốn giữ, không muốn chiếm, tình yêu trở nên trong trẻo lạ thường.<br />
Ta không mất hạnh phúc khi người mình yêu cũng biết yêu thương người khác, vì ta hiểu rằng: <strong>yêu thương không phải chiếc bánh chia phần, mà là ngọn lửa, càng truyền đi càng trở nên rực rỡ</strong>.</p>

<h2 id="tự-đủ-để-không-cần-sở-hữu">Tự đủ để không cần sở hữu</h2>
<p>Muốn bước ra khỏi ghen tuông, ta không cần phải gồng lên ngăn cản tâm trí bằng chuỗi lệnh cấm “đừng ghen, ghen là xấu xí”, mà cần học cách nuôi dưỡng sự đủ đầy trong trái tim mình.</p>

<p>Khi ta cảm thấy đủ, ta không còn sợ mất.<br />
Khi ta hiểu yêu thương là dòng chảy tự nhiên, ta sẽ không cố chặn nó lại.<br />
Khi ta biết cách yêu chính mình, ta sẽ nhìn người khác bằng ánh mắt bao dung hơn.</p>

<p>Và rồi, như một điều trong sách vở hay thước phim, ta bắt đầu có thể <strong>thương được cả người từng làm mình tổn thương</strong>. Vì khi đó, ta nghiệm ra rằng, ai cũng từng sợ hãi như ta, từng yếu đuối, từng lo mất đi điều mình yêu.</p>

<h2 id="chiếc-bóng-của-yêu-thương">Chiếc bóng của yêu thương</h2>
<p>Ghen tuông là chiếc bóng của tình yêu.<br />
Bóng càng dài khi ánh sáng trong lòng ta yếu ớt.<br />
Nội tâm đủ sáng, bóng sẽ tự tan.</p>

<p>Ta không cần giữ tình yêu bằng tay.<br />
Chỉ cần giữ ngọn lửa trong tim vẫn cháy.<br />
Vì tình yêu thật sự, chẳng thể nào rời bỏ người biết yêu bằng tự do.</p>]]></content><author><name></name></author><category term="opinion" /><category term="opinion" /><category term="thinking" /><category term="philosophy" /><category term="mindfulness" /><category term="growth" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Tư duy chậm lại</title><link href="https://thanhdancer.com/opinion/2025/09/14/tu-duy-cham-lai.html" rel="alternate" type="text/html" title="Tư duy chậm lại" /><published>2025-09-14T00:00:00+00:00</published><updated>2025-09-14T00:00:00+00:00</updated><id>https://thanhdancer.com/opinion/2025/09/14/tu-duy-cham-lai</id><content type="html" xml:base="https://thanhdancer.com/opinion/2025/09/14/tu-duy-cham-lai.html"><![CDATA[<p>“Hội đồng thành phố cũng còn có một quy định là không được thảo luận một nghị quyết nào ngay trong ngày mà nó được đề nghị, mà chỉ được thảo luận nó trong buổi họp đầy đủ của ngày hôm sau. Nếu không thì thể nào cũng có người hấp tấp phát biểu ngay những điều bồng bột trong đầu mình, rồi bắt đầu chỉ tìm mọi cách để biện hộ cho ý kiến bột phát đó chứ không quan tâm gì đến quyền lợi của dân chúng nữa. Kiểu người ấy thường sẵn sàng hy sinh công ích để giữ đặc quyền của mình, mà lý do thì rất vớ vẩn, nghĩa là đã trót nói cái gì ra rồi thì không thể chấp nhận là mình có thể sai. Cho nên tốt nhất là hãy bắt mọi người ai cũng phải để thì giờ suy nghĩ cho chín trước khi thảo luận” - Utopia</p>

<p>Đây là một đoạn trích trong cuốn Utopia của Thomas More, nói về cách mà một hội đồng thành phố nên vận hành để tránh những quyết định vội vàng, bồng bột. Đọc đến đoạn này, ở thời điểm hiện tại của nhận thức, mình cảm thấy đồng cảm sâu sắc. Thực hành “chậm lại” — sống trong khoảnh khắc thay vì chỉ lướt qua — giúp mình thấy rõ hơn sự tinh tế của thực tại, mở rộng lòng đồng cảm và sự thấu hiểu.</p>

<p>Phản ứng đầu tiên của mình trước một thông tin mới thường là phản kháng. Nếu không có khoảnh khắc lắng lại, có lẽ mình đã bỏ qua nhiều điều thú vị. Khi cho bản thân một nhịp chậm, mình có cơ hội nén cảm xúc, để thông tin mới hòa vào nhận thức, rồi từ từ phối kết, tìm cách thấu hiểu, cảm thông, xác định ranh giới và củng cố niềm tin. Ngoại trừ những người cố tình đưa ra thông tin sai lệch vì mục đích không trong sáng, mình tin rằng đa số chúng ta đều có thiện ý, đúng sai chỉ khác nhau ở góc nhìn. Nhờ vậy, việc lắng nghe trở thành một hành trình: ban đầu có thể mệt mỏi vì phải “thỏa thuận” với chính mình để chấp nhận điều lạ lẫm, nhưng khi tìm được cách hóa giải, mình lại thấy trân trọng và yêu mến người đối diện hơn — vì đã hiểu được họ.</p>

<p>Gần đây, mình chọn giao tiếp qua những kênh chậm mà chín chắn hơn, như email hay thư tay. Một phần vì mình không muốn bị cuốn vào cảm giác “đã xem mà chưa trả lời” thường gặp ở tin nhắn. Một phần vì mình đang rèn luyện cách phân bổ thời gian tập trung: ví dụ, hẹn trước 15 phút trao đổi công việc với đồng nghiệp A, và trong 15 phút đó mình hoàn toàn dành cho A, từ chối mọi thứ khác. Với tin nhắn liên tục, nhiều người, nhiều chuyện, ta dễ bị cuốn đi và giải quyết hời hợt.
Một lý do khác mình ưa thích kênh chậm: nó phản ánh sự chuẩn bị. Mình tin rằng đối tác khi gửi email đã cân nhắc kỹ lưỡng, chắt lọc thông tin để truyền đạt. Đón nhận một nội dung như vậy, mình thấy dễ chịu hơn nhiều so với những mẩu tin nhanh, ngắt quãng, buộc phải hỏi đi hỏi lại mà vẫn chưa nắm được ý chính. Hơn nữa, cách trình bày, chọn từ, cấu trúc văn bản cũng là những tín hiệu giúp mình hình dung phần nào hoàn cảnh và tính cách của người gửi.</p>

<p>Mình nghiệm ra rằng: muốn nhanh thì phải chuẩn, muốn chuẩn thì phải đúng (<a href="https://wiki.c2.com/?MakeItWorkMakeItRightMakeItFast"><em>Make It Work, Make It Right, Make It Fast</em></a>). Mà muốn làm đúng thì nền móng phải vững chắc, chính xác — điều ấy không thể vội vàng. Thời thế xoay vần, công nghệ đổi thay, nhưng mình vẫn giữ niềm tin mãnh liệt vào những giá trị cốt lõi bền vững.</p>]]></content><author><name></name></author><category term="opinion" /><category term="opinion" /><category term="thinking" /><category term="philosophy" /><category term="mindfulness" /><category term="growth" /><summary type="html"><![CDATA[“Hội đồng thành phố cũng còn có một quy định là không được thảo luận một nghị quyết nào ngay trong ngày mà nó được đề nghị, mà chỉ được thảo luận nó trong buổi họp đầy đủ của ngày hôm sau. Nếu không thì thể nào cũng có người hấp tấp phát biểu ngay những điều bồng bột trong đầu mình, rồi bắt đầu chỉ tìm mọi cách để biện hộ cho ý kiến bột phát đó chứ không quan tâm gì đến quyền lợi của dân chúng nữa. Kiểu người ấy thường sẵn sàng hy sinh công ích để giữ đặc quyền của mình, mà lý do thì rất vớ vẩn, nghĩa là đã trót nói cái gì ra rồi thì không thể chấp nhận là mình có thể sai. Cho nên tốt nhất là hãy bắt mọi người ai cũng phải để thì giờ suy nghĩ cho chín trước khi thảo luận” - Utopia]]></summary></entry><entry><title type="html">Nghĩ về Mưa Đỏ</title><link href="https://thanhdancer.com/reaction/2025/09/07/nghi-ve-mua-do.html" rel="alternate" type="text/html" title="Nghĩ về Mưa Đỏ" /><published>2025-09-07T00:00:00+00:00</published><updated>2025-09-07T00:00:00+00:00</updated><id>https://thanhdancer.com/reaction/2025/09/07/nghi-ve-mua-do</id><content type="html" xml:base="https://thanhdancer.com/reaction/2025/09/07/nghi-ve-mua-do.html"><![CDATA[<p>Trong lịch sử Việt Nam hiện đại, Trận chiến 81 ngày đêm tại Thành cổ Quảng Trị năm 1972 là một dấu mốc bi tráng. Từ ngày 28/6 đến 16/9/1972, hàng vạn chiến sĩ đã chiến đấu và hy sinh trong bom đạn ác liệt để giành giật từng tấc đất bên bờ sông Thạch Hãn. Trận đánh không chỉ mang ý nghĩa chiến thuận, mà còn có vai trò quan trọng trong việc tạo thế cân bằng tại bàn đàm phán Hiệp định Paris, mở đường cho hoà bình và thống nhất đất nước.</p>

<p>Dựa trên tiểu thuyết Mưa đỏ của nhà văn Chu Lai, bộ phim “Mưa Đỏ: Máu xương đổ xuống - Đất trời lưu danh” tái hiện lại bối cảnh lịch sử hào hùng ấy. Phim không chỉ khắc hoạ sự khống liện của chiến tranh, mà còn hướng đến khơi gợi sự đồng cảm, tinh thần hoà hợp và trân trọng giá trị hoà bình ngày hôm nay.</p>

<p><a href="/images/2025/09/07/muado2jpg-1757080142362.webp"><img src="/images/2025/09/07/muado2jpg-1757080142362.webp" alt="Poster phim Mưa Đỏ" /></a></p>

<p>Về nội dung, ngay từ đầu bộ phim đã mở ra bằng hình ảnh sự tòng quân của cả hai chiến tuyến. Điều này khiến mình kỳ vọng rằng sẽ được cùng khán giả chứng kiến câu chuyện từ cả hai phía. Nếu được khai thác tốt, phim có thể tránh đi lối tuyên truyền phân cực thắng - thua, thiện - ác, ta - địch quen thuộc, mang lại cho khán giả một góc nhìn cảm thông hơn với những người lính miền Nam. Nếu làm được điều đó, mình tin rằng sự thấu hiểu và chia sẻ sẽ khơi gợi tinh thần hàn gắn, hoà bình, đoàn kết, góp phần khắc phục những vết rạn nứt quá khứ để cùng nhau xây dựng một Việt Nam mạnh mẽ hơn.</p>

<p>Tuy nhiên, hy vọng đó chỉ kéo dài khoảng 30 phút đầu phim, khi đạo diễn khéo léo dựng lên bối cảnh của hai tuyến: tiểu đội lính miền Bắc đầy hào khí, mộng mơ, quả cảm vì lý tưởng; song song là Quang - một chiến sĩ Việt Nam Cộng Hoà tham chiến với lòng dũng cảm và nghĩa khí. Những hoạt cảnh tiếp theo khắc hoạ sự khốc liệt, gian khổ của cuộc chiến, tinh thần quyết tâm giành giật cứ điểm quan trọng. Đến giai đoạn này, bộ phim dành cho các chiến sĩ Việt Minh cảm xúc cao hơn, không còn khắc hoạ sâu đời sống bên kia chiến tuyến, mà chủ yếu thể hiện sự áp đặt vô lý từ tướng lĩnh và tổng thống Việt Nam Cộng Hoà vào chiến trường. Điều này có thể khiến cảm xúc khán giả dễ bị phân cực, không còn sự cân bằng như kỳ vọng ban đầu.</p>

<p>Xét về tổng thể, Mưa đỏ là bộ phim đáng xem, đặc biệt trong dịp Quốc Khánh như một cách để hoà mình vào không khí ngày lễ. Về mặt kỹ thuật, phim được thực hiện rất chỉn chu: từ góc máy, âm thanh, ánh sáng. đến biên đạo võ thuật và các hình ảnh mang tính biểu tượng sâu sắc. Đoàn làm phim đa dành nhiều tháng trời khảo sát hơn 10 tỉnh thành để dựng phim trường rộng gần 50ha bên bờ sông Thạch Hãn, phục dựng Thành cổ Quảng Trị cùng hệ thống hầm hào, chiến luỹ với độ chân thực cao. Sự tỉ mỉ còn thể hiện ở việc tái hiện chính xác phục trang và vũ khí của giai đoạn 1972.</p>

<p>Một điểm cộng khác là diễn xuất của dàn diễn viên trẻ. Dù chưa nhiều tên tuổi nổi bật, họ mang đến cảm xúc tự nhiên, đặc biệt qua ánh mắt và biểu cảm đầy chân thực, hoà hợp hoàn toàn với bối cảnh. Cách kể chuyện mạch lạc, thắt nút, mở nút hợp lý, và đến cuối phim vẫn đủ sức níu chân khán giả ở lại đến phần credit - một minh chứng rõ ràng cho sức hút của tác phẩm.</p>

<p>Quan trọng hơn, Mưa đỏ không chỉ tái hiện một trận chiến khốc liệt, mà còn khơi gợi nơi người xem sự thấu cảm và trân trọng hoà bình hôm nay. Bộ phim nhắc chúng ta nhớ rằng sau những mất mát và chia cắt, điều còn lại và cần được gìn giữ chính là tinh thần hoà hợp, đoàn kết để cùng nhau xây dựng một Việt Nam sánh vai với các bạn bè quốc tế.</p>]]></content><author><name></name></author><category term="reaction" /><category term="quang-tri" /><category term="mua-do" /><category term="film" /><category term="vietnam" /><category term="war" /><summary type="html"><![CDATA[Trong lịch sử Việt Nam hiện đại, Trận chiến 81 ngày đêm tại Thành cổ Quảng Trị năm 1972 là một dấu mốc bi tráng. Từ ngày 28/6 đến 16/9/1972, hàng vạn chiến sĩ đã chiến đấu và hy sinh trong bom đạn ác liệt để giành giật từng tấc đất bên bờ sông Thạch Hãn. Trận đánh không chỉ mang ý nghĩa chiến thuận, mà còn có vai trò quan trọng trong việc tạo thế cân bằng tại bàn đàm phán Hiệp định Paris, mở đường cho hoà bình và thống nhất đất nước.]]></summary></entry><entry><title type="html">Scrum Reserve Timebox</title><link href="https://thanhdancer.com/management/2025/08/31/scrum-reserved-space.html" rel="alternate" type="text/html" title="Scrum Reserve Timebox" /><published>2025-08-31T00:00:00+00:00</published><updated>2025-08-31T00:00:00+00:00</updated><id>https://thanhdancer.com/management/2025/08/31/scrum-reserved-space</id><content type="html" xml:base="https://thanhdancer.com/management/2025/08/31/scrum-reserved-space.html"><![CDATA[<p>Khi tiếp cận với mô hình Agile, đặc biệt là Scrum, điều khiến mình tâm đắc nhất chính là backlog được quản lý trong timebox. Cách làm này bảo vệ đội ngũ khỏi tình trạng bị phân tâm, nhận thêm việc ngoài kế hoạch, dẫn đến quá tải, chất lượng giảm sút, phải làm thêm giờ và dễ rơi vào kiệt sức.</p>

<p>Một Sprint kéo dài 2 tuần thường được coi là hợp lý: đủ ngắn để điều chỉnh chiến lược khi cần thiết, đủ dài để hoàn thiện một phase hoặc một tính năng, tạo ra một output vừa vặn khi kết thúc. Tuy nhiên, trên thực tế quản lý, luôn có những công việc chen ngang xuất hiện - thường là nhiệm vụ khẩn cấp, không thể chờ đến cuối Sprint. Nếu bỏ qua, dự án có thể đánh mất cơ hội hoặc đi sai hướng. Nếu đưa ngay vào Sprint đang chạy, thì vừa vi phạm nguyên tắc cam kết, vừa khiến team khó thực hiện trọn vẹn cả backlog cũ lẫn mới. Đây là một tình huống tiến thoái lưỡng nan mà mình từng nhiều lần gặp phải.</p>

<h2 id="ý-chính-tóm-gọn">Ý chính tóm gọn</h2>
<ul>
  <li>Không thể tránh hoàn toàn việc chen ngang trong Sprint -&gt; cần cơ chế để xử lý.</li>
  <li>Reserve Space = 20% effort dành cho công việc đột xuất, khẩn cấp.</li>
  <li>Low Prioriry backlog có thể “lấp chỗ trống” nhưng sẵn sàng bị thay thế.</li>
  <li>Nếu Reserve Space luôn bị vượt quá -&gt; phải xem lại kế hoạch dự án và kỳ vọng của các Stakeholders.</li>
  <li>Kết hợp kỷ luật của Scrum với linh hoạt thực tế -&gt; giúp team vừa ổn định, vừa thích ứng.</li>
</ul>

<h2 id="phân-tích-vấn-đề">Phân tích vấn đề</h2>
<p>Như đã nêu ở phần mở đầu, các vấn đề có thể kể đến trong trường hợp này gồm:</p>
<ul>
  <li>Nếu bỏ qua: có nguy cơ bỏ lỡ cơ hội quan trọng, dự án đi chệch mục tiêu.</li>
  <li>Nếu nhồi thêm vào Sprint: team bị quá tải, backlog cam kết từ đầu khó hoàn thành, chất lượng tổng thể giảm.</li>
</ul>

<p>Kinh nghiệm thực tế cho thấy, việc này không thể giải quyết bằng cách áp dụng lý thuyết một cách cứng nhắc, mà cần có một cơ chế linh hoạt để hấp thụ các biến động.</p>

<h2 id="giải-pháp-reserve-space-trong-sprint">Giải pháp: Reserve Space trong Sprint</h2>
<p>Mình đã thử áp dụng một ý tưởng gọi là Reserve Space - tức dành trước một phần dung lượng Sprint để xử lý các công việc khẩn cấp. Cách làm như sau:</p>

<ol>
  <li>Khi lập kế hoạch Sprint:
    <ul>
      <li>Chỉ commit backlog chính (Normal Backlog) ở mức khoảng 80% effort tổng Sprint.</li>
      <li>20% effort còn lại dành cho Reserve Space.</li>
    </ul>
  </li>
  <li>Cách sử dụng Reserve Space:
    <ul>
      <li>Nếu có công việc khẩn cấp (Critical Backlog), chúng sẽ được đưa vào phần Reserve Space.</li>
      <li>Các backlog ưu tiên thấp (Low Priority Backlog) có thể được xếp tạm trong Reserve Space để team thực hiện nếu không có việc chen ngang, nhưng sẵn sàng bị loại bỏ nếu cần nhường chỗ cho backlog quan trọng hơn.</li>
    </ul>
  </li>
  <li>Khi Reserve Space bị vượt quá:
    <ul>
      <li>Nếu Sprint nào cũng xuất hiện quá nhiều backlog khẩn cấp vượt ngoài Reserve Space, đó là tín hiệu cần xem xét lại dự án: có thể team đang hứa hẹn quá mức hoặc kỳ vọng từ stakeholders chưa thực tế.</li>
    </ul>
  </li>
</ol>

<h2 id="bài-học-rút-ra">Bài học rút ra</h2>
<p>Scrum mang lại sự kỷ luật trong cam kết, nhưng thực tế quản lý dự án luôn có biến số. Thay vì máy moc bỏ qua hoặc nhồi nhét backlog chen ngang, việc chủ động thiết kế một khoảng dung lượng dự phòng trong Sprint giúp đội ngũ vừa giữ được sự ổn định, vừa linh hoạt khi tình huống bất ngờ xảy đến.</p>]]></content><author><name></name></author><category term="management" /><category term="project-management" /><category term="scrum" /><category term="agile" /><category term="timebox" /><category term="backlog" /><category term="sprint" /><summary type="html"><![CDATA[Khi tiếp cận với mô hình Agile, đặc biệt là Scrum, điều khiến mình tâm đắc nhất chính là backlog được quản lý trong timebox. Cách làm này bảo vệ đội ngũ khỏi tình trạng bị phân tâm, nhận thêm việc ngoài kế hoạch, dẫn đến quá tải, chất lượng giảm sút, phải làm thêm giờ và dễ rơi vào kiệt sức.]]></summary></entry><entry><title type="html">Cẩn trọng dùng UFW với Docker</title><link href="https://thanhdancer.com/technical/2025/01/13/can-trong-dung-ufw-voi-docker.html" rel="alternate" type="text/html" title="Cẩn trọng dùng UFW với Docker" /><published>2025-01-13T00:00:00+00:00</published><updated>2025-01-13T00:00:00+00:00</updated><id>https://thanhdancer.com/technical/2025/01/13/can-trong-dung-ufw-voi-docker</id><content type="html" xml:base="https://thanhdancer.com/technical/2025/01/13/can-trong-dung-ufw-voi-docker.html"><![CDATA[<h2 id="tldr">TLDR;</h2>
<ul>
  <li>UFW không chặn được các gói tin từ bên trong mạng nội bộ khi mapping port với Docker container (thường dùng trong tham số của docker run <code class="language-plaintext highlighter-rouge">-p {internal-ip}:{expose-port}:{container-port}</code>).</li>
  <li>Phương án 1: Sử dụng firewall từ Cloud Provider.</li>
  <li>Phương án 2: Sử dụng <a href="https://linux.die.net/man/8/iptables"><code class="language-plaintext highlighter-rouge">iptables</code></a> để chặn các gói tin từ bên trong mạng nội bộ.</li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Block all traffics </span>
<span class="nb">sudo </span>iptables <span class="nt">-I</span> DOCKER-USER <span class="nt">-i</span> <span class="o">{</span>network_interface<span class="o">}</span> <span class="nt">-j</span> DROP

<span class="c"># Keep connection states ESTABLISHED, RELATED</span>
<span class="nb">sudo </span>iptables <span class="nt">-I</span> DOCKER-USER <span class="nt">-i</span> eth1 <span class="nt">-m</span> conntrack <span class="nt">--ctstate</span> ESTABLISHED,RELATED <span class="nt">-j</span> ACCEPT

<span class="c"># Each allowing rule will be added</span>
<span class="nb">sudo </span>iptables <span class="nt">-I</span> DOCKER-USER <span class="nt">-i</span> <span class="o">{</span>network_interface<span class="o">}</span> <span class="nt">-m</span> conntrack <span class="nt">-p</span> tcp <span class="nt">--ctstate</span> NEW <span class="nt">--ctorigsrc</span> <span class="o">{</span>source_ip<span class="o">}</span> <span class="nt">--ctorigdstport</span> <span class="o">{</span>destination_port<span class="o">}</span> <span class="nt">-j</span> ACCEPT
</code></pre></div></div>

<h2 id="kịch-bản">Kịch bản</h2>
<p><a href="/images/2025/01/13/scenario1.png"><img src="/images/2025/01/13/scenario1.png" alt="Hạ tầng" /></a></p>
<h3 id="hạ-tầng">Hạ tầng</h3>

<table>
  <thead>
    <tr>
      <th>Máy chủ</th>
      <th>Network Interface</th>
      <th>IP Address</th>
      <th>Mô tả</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>A</td>
      <td>eth0</td>
      <td>x.x.x.1</td>
      <td>Cổng mạng ngoại bộ</td>
    </tr>
    <tr>
      <td>A</td>
      <td>eth1</td>
      <td>10.0.0.1</td>
      <td>Cổng mạng nội bộ</td>
    </tr>
    <tr>
      <td>B</td>
      <td>eth0</td>
      <td>x.x.x.2</td>
      <td>Cổng mạng ngoại bộ</td>
    </tr>
    <tr>
      <td>B</td>
      <td>eth1</td>
      <td>10.0.0.2</td>
      <td>Cổng mạng nội bộ</td>
    </tr>
    <tr>
      <td>C</td>
      <td>eth1</td>
      <td>10.0.0.3</td>
      <td>Cổng mạng nội bộ</td>
    </tr>
  </tbody>
</table>

<h3 id="dịch-vụ">Dịch vụ</h3>
<p>Các dịch vụ đang chạy trong docker container, các cổng (port) được mapping như bảng sau.</p>

<table>
  <thead>
    <tr>
      <th>Máy chủ</th>
      <th>Dịch vụ</th>
      <th>Bind IP</th>
      <th>Port</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>A</td>
      <td>Web Server</td>
      <td>0.0.0.0</td>
      <td>80</td>
    </tr>
    <tr>
      <td>B</td>
      <td>MySQL 1</td>
      <td>10.0.0.2</td>
      <td>3306</td>
    </tr>
    <tr>
      <td>B</td>
      <td>MySQL 2</td>
      <td>10.0.0.2</td>
      <td>3307</td>
    </tr>
  </tbody>
</table>

<h3 id="mục-tiêu">Mục tiêu</h3>
<ul>
  <li>Chặn toàn bộ các gói tin từ Internet vào máy chủ B.</li>
  <li>Chặn toàn bộ các gói tin từ bên trong mạng nội bộ vào máy chủ B.</li>
  <li>Mở cho duy nhất máy chủ C được phép truy cập vào máy chủ B qua cổng 3307</li>
  <li>Mở cho duy nhất máy chủ A được phép truy cập vào máy chủ B qua cổng 3306</li>
</ul>

<h3 id="thực-thi">Thực thi</h3>
<p><ins><strong><em>Lưu ý:</em></strong> Kịch bản này chứa lỗi, không sử dụng trong môi trường thực tế.</ins></p>
<ul>
  <li>Bind dịch vụ MySQL 1 và MySQL 2 trên máy chủ B với cổng 3306 và 3307 trên cổng mạng nội bộ.</li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Môi trường: Máy chủ B</span>
docker run <span class="nt">--name</span> mysql-1 <span class="nt">-d</span> <span class="nt">-p</span> 10.0.0.2:3306:3306 mysql:5.7 
docker run <span class="nt">--name</span> mysql-2 <span class="nt">-d</span> <span class="nt">-p</span> 10.0.0.2:3307:3306 mysql:5.7
</code></pre></div></div>
<ul>
  <li>Dùng <code class="language-plaintext highlighter-rouge">ufw</code> làm firewall trên máy chủ B.</li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Môi trường: Máy chủ B</span>

<span class="c"># Chặn toàn kết nối vào</span>
ufw default deny incoming

<span class="c"># Mở cổng 3306 cho máy chủ A</span>
ufw allow from 10.0.0.1/32 to any port 3306

<span class="c"># Mở cổng 3307 cho máy chủ C</span>
ufw allow from 10.0.0.3/32 to any port 3307
</code></pre></div></div>

<h2 id="vấn-đề">Vấn đề</h2>
<ul>
  <li>UFW không chặn được các gói tin <sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup> khi mapping port với Docker container (thường dùng trong tham số của docker run <code class="language-plaintext highlighter-rouge">-p {internal-ip}:{expose-port}:{container-port}</code>).</li>
  <li>Một số bài viết <sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup> tìm cách chèn thêm các rules vào chain <code class="language-plaintext highlighter-rouge">DOCKER-USER</code> của iptables nhưng chỉ hiệu quả để chặn các gói tin đến từ bên ngoài, không chặn được các gói tin từ bên trong mạng nội bộ như kịch bản đề ra.</li>
</ul>

<h2 id="phương-án">Phương án</h2>
<h3 id="1-sử-dụng-firewall-từ-cloud-provider">1. Sử dụng firewall từ Cloud Provider</h3>
<ul>
  <li>Đối với các dịch vụ cloud chuyên nghiệp như AWS, GCP, Azure, các máy chủ sẽ được quản lý bởi firewall của cloud provider. Với sự hỗ trợ của hệ thống mạng ảo VPC, họ tích hợp firewall tầng mạng thay vì sử dụng các firewall tầng phần mềm <sup id="fnref:3"><a href="#fn:3" class="footnote" rel="footnote" role="doc-noteref">3</a></sup> <sup id="fnref:4"><a href="#fn:4" class="footnote" rel="footnote" role="doc-noteref">4</a></sup> <sup id="fnref:5"><a href="#fn:5" class="footnote" rel="footnote" role="doc-noteref">5</a></sup>. Vì vậy, việc chặn sẽ hiệu quả và không ảnh hưởng vì các phần mềm xung đột với nhau.</li>
</ul>

<h3 id="2-sử-dụng-iptables-trên-từng-máy-chủ">2. Sử dụng iptables trên từng máy chủ</h3>
<ul>
  <li>Dùng chain <code class="language-plaintext highlighter-rouge">DOCKER-USER</code> để quản lý các rule của Docker thay vì các chain mặc định. Mục đích của việc này là để tách biệt các rule định nghĩa cho Docker với các rule khác <sup id="fnref:1:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup>.</li>
  <li>Các rules viết phải sử dụng extension <code class="language-plaintext highlighter-rouge">conntrack</code><sup id="fnref:6"><a href="#fn:6" class="footnote" rel="footnote" role="doc-noteref">6</a></sup>  vì sau khi gói tin vào <code class="language-plaintext highlighter-rouge">DOCKER-USER</code> đã qua bộ lọc DNAT <sup id="fnref:1:2"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup>, địa chỉ và cổng đã có thể bị thay đổi.</li>
  <li>Lệnh thêm rules vào chain <code class="language-plaintext highlighter-rouge">DOCKER-USER</code> trên máy chủ B:</li>
</ul>

<p><ins><strong><em>Lưu ý:</em></strong> iptables có thể làm mất kết nối điều khiển nếu bạn cấu hình sai. Hãy chắc chắn có phương án truy cập thay thế trong trường hợp mất kết nối.</ins></p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Môi trường: Máy chủ B</span>
<span class="c"># Chặn toàn bộ gói tin từ Internet </span>
<span class="nb">sudo </span>iptables <span class="nt">-I</span> DOCKER-USER <span class="nt">-i</span> eth0 <span class="nt">-j</span> DROP
<span class="nb">sudo </span>iptables <span class="nt">-I</span> DOCKER-USER <span class="nt">-i</span> eth0 <span class="nt">-j</span> LOG <span class="nt">--log-prefix</span> <span class="s2">"Dropped packet: "</span> <span class="nt">--log-level</span> 4

<span class="c"># Chặn toàn bộ gói tin nội bộ</span>
<span class="nb">sudo </span>iptables <span class="nt">-I</span> DOCKER-USER <span class="nt">-i</span> eth1 <span class="nt">-j</span> DROP
<span class="nb">sudo </span>iptables <span class="nt">-I</span> DOCKER-USER <span class="nt">-i</span> eth1 <span class="nt">-j</span> LOG <span class="nt">--log-prefix</span> <span class="s2">"Dropped packet: "</span> <span class="nt">--log-level</span> 4

<span class="c"># Giữ các kết nối ở trạng thái ESTABLISHED, RELATED</span>
<span class="c"># Rule này sẽ giúp bạn giải quyết tình trạng kết nối ra ngoài đã thiết lập nhưng lại bị chặn.</span>
<span class="nb">sudo </span>iptables <span class="nt">-I</span> DOCKER-USER <span class="nt">-i</span> eth1 <span class="nt">-m</span> conntrack <span class="nt">--ctstate</span> ESTABLISHED,RELATED <span class="nt">-j</span> ACCEPT

<span class="c"># Mở cho duy nhất máy chủ A truy cập cổng 3306 qua mạng nội bộ</span>
<span class="nb">sudo </span>iptables <span class="nt">-I</span> DOCKER-USER <span class="nt">-i</span> eth1 <span class="nt">-m</span> conntrack <span class="nt">-p</span> tcp <span class="nt">--ctstate</span> NEW <span class="nt">--ctorigsrc</span> 10.0.0.1 <span class="nt">--ctorigdstport</span> 3306 <span class="nt">-j</span> ACCEPT

<span class="c"># Mở cho duy nhất máy chủ C truy cập cổng 3307 qua mạng nội bộ</span>
<span class="nb">sudo </span>iptables <span class="nt">-I</span> DOCKER-USER <span class="nt">-i</span> eth1 <span class="nt">-m</span> conntrack <span class="nt">-p</span> tcp <span class="nt">--ctstate</span> NEW <span class="nt">--ctorigsrc</span> 10.0.0.3 <span class="nt">--ctorigdstport</span> 3307 <span class="nt">-j</span> ACCEPT
</code></pre></div></div>

<!-- ## Tham chiếu -->

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">
      <p><a href="https://docs.docker.com/engine/network/packet-filtering-firewalls/#port-publishing-and-mapping">Packet filtering and firewalls</a> <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a> <a href="#fnref:1:1" class="reversefootnote" role="doc-backlink">&#8617;<sup>2</sup></a> <a href="#fnref:1:2" class="reversefootnote" role="doc-backlink">&#8617;<sup>3</sup></a></p>
    </li>
    <li id="fn:2">
      <p><a href="https://github.com/chaifeng/ufw-docker">To Fix The Docker and UFW Security Flaw Without Disabling Iptables</a> <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3">
      <p><a href="https://docs.aws.amazon.com/network-firewall/latest/developerguide/what-is-aws-network-firewall.html">AWS Network Firewall</a> <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:4">
      <p><a href="https://cloud.google.com/firewall/docs/configure-global-fw-policies">Google Cloud NGFW</a> <a href="#fnref:4" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:5">
      <p><a href="https://learn.microsoft.com/en-us/azure/firewall/overview">Azure Firewall</a> <a href="#fnref:5" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:6">
      <p><a href="https://ipset.netfilter.org/iptables-extensions.man.html#lbAO">iptable conntrack extension</a> <a href="#fnref:6" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name></name></author><category term="technical" /><category term="docker" /><category term="security" /><category term="network" /><category term="firewall" /><category term="iptables" /><category term="ufw" /><summary type="html"><![CDATA[TLDR; UFW không chặn được các gói tin từ bên trong mạng nội bộ khi mapping port với Docker container (thường dùng trong tham số của docker run -p {internal-ip}:{expose-port}:{container-port}). Phương án 1: Sử dụng firewall từ Cloud Provider. Phương án 2: Sử dụng iptables để chặn các gói tin từ bên trong mạng nội bộ.]]></summary></entry><entry><title type="html">Lọc trùng dữ liệu</title><link href="https://thanhdancer.com/technical/2015/03/02/loc-trung-du-lieu.html" rel="alternate" type="text/html" title="Lọc trùng dữ liệu" /><published>2015-03-02T00:00:00+00:00</published><updated>2015-03-02T00:00:00+00:00</updated><id>https://thanhdancer.com/technical/2015/03/02/loc-trung-du-lieu</id><content type="html" xml:base="https://thanhdancer.com/technical/2015/03/02/loc-trung-du-lieu.html"><![CDATA[<h2 id="ý-chính">Ý chính</h2>
<ul>
  <li>Sử dụng Bash với công cụ <code class="language-plaintext highlighter-rouge">cat</code>, <code class="language-plaintext highlighter-rouge">parallel</code>, <code class="language-plaintext highlighter-rouge">sed</code>, <code class="language-plaintext highlighter-rouge">sort</code> cho kết quả tối ưu nhất.</li>
</ul>

<h2 id="giới-thiệu">Giới thiệu</h2>
<p>Khi làm việc với dữ liệu thô, theo trạng thái từng từ, mỗi từ một dòng (thường dùng trong làm từ điển), dữ liệu thường bị thừa ra. Nguyên nhân là do dữ liệu trùng nhau, các kí tự thừa (\r, \n, space) ở đầu và cuối các từ làm bộ lọc nhầm lẫn cho rằng đây là các từ khác nhau. Vậy nên bài toán đặt ra trong quá trình làm sạch dữ liệu là xóa các kí tự thừa ở đầu và cuối của từ, sắp xếp và lọc các từ trùng nhau.</p>

<p>Trong làm việc với dữ liệu ít, công việc đó đơn giản, thậm chí làm việc với các phần mềm bảng tính như Excel cũng có thể giải quyết vấn đề. Tuy nhiên, với dữ liệu bắt đầu từ 100 Mb đến hàng GB, TB thì ta phải có một số thủ thuật. Trong bài viết này mình sẽ chia sẻ kinh nghiệm vài lần xử lý và số liệu benchmark.</p>

<h2 id="thử-nghiệm-lọc-trùng-lần-thứ-nhất">Thử nghiệm lọc trùng lần thứ nhất</h2>
<h3 id="điều-kiện">Điều kiện</h3>
<p>Máy tính cá nhân với cấu hình:</p>
<ul>
  <li>OS: Ubuntu 14.04</li>
  <li>RAM: 4GB</li>
  <li>CPU: Intel® Core™ i5-2430M CPU @ 2.40GHz × 4</li>
</ul>

<p>Dữ liệu được phân bổ:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">1k.txt</code>: 1,000 dòng đầu tiên của tệp dữ liệu.</li>
  <li><code class="language-plaintext highlighter-rouge">100k.txt</code>: 100,000 dòng đầu tiên của tệp dữ liệu gốc.</li>
  <li><code class="language-plaintext highlighter-rouge">6tr.txt</code>: Tệp dữ liệu gốc chứa khoảng 6 triệu dòng.</li>
</ul>

<h3 id="phương-thức-thực-hiện">Phương thức thực hiện</h3>
<p>Mình sẽ sử dụng 3 ngôn ngữ để tiện so sánh: Bash, R, và Python.<br />
Theo những cách trước đây, sẽ sử dụng ngôn ngữ Bash và hàm có sẵn của hệ điều hành linux là <code class="language-plaintext highlighter-rouge">sort</code> và <code class="language-plaintext highlighter-rouge">uniq</code>.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat</span> &lt;input-file&gt; | <span class="nb">sort</span> | <span class="nb">uniq</span> &lt;output-file&gt;
</code></pre></div></div>
<p>Sau khi lọc trùng sẽ thu được output đã sắp xếp. Vì lệnh <code class="language-plaintext highlighter-rouge">uniq</code> chỉ được thực hiện sau khi đã sắp xếp input nên bắt buộc phải sort trước khi lọc trùng.</p>

<p>Sau một thời gian tiếp cận, mình biết thêm <a href="https://www.r-project.org">ngôn ngữ R</a> được đánh giá rất tốt dùng cho Thống kê. Vậy nên mình đã cài đặt và thử nghiệm trong công việc lọc trùng. Đối với R, sau khi nhập dữ liệu, ta không cần phải sắp xếp.</p>

<p>Cuối cùng với ngôn ngữ Python, dùng thư viện <a href="https://docs.python.org/3/library/collections.html#counter-objects"><code class="language-plaintext highlighter-rouge">collections.Counter</code></a> để đưa dữ liệu vào bộ đếm. Sau đó ghi ra file.</p>

<h3 id="kết-quả">Kết quả</h3>

<table>
  <thead>
    <tr>
      <th>Ngôn ngữ</th>
      <th>Có sắp xếp</th>
      <th>Đầu vào</th>
      <th>Thời gian</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Bash</td>
      <td>Có</td>
      <td>1k.txt</td>
      <td><strong>0s</strong></td>
    </tr>
    <tr>
      <td>Bash</td>
      <td>Có</td>
      <td>100k.txt</td>
      <td>1s</td>
    </tr>
    <tr>
      <td>Bash</td>
      <td>Có</td>
      <td>6tr.txt</td>
      <td>48s</td>
    </tr>
    <tr>
      <td>R</td>
      <td>Không</td>
      <td>1k.txt</td>
      <td>0.01s</td>
    </tr>
    <tr>
      <td>R</td>
      <td>Không</td>
      <td>100k.txt</td>
      <td><strong>0.657s</strong></td>
    </tr>
    <tr>
      <td>R</td>
      <td>Không</td>
      <td>6tr.txt</td>
      <td>71.624s</td>
    </tr>
    <tr>
      <td>Python</td>
      <td>Không</td>
      <td>1k.txt</td>
      <td>0.001s</td>
    </tr>
    <tr>
      <td>Python</td>
      <td>Không</td>
      <td>100k.txt</td>
      <td>0.075s</td>
    </tr>
    <tr>
      <td>Python</td>
      <td>Không</td>
      <td>6tr.txt</td>
      <td><strong>5.926s</strong></td>
    </tr>
  </tbody>
</table>

<h3 id="nhận-xét">Nhận xét</h3>

<p>Như vậy, dùng Bash xử lý file 72MB sẽ phải mất thời gian khoảng 48s để thực hiện, đối với R thì mất 71s (trong đó 28s để đọc dữ liệu). Riêng đối với Python chỉ mất khoảng 6s cho tất cả các công đoạn.</p>

<p>Tuy nhiên với đầu ra của dữ liệu thì chênh lệch nhau khá lớn giữa các ngôn ngữ. Sau khi kiểm tra các file đầu ra của bộ input 100k, không tìm thấy sự khác nhau của output giữa các ngôn ngữ. Tuy nhiên lại có một phát hiện khác khi sử dụng lệnh cat -v đối với file 1k-python.out, cuối mỗi dòng xuất hiện ký tự <code class="language-plaintext highlighter-rouge">^M</code> (<code class="language-plaintext highlighter-rouge">\r</code> trong Windows).</p>

<p>Hơn nữa, sau khi xem kĩ các file output, nhận thấy các kí tự thừa khoảng trống đằng sau nhưng vẫn không bị lọc.</p>

<p><img src="/images/2015/03/02/extra-spaces-1.png" alt="Kí tự thừa" /></p>

<p><img src="/images/2015/03/02/extra-spaces-2.png" alt="Kí tự thừa" /></p>

<h3 id="rút-kinh-nghiệm">Rút kinh nghiệm</h3>
<ul>
  <li>Với khả năng tối ưu nhất, mình sẽ sử dụng Python để thực hiện các lần thử nghiệm tiếp theo.</li>
  <li>Tiền xử lý dữ liệu (pre-process) bằng cách xoá hết các khoảng trống trước và sau của mỗi dòng.</li>
  <li>Sử dụng đa luồng (multi-thread) để tăng tốc độ xử lý của CPU.</li>
</ul>

<h2 id="thử-nghiệm-lần-hai">Thử nghiệm lần hai</h2>
<h3 id="điều-kiện-1">Điều kiện</h3>
<ul>
  <li>Tương tự như <a href="#điều-kiện">điều kiện của lần 1</a>.</li>
  <li>Thêm file <code class="language-plaintext highlighter-rouge">full.txt</code> chứa toàn bộ dữ liệu cần xử lý (khoảng 500 MB).</li>
</ul>

<h3 id="phương-thức-thực-hiện-1">Phương thức thực hiện</h3>
<p>Trước hết, xoá hết các ký tự khoảng trống, <code class="language-plaintext highlighter-rouge">\n</code>, <code class="language-plaintext highlighter-rouge">\r</code> ở trước và sau mỗi dòng.<br />
Sử dụng hàm <code class="language-plaintext highlighter-rouge">map(str.strip, data)</code> của Python sau khi đọc file để thực hiện tác vụ trên. Các bước thử nghiệm tương tự lần trước.</p>

<h3 id="kết-quả-1">Kết quả</h3>

<table>
  <thead>
    <tr>
      <th>File</th>
      <th>Đọc</th>
      <th>Xử lý</th>
      <th>Ghi</th>
      <th>Tổng</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1k.txt</td>
      <td>0.000s</td>
      <td>0.000s</td>
      <td>0.000s</td>
      <td><strong>0.001s</strong></td>
    </tr>
    <tr>
      <td>100k.txt</td>
      <td>0.004s</td>
      <td>0.052s</td>
      <td>0.047s</td>
      <td><strong>0.103s</strong></td>
    </tr>
    <tr>
      <td>6tr.txt</td>
      <td>0.261s</td>
      <td>3.740s</td>
      <td>2.594s</td>
      <td><strong>6.595s</strong></td>
    </tr>
    <tr>
      <td>full.txt</td>
      <td>1m 6s</td>
      <td>9m 18s</td>
      <td>34m 19s</td>
      <td><strong>44m 44s</strong></td>
    </tr>
  </tbody>
</table>

<h3 id="nhận-xét-1">Nhận xét</h3>
<ul>
  <li>Với 2 file <code class="language-plaintext highlighter-rouge">1k.txt</code> và <code class="language-plaintext highlighter-rouge">100k.txt</code>,  khi chưa có sự trùng lặp nhiều về các từ chứa kí tự trống 2 đầu, dung lượng file tương đồng với cách sử dụng Bash. Có thể kết luận mỗi dòng chứa thêm kí tự <code class="language-plaintext highlighter-rouge">^M</code> đã làm dung lượng file tăng lên đáng kể.</li>
  <li>Đối với output của tập đầu vào <code class="language-plaintext highlighter-rouge">6tr.txt</code>, dung lượng đã giảm so với tập Bash ban đầu khoảng 30 KB.</li>
  <li>Khi xử lý với bộ dữ liệu nặng hơn, RAM bị quá tải. Khi đọc file, mặc dù số lượng biến ít, nhưng giá trị của biến sẽ phải nạp tương ứng với kích thước file đọc vào (trong trường hợp <code class="language-plaintext highlighter-rouge">full.txt</code> là 499 MB). Nếu như chạy toàn bộ sẽ hết dung lượng RAM và thời gian chạy sẽ rất lâu do phải đợi bộ nhớ giải phóng. Các lệnh chạy này xử lý trên RAM, không ảnh hưởng tới CPU nên việc multi-thread không cấp bách bằng việc chia nhỏ file để load. Dung lượng RAM còn lại (khi chạy song song các chương trình khác) cũng rất quan trọng. Đối với bộ dữ liệu <code class="language-plaintext highlighter-rouge">6tr.txt</code>, khi chạy cùng Google Chrome xảy ra tình trạng xử lý lâu, mất tới 60s thay vì 6s như trong trường hợp chạy chỉ cùng các trình editor đơn thuần.</li>
</ul>

<p><img src="/images/2015/03/02/ram-usage.jpg" alt="RAM" /></p>

<h3 id="rút-kinh-nghiệm-1">Rút kinh nghiệm</h3>
<ul>
  <li>Cắt nhỏ file ra thành từng phần nhỏ để xử lý.</li>
</ul>

<h2 id="thử-nghiệm-lần-ba">Thử nghiệm lần ba</h2>
<h3 id="điều-kiện-2">Điều kiện</h3>
<ul>
  <li>Cấu hình và dữ liệu <a href="#điều-kiện">tương tự lần 1</a>.</li>
</ul>

<h3 id="phương-thức-thực-hiện-2">Phương thức thực hiện</h3>
<p>Mình chưa tìm ra cách tối ưu khi load file và xử lý trên Python, vì vậy sẽ thử nghiệm với Bash để tìm cách cải tiến.</p>

<p>Trước đây, dòng lệnh để xử lý dữ liệu là <code class="language-plaintext highlighter-rouge">cat &lt;input-file&gt; | sort | uniq &lt;output-file&gt;</code>. Khi sử dụng lênh trên phát sinh một số vấn đề:</p>
<ul>
  <li>Dùng 3 hàm liền nhau, lặp lại công việc bị thừa.</li>
  <li>Chưa xử lý được vấn đề có các ký tự thừa ở đầu và cuối dòng.</li>
  <li>Chạy đơn luồng, không tận dụng được CPU.</li>
</ul>

<p>Mình đã khắc phục như sau:</p>
<ul>
  <li>Dùng <code class="language-plaintext highlighter-rouge">sed</code> để xoá các ký tự không mong muốn.</li>
  <li>Dùng <code class="language-plaintext highlighter-rouge">sort</code> với tham số -us (<code class="language-plaintext highlighter-rouge">-u: unique, -s: stable</code>). Khi sử dụng hai tham số này, ta đã có thể tối ưu việc xoá bỏ các dòng trùng nhau, sắp xếp, đọc file và chạy song song.</li>
</ul>

<p><img src="/images/2015/03/02/ram-usage-2.png" alt="RAM" /></p>

<h4 id="bước-1-tiền-xử-lý-xoá-khoảng-trống">Bước 1: Tiền xử lý xoá khoảng trống</h4>

<p>Với hàm <code class="language-plaintext highlighter-rouge">sed</code>, không có tham số tối ưu khi lọc dữ liệu nên chỉ chạy 1 luồng. Ta được kết quả:</p>

<table>
  <thead>
    <tr>
      <th>File</th>
      <th>Thời gian</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>6tr.txt</td>
      <td>7s</td>
    </tr>
    <tr>
      <td>full.txt</td>
      <td>1m 29s</td>
    </tr>
  </tbody>
</table>

<p>Để tối ưu hơn, mình sử dụng công cụ <a href="https://www.gnu.org/software/parallel/"><code class="language-plaintext highlighter-rouge">GNU parallel</code></a> để sed data. Câu lệnh tiền xử lý xoá khoảng trắng sẽ trở thành:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat</span> &lt;input&gt; | parallel –pipe <span class="nb">sed</span> ‘-e “s/<span class="se">\r</span>//g” <span class="nt">-e</span> “s/^ <span class="k">*</span>//” <span class="nt">-e</span> “s/ <span class="k">*</span><span class="nv">$/</span>/”’ <span class="o">&gt;</span> &lt;output&gt;
</code></pre></div></div>

<p>Kết quả thu được:</p>

<table>
  <thead>
    <tr>
      <th>File</th>
      <th>Thời gian</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>6tr.txt</td>
      <td>6s</td>
    </tr>
    <tr>
      <td>full.txt</td>
      <td>41s</td>
    </tr>
  </tbody>
</table>

<h4 id="bước-2-sắp-xếp-và-lọc-trùng">Bước 2: Sắp xếp và lọc trùng</h4>
<p>Mình sẽ chỉ sử dụng lệnh <code class="language-plaintext highlighter-rouge">sort</code> với tham số -us để sắp xếp và lọc trùng. Câu lệnh sẽ trở thành:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sort</span> <span class="nt">-us</span> <span class="nt">-o</span> &lt;output&gt; &lt;input&gt;
</code></pre></div></div>

<p>Thời gian thực hiện:</p>

<table>
  <thead>
    <tr>
      <th>File</th>
      <th>Thời gian</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>6tr.txt</td>
      <td>33s</td>
    </tr>
    <tr>
      <td>full.txt</td>
      <td>3m 41s</td>
    </tr>
  </tbody>
</table>

<h3 id="nhận-xét-2">Nhận xét</h3>
<p>Việc tối ưu đã hoàn thiện hơn nhiều so với lần trước.</p>]]></content><author><name></name></author><category term="technical" /><category term="python" /><category term="data" /><category term="processing" /><summary type="html"><![CDATA[Ý chính Sử dụng Bash với công cụ cat, parallel, sed, sort cho kết quả tối ưu nhất.]]></summary></entry></feed>