[閱讀筆記] Design Data-Intensive Application - Storage and Retrieval (OLAP)

前言 本篇繼續探討 Design Data-Intensive Application 這本書的第三章:Storage and Retrieval 簡單整理一下本小節主要談論的架構: OLTP(Transaction) Row-orient storage Database engine Log-structure -> ex: LSM, SSTable, Lucene… page-orient(B tree) -> some RDBMs and NoSQL OLAP(Analytic) data warehouse(ETL) Column-orient storage bitmap encoding run-length encoding Column Families(Cassandra) 今天這篇主要要談論的是 OLAP 的部分 OLTP vs OLAP 兩者比較的關鍵是 事務處理(Transaction)還是分析(Analytic)? OLTP(OnLine Transaction Processing) 以往來說,資料庫交互都圍繞在商業交易這類跟錢相關的交易(commercial transcation),當應用拓展到不同領域後,漸漸已經跟錢無關,最後就剩下保留 交易/事務(transcation) 這個術語與概念,用於描述一組讀寫操作的邏輯單元 使用上,應用程式會需要透過索引(index)的方式查找某個鍵值對應的少量資料,依據 user 的 input(insert, update, delete)來更新紀錄 這種交互式的方式關心的是能否快速的回應 user 的 query 或 insert,在大量負載時能降低操作時的延遲,所以 disk search time 會是瓶頸,而 OLTP 應付的資料量相對於 OLAP 來說更少,也比較關心的是即時的資料....

<span title='2023-03-03 00:49:13 +0800 +0800'>March 3, 2023</span>&nbsp;·&nbsp;2 min&nbsp;·&nbsp;352 words&nbsp;·&nbsp;Madi

[閱讀筆記] Design Data-Intensive Application - Storage and Retrieval (OLTP)

前言 本篇繼續探討 Design Data-Intensive Application 這本書的第三章:Storage and Retrieval 簡單整理一下本小節主要談論的架構: OLTP(Transaction) Row-orient storage Database engine Log-structure -> ex: LSM, SSTable, Lucene… page-orient(B tree) -> some RDBMs and NoSQL OLAP(Analytic) data warehouse(ETL) Column-orient storage bitmap encoding run-length encoding Column Families(Cassandra) 今天這篇主要要談論的是 OLTP 的部分,以 index structure 的設計為主題 Database storage engine 書中從被應用至 RDBMs 和 NoSQL 底層的 database storage engine 談起 Log-structured 許多資料庫都會有內部的日誌(log),本身是一個 append-only 的文件,用於描述應用程式正在發生的事情的紀錄,或許是二進位制的,因為本來就不是設計給人類看的.但當紀錄變多時,查詢時間會很久,所以為了加速搜尋,就需要有額外的結構來輔助我們,這個 additional structure 就是 index 但為了維護這個額外的結構,會多多少少的影響到寫入的速度,因為每增加一筆資料都要更新 index,正因如此,資料庫預設都不會加上 index,而是交給程式開發者或是 DBA 來設計該用什麼樣的 index 來增快查詢,避免額外的開銷...

<span title='2023-03-03 00:49:13 +0800 +0800'>March 3, 2023</span>&nbsp;·&nbsp;2 min&nbsp;·&nbsp;361 words&nbsp;·&nbsp;Madi

JWT & SendGrid - 實作電商忘記密碼

前言 前陣子參與一個電商的開發案,參考一些開源專案的設計,包含火紅的 Shopify 替代方案-Medusa,研究完後大致了解該怎麼實作和設計一系列跟密碼重設、忘記密碼、註冊登入…等電商功能,所以就有了此篇文章來紀錄一下過程,實作內容是 Medusa 的原始碼,會以一個 high-level 的設計來闡述設計的流程與該注意的事項 以使用者觀點來看忘記密碼/重設密碼這件事 一般來說,我們在用任何有登入、註冊相關的網站,都會有「忘記密碼」的按鈕,但實際上網站後台的資料庫並不會存我們密碼的明碼(理論上都不應該 QQ),所以當按下忘記密碼後,我們會收到一個電子信箱,裡頭並不會原封不動地將我們的密碼傳回來,因為該網站的資料庫存的是 hashed 過後的密碼,而 hash 是無法被逆向回推的,所以這時候信件裡應該是一組 url,點擊後會跳轉到該網站寫好的重設密碼的頁面,讓該使用者輸入密碼與確認密碼,以便重新設定一組新密碼. 例如下圖的 email 截圖,圖片來源: https://designmodo.com/reset-password-emails/ 以上就是一般使用者的操作流程,這些流程大家都再熟悉不過,但背後的系統流程是怎麼運做的呢? 簡述設計流程 既然要收發信件,肯定需要有寄信服務,寄送信件的服務有很多種,最常見的就是SendGrid,我在實作中有註冊一組帳號來取得發送 email 的 token,但後來開發上有受到一些阻礙與問題,最終改用 這篇文章 和 這篇文章 提到的 GCP 支援的 SendGrid Email API 免費方案來完成寄信功能,目前運作起來一切正常 有了寄信服務之後,接下來要解決的是怎麼確保重設密碼的人就是該帳號的擁有者,避免中間過程被盜取身份,竄改該使用者的密碼? 這個問題是最關鍵的,也就是身份認證的資安議題 一般來說,身份認證(Authentication)肯定會需要 DB 來儲存該 user 的個人資料與帳號密碼,因此實作中我使用 PostgreSQL 作為 DB 的選用,而現今認證機制大多使用 JWT,好處是省去 server 再拿 session id 撈一次資料庫的成本,直接用 base64 將 payload 內容 decode,拿到其中就算公開也沒差的無隱私資料,例如:user id,接著服務當場拿該 user id 去問 DB 該 user 的資料,當然也會帶著 JWT token 去詢問,此時 JWT 的第三部分(signature)的 secret 就是判斷該 token 是否有被篡改的依據,若成功驗證,就能成功取得該 user 的資料,完成身份認證(Authentication)甚至授權(Authorization)的流程...

<span title='2023-02-27 00:49:13 +0800 +0800'>February 27, 2023</span>&nbsp;·&nbsp;5 min&nbsp;·&nbsp;923 words&nbsp;·&nbsp;Madi

React - useEffect cleanup with fetch abort

前言 前陣子在公司開發一個搜尋網站,參考第三方開源專案 searchkit 的設計架構,嘗試使用 GraphQL 搭配 Elasticsearch 來透過一次 request 獲取大量 resource 的搜尋資料,前端則使用 React 搭建 SPA 網頁,但在使用頁籤跳頁時卻出現 React 的警告: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function. 大概知道是 useEffect 要 cleanup 的問題,但卻不知道 callback funtion 該怎麼做,debug 了好一陣子也未果,後來因緣際會下看到幾篇技術文章才恍然大悟,原來 fetch 就有 abort 可以處理,因此簡單以 pagination 的情境來重現上述問題,順手作個紀錄 重現問題 為了重現當初遇到的問題,找了 jsonplaceholder 上的 open data,來做一個文章(posts) pagination 的 demo...

<span title='2023-02-21 09:32:04 +0800 +0800'>February 21, 2023</span>&nbsp;·&nbsp;4 min&nbsp;·&nbsp;745 words&nbsp;·&nbsp;Madi

Node.js - Socket.io 實作多人聊天室

前言 前幾天研究了一下 Client Pull 和 Server Push 的幾種方式,其中屬於 Server Push 的 SSE(Server Send Event)已經在之前的文章 資料實時更新的方式 - Client Pull vs Server Push 中實作過,這次來研究另一種 Server Push 的方式,同時也是較常聽到的 WebSocket,來研究看看如何實作一個簡單的多人聊天室 簡介 Socket.io 因為待會 demo 的前後端會使用 Socket.io 套件來實作,所以開始前先來介紹一下 Socket.io 這個套件 (以下內容整理自官網介紹) Socket.IO is a library that enables low-latency, bidirectional and event-based communication between a client and a server. Socket.io 也是為了解決網路即時通訊而誕生,但是他並不像 WebSocket 一樣屬於通用協定,而是將底層 WebSocket 抽象化的 JavaScript Library(包含前端與後端的 npm 套件),所以 Socket.io 是建於 WebSocket 之上,有自己定義的溝通格式。 Socket.IO is NOT a WebSocket implementation....

<span title='2023-02-10 00:49:13 +0800 +0800'>February 10, 2023</span>&nbsp;·&nbsp;3 min&nbsp;·&nbsp;585 words&nbsp;·&nbsp;Madi