0%

前言

AWS lambda 作為 serverless 服務,之前有介紹過 AWS Lambda 初體驗 by .net core,本次要介紹 serverless 框架搭配 AWS CloudFormation (IaC)

Serverless 預設使用 provider 是 AWS

AWS is the default cloud provider used by Serverless Framework.

建立第一個 serverless

本次案例我們利用 serverless cli 建立 dotnet template,利用 nqm 安裝

1
npm install -g serverless

安裝完後建立一個 dotnet core serverless project

1
serverless create -t aws-csharp -n dotnetServerless

本次使用參數說明

Read more »

前言

AutoVacuum 在 Postgresql 是一個很重要的機制(甚至可以說最重要也不為過),但裡面有些地方需要了解今天就帶大家初探

資料 & 測試資料資訊

本次執行 Sample Data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
CREATE TABLE T1 (
ID INT NOT NULL PRIMARY KEY,
val INT NOT NULL,
col1 UUID NOT NULL,
col2 UUID NOT NULL,
col3 UUID NOT NULL,
col4 UUID NOT NULL,
col5 UUID NOT NULL,
col6 UUID NOT NULL
);


INSERT INTO T1
SELECT i,
RANDOM() * 1000000,
md5(random()::text || clock_timestamp()::text)::uuid,
md5(random()::text || clock_timestamp()::text)::uuid,
md5(random()::text || clock_timestamp()::text)::uuid,
md5(random()::text || clock_timestamp()::text)::uuid,
md5(random()::text || clock_timestamp()::text)::uuid,
md5(random()::text || clock_timestamp()::text)::uuid
FROM generate_series(1,20000000) i;


CREATE TABLE T2 (
ID INT NOT NULL PRIMARY KEY,
val INT NOT NULL,
col1 UUID NOT NULL,
col2 UUID NOT NULL,
col3 UUID NOT NULL,
col4 UUID NOT NULL,
col5 UUID NOT NULL,
col6 UUID NOT NULL
);

INSERT INTO T2
SELECT i,
RANDOM() * 1000000,
md5(random()::text || clock_timestamp()::text)::uuid,
md5(random()::text || clock_timestamp()::text)::uuid,
md5(random()::text || clock_timestamp()::text)::uuid,
md5(random()::text || clock_timestamp()::text)::uuid,
md5(random()::text || clock_timestamp()::text)::uuid,
md5(random()::text || clock_timestamp()::text)::uuid
FROM generate_series(1,1000000) i;

vacuum ANALYZE T1;
vacuum ANALYZE T2;

查詢 sample code

1
2
3
4
5
EXPLAIN (ANALYZE,TIMING ON,BUFFERS ON)
SELECT t1.*
FROM T1
INNER JOIN T2 ON t1.id = t2.id
WHERE t1.id < 1000000

此次查詢如期走 Merge Join

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
"Gather  (cost=1016.37..30569.85 rows=53968 width=104) (actual time=0.278..837.297 rows=999999 loops=1)"
" Workers Planned: 2"
" Workers Launched: 2"
" Buffers: shared hit=38273 read=21841"
" -> Merge Join (cost=16.37..24173.05 rows=22487 width=104) (actual time=11.993..662.770 rows=333333 loops=3)"
" Merge Cond: (t2.id = t1.id)"
" Buffers: shared hit=38273 read=21841"
" -> Parallel Index Only Scan using t2_pkey on t2 (cost=0.42..20147.09 rows=416667 width=4) (actual time=0.041..69.947 rows=333333 loops=3)"
" Heap Fetches: 0"
" Buffers: shared hit=6 read=2732"
" -> Index Scan using t1_pkey on t1 (cost=0.44..48427.24 rows=1079360 width=104) (actual time=0.041..329.874 rows=999819 loops=3)"
" Index Cond: (id < 1000000)"
" Buffers: shared hit=38267 read=19109"
"Planning:"
" Buffers: shared hit=4 read=8"
"Planning Time: 0.228 ms"
"Execution Time: 906.760 ms"

假如更新如多資料,但未觸發臨界值

Read more »

前言

在巨量資料下,資料庫合理的分片(DB sharding)可以幫助我們承受更高量的資料量(前提Index還有設定都調教到很好在考慮 sharding)

而在 Redis 世界裡也有 redis cluster 來做 sharding 事情,今天就來跟大家分享介紹

我使用是 bitnami redis-cluster 這個 Image 來做這次 Poc

此案例是 3 master - 3 slave Redis server 範例

建立 Redis Cluster

How to Use

1
docker-compose up -d

跑完之後就會出現 6 台 Redis Container,如下表

1
2
3
4
5
6
7
8
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1a0c740cbb96 bitnami/redis-cluster:6.2 "/opt/bitnami/script…" 31 seconds ago Up 27 seconds 0.0.0.0:8105->6379/tcp, :::8105->6379/tcp rediscluster_redis-node-5_1
1651a81a286f bitnami/redis-cluster:6.2 "/opt/bitnami/script…" 37 seconds ago Up 30 seconds 0.0.0.0:8102->6379/tcp, :::8102->6379/tcp rediscluster_redis-node-2_1
5d93edfc55e6 bitnami/redis-cluster:6.2 "/opt/bitnami/script…" 37 seconds ago Up 31 seconds 0.0.0.0:8104->6379/tcp, :::8104->6379/tcp rediscluster_redis-node-4_1
8ab5bbbb7364 bitnami/redis-cluster:6.2 "/opt/bitnami/script…" 37 seconds ago Up 29 seconds 0.0.0.0:8103->6379/tcp, :::8103->6379/tcp rediscluster_redis-node-3_1
8edf90bed3fb bitnami/redis-cluster:6.2 "/opt/bitnami/script…" 37 seconds ago Up 29 seconds 0.0.0.0:8101->6379/tcp, :::8101->6379/tcp rediscluster_redis-node-1_1
e11ac0ec56aa bitnami/redis-cluster:6.2 "/opt/bitnami/script…" 37 seconds ago Up 30 seconds 0.0.0.0:8100->6379/tcp, :::8100->6379/tcp rediscluster_redis-node-0_1
Read more »

前言

當一個專案越來越大,在開發新產品時同時要兼顧程式碼品質會越來越困難,今天要介紹的 Ndepend 是一個很優秀靜態分析 .Net 專案好物

會幫我們產生一個 DashBoard 來了解目前專案大致上分析後的問題,並提供建議解法和處理方向,讓我們提前更快速抓出未來或目前存在 bug,減少發生需要晚上起來 support 機率,讓客戶,老闆,工程師都開心的三大歡喜

另外我們也可以透過 Ndepend 來撰寫我們自己 Code Rule 並在 CI/CD 流程中進行靜態掃描,讓我們出產軟體更有品質

本文我使用我自己的開源專案 ElectronicInvoice_TW 來當作分析案例

建立 Ndepend 開始分析

安裝完 Ndepend 後我們可以在 virtual studio 上面的[延伸模組] 出現建立 Ndepend 項目,一開始我們利用 Attach New Ndepend Project to Current VS Solution ,來建立分析項目

NDepend 分析完程式後我們會在 sln 檔同級目錄下看到一個 NDependOut 資料夾跟 .ndproj 檔案

  • .ndproj 是 XML 格式儲存的專案檔,內容包含 NDepend 專案資訊及分析設定資訊
  • NDependOut 資料夾中會有一個 .ndar 檔案這次一個二進制格式儲存的分析後結果
  • NDependOut 中有一個 NDependReport.html 是一個分析後 Html 報表
Read more »

前言

在 Postgresql 世界裡每建立一個 Connection,都會有一個 process 來服務該請求,Postgresql 沒有 ThreadPool 概念所以在 Connection 使用量大時會發生一些問題

  • 資源浪費
  • 超過同時間超過 max_connection 後面連接會無法連接

一個 open source 插件 PgBouncer 就是幫我們解決上面問題,不過如果你是使用 AWS RDS 來當作 DB 就很適合使用 RDS Proxy

本次使用免費帳號範圍提供的機器 db.t2.micro

另外因為 RDS Proxy 在 EC2 內網才能連接,所以我也利用免費帳號準備一台 EC2 並安裝 pgbench 進行壓力測試

壓測前準備 & 說明

我把 max_connections 最大連接數量調整成 550

Read more »

前言

資料結構跟演算法是程式設計師的內功,在中小型系統懂這兩樣東西效用可能有限,但在大型系統中熟不熟用資料結構跟演算法做出來的效益會天差地遠

對於常使用的物件和變數我們會放置在 Redis 上( cache server ),但記憶體有限,我們想放的東西無限,造就無法將所有物件都存放在 Redis 或 Server Memory 上.

假如你有設定過 Redis config 你會看到一個 property maxmemory_policy 來管理如何淘汰,記憶體中的物件

  • volatile-lru
  • allkeys-lru

上面有個名稱 LRU (Least Recently Used Cache) 代表甚麼意涵呢?稍後會跟大家做解釋

Github Sample Project

LRU 算法概念

LRU (Least Recently Used Cache) 顧名思義,會記憶體不夠用時優先保留最近常使用的 Cache 資料,並剔除最舊的資料來緩解壓力

這個算法策略可以確保 Hot Data 在記憶體不足時不會被刪除

Read more »

前文

我認為 DB query optimizer (QO) 產生執行計畫並執行查詢和 使用地圖找尋最佳路徑很類似

下面會跟大家分享我心中 地圖理論 希望可以對於想了解 DB 運作的人更快上手

看見全貌

在了解一個事情跟技術,我們需要先用宏觀的角度來看待事情

下圖是 postgresql DB 運作核心概念圖

其中在執行語法前後最重要的幾個步驟是

  1. Parser:檢查語法是否有錯誤,如果錯誤就不執行後續步驟
  2. ReWriter:嘗試優化改寫 SQL
  3. Planner:利用統計資訊 & 演算法建立執行計畫
  4. Executor:挑選一個成本最低的執行計劃來查找資料

我認為資料 Search Engine 的 Planner & Executor 核心概念跟查找地圖( google map 很類似 )

Read more »

前言

我之前有寫透過 lock or CAS 來防治,Racing condition 問題,但如果這個問題延深到多台服務器甚至是 micor-services 架構我們要怎麼處理資料問題呢?

下面程式在單體服務或應用程式不會出問題,但如果服務器有多台問題可就大了,因為下面的 lock 只限於單體 Server 上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private readonly static object _lock = new object();
[HttpGet()]
public string Get()
{
int remainCount;
lock (_lock)
{

remainCount = (int)RedisConnection.GetDatabase().StringGet(_productId);
if (remainCount > 0)
{
RedisConnection.GetDatabase().StringSet(_productId, --remainCount);
}
}

string productMsg = remainCount <= 0 ? "沒貨了賣完了" : $"還剩下 {remainCount} 商品";
string result = $"{Dns.GetHostName()} 處理貨物狀態!! {productMsg}";
_logger.LogInformation(result);
return result;
}

如果有聽過 Redis 可能就會聽過 RedLock.net 來處理,但您知道 RedLock.net 底層大致上怎麼實作的嗎?

本篇文章會帶領大家透過 distlock 算法時做出,自己的Redlock

本篇只介紹核心概念,細部防錯我沒有寫出來,所以建議本篇程式不要用在 prod 環境

我使用 docker-compose 建立問題架構,架構圖如下

原始碼位置 Redlock-Csharp

Read more »

前言

執行計畫代表此次查詢要怎麼樣的演算法查詢我們的資料,而成本是決定使用哪個執行計畫的重要因素

在 postgreSQL DB query optimizer 會選擇成本最低的執行計劃,當作查詢資料使用算法

在 Sql-sevrer 成本計算封裝在程式內部,我們無法透過一些因子來調整,但 postgreSQL 可以

我認為 query optimizer 判斷成本概念有點類似 google map 在找尋最佳路徑

我對於資料庫有定義一個,地圖理論來說明 RDBMS 執行計畫相關的事情

本篇成本因子效能調教會涉 Linux kernel systemtap ,國中數學,postgreSQL 運作模型,篇幅可能會有點多且複雜

但我認為本篇學會可以對於 query optimizer 有更進一步了解

預設成本因子潛在問題

下面我使用一個例子來

Read more »

前言

AWS 在有眾多服務,其中我對於 Lambda 最有興趣 (因為 .net 有一個 Lambda 表達式 )

最近申辦帳號可以使用 12 個月部分免費服務(有條件限制),看我還不玩爆 AWS XD

經過了解得知 Lambda 是一個 EDA 架構並幫我們解決開發時需要煩惱硬體上配置(記憶體要多少,CPU,是否需要 load balance scale out…),做一個 serverless 服務

讓我們可以專心開發程式,本篇會針對 .net core 建立一個 sample 專案到上傳到 AWS Lambda 服務上說明

安裝aws cli & 設定 profile

首先我們需要先安裝 aws cli,如果是 windows 我們可以透過 powershell,來完成

1
C:\> msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi
1
2
$ aws --version
aws-cli/2.2.44 Python/3.8.8 Windows/10 exe/AMD64 prompt/off

確定安裝完後我們可以執行 aws configure 設定我們 AWS 服務相關 IAM 資訊

Read more »