2021 iThome 鐵人賽 MongoDB披荊斬棘之路


DAY4 MongoDB 資料庫與 Collection

Database

MongoDB 一個 instance 中可以有很多資料庫,預設的有三個,admin, config, local。當我們連進 MongoDB 後,輸入 show dbs 就可以看到這三個,這三個分別有其用處。

  • admin:
    看這個名字可以想見這個資料庫很重要,對的,所有的重要資訊、重要指令都只能在這個資料庫底下操作。例如要新增角色或者關閉 instance,相當於所有資料庫的 administrator 一般。

    如果要建立個別資料庫的使用者或角色,在各別的資料庫建立即可,但如果想要跨資料庫,則需要在這裡建立,這樣會自動繼承到其他資料庫。

  • config:
    此資料庫主要是存放 sharding 相關的資訊。在 3.6 版後,開始存放 standalone 或 replication 的資料,也有跟 transaction 相關的資料,但無論如何是禁止去針對這個資料庫進行修改或刪除的,僅有查看可以。

  • local:
    用來存放這個 instance,在這台機器的檔案與資訊,不會因為 replica set 的設定而把相關資料複製走,簡單來說就是別人用不到的資訊。連進去就有一個 startup_log 可以查看。

建立資料庫

建立資料庫並不需要特別宣告,直接 use 即可,以下為範例:

1
2
3
4
5
6
test> show dbs
admin 41 kB
config 111 kB
local 73.7 kB
test> use testUsedDatabase
switched to db testUsedDatabase

直接使用 use testUsedDatabase 就會切換到當下資料庫。

閱讀全文 »

2021 iThome 鐵人賽 MongoDB披荊斬棘之路


DAY3 MongoDB 連線與 IDE

MongoDB 的連線方式主要有三種,分別是:

  • legacy mongo shell
  • mongo shell
  • IDE

學習以及開發階段,我會比較推薦使用 legacy mongo shell 搭配 IDE 的方式,不過這只是建議並非絕對。主要是 mongo shell 固然強大,但需要額外下載才能使用,一旦遇上沒有 mongo shell 的環境,在反應上可能會略差一點,尤其是線上產品的支援環境不見得會有,有的話那就萬幸了。

legacy mongo shell

這邊說的 legacy mongo shell 執行檔就是 5.0 之前的版本,也就是安裝好 MongoDB 內建的版本。會推薦的原因是少了 intellisense (是缺點也是優點),因此使用上會對指令記憶度最高,且不受環境影響,有安裝 MongoDB 的,肯定也會有這套。

如果使用 docker,那還真的是本機不見得會有呢(馬上打臉上面),解決方案就是連進 container 使用,docker exec -it mongo bash,還是有 mongo 可以使用的啦!

連線方法

閱讀全文 »

2021 iThome 鐵人賽 MongoDB披荊斬棘之路


DAY2 安裝與使用 MongoDB

MongoDB 在社群, 非營利環境使用是免費的,而我一律推薦使用 docker 來操作,一來省掉一堆平台相容性以及安裝上遇到的問題,二來大家都會是一樣的起始狀態,三來是弄壞了也不用擔心重裝麻煩之類的。所以本篇以下不會介紹到任何os獨有安裝方式,僅使用 docker 而已,如果對 docker 熟稔的朋友就可以直接跳過本篇了。

安裝

Application 安裝模式會因為各種os有所不同,這邊不會一一介紹,有需要的可以直接參考官網 各個平台安裝 MongoDB 方法。我要用的是以 docker 方式來啟動 MongoDB。(開始前請先安裝 docker)

首先直接從 docker hub 拉取最新的映像檔(image)

docker pull mongo:latest

有指定的版本號或 tag 也可以去 docker hub 查看

1
2
3
4
5
6
7
8
➜  / docker pull mongo:latest
latest: Pulling from library/mongo
16ec32c2132b: Already exists
81447d2c233f: Pull complete
Digest: sha256:93ea50c5f15f9814870b3509449d327c5bc4d38f2b17c20acec528472811a723
Status: Downloaded newer image for mongo:latest
docker.io/library/mongo:latest
➜ /
閱讀全文 »

2021 iThome 鐵人賽 MongoDB披荊斬棘之路


DAY1 揭開序幕與 MongoDB 簡介

前言

終於鼓起勇氣要報名 iThome 鐵人賽!
本系列將會陸續介紹與紀錄在使用 MongoDB 的一些心得以及雷區。MongoDB 在 2021 已經是家喻戶曉的資料庫了,網路上教學資源也很多,我會分配多一些內容在中文資源較少的部分,讓大家能夠更容易學習到更多不同面向的 MongoDB,如有錯誤或者問題請不吝指教。

使用環境

我使用的環境是

  • macOS
  • .NET Core
  • Docker

要如何使用會簡單的說明,因為主軸畢竟還是在 MongoDB。

MongoDB 簡介

閱讀全文 »

2021 iThome 鐵人賽 MongoDB披荊斬棘之路


Basic

Advanced


閱讀全文 »

這篇文章會提到關於 Redis cluster 的內容,如果不太清楚還是建議先去了解一下。


今天遇到一個狀況,當我們在使用 redis cluster 時,按照官網的範例通常 key 會是這樣的格式 IAMKEY{SLOT},那如果將 slot 位置改變到 key 中間,算出來的 hash slot 會不同嗎?


實驗開始

Step 1 啟動 Redis

先啟用 redis (看你是要使用 instance 還是 docker)
我比較習慣把常用的服務寫在一個 docker-compose yml 內,這樣每次都能用到全新的,也不用各別一一啟動。

1
2
3
4
5
6
7
8
9
version: "3.7"
services:
redis:
image: redis
container_name: redis-testdc
ports:
- "16377:6379"
environment:
PASSWORD: pass.123

Step 2 連上 redis

閱讀全文 »

本篇資料庫的資料依舊使用上一篇文章的範例,沒有的可以新增一下。

1
2
3
4
5
6
7
db.getCollection('movie').insertMany([
{"name": "movieA", "language": "en-gb", "rating": 8, "totalCost": 30000000, "producer": "companyA"},
{"name": "movieB", "language": "en-gb", "rating": 5, "totalCost": 10000000, "producer": "companyA"},
{"name": "movieC", "language": "zh-tw", "rating": 6, "totalCost": 25000000, "producer": "companyA"},
{"name": "movieD", "language": "zh-tw", "rating": 8, "totalCost": 10000000, "producer": "companyB"},
{"name": "movieE", "language": "zh-tw", "rating": 9, "totalCost": 6000000, "producer": "companyC"},
])

$count

這邊要介紹的 $count 是在 aggregation 階段使用的,跟在 5.0 後 group 內使用的又有點語法不同。

  • Aggregation 版本
1
2
3
4
db.movie.aggregate([
{ $match: { rating: { $gt: 7 } } },
{ $count: "popular_movie" }
])
  • Group 版本 (5.0之前)
1
2
3
4
5
db.movie.aggregate( [
{ $match: { rating: { $gt: 7 } } },
{ $group: { _id: null, rating: { $sum: 1 } } },
{ $project: { _id: 0 } }
] )
  • Group 版本 (5.0之後)
閱讀全文 »

其實 Git 取消使用密碼登入的通知已經發了一年多了,只是我一直選擇性忽略掉它。直到 2021/08/13 它失效那一天,我無法再部署那一天,我才不甘願地去處理這件事。其實不是一件很困難的事情,但還是簡單紀錄下,因為還是花點時間看了一下怎麼調整。


警告訊息長這樣

在使用 Hexo 部署 Git 時候,總是會跳這個警告

1
2
3
4
5
6
7
8
9
10
11
12
13
14
remote: Support for password authentication was removed on August 13, 2021. Please use a personal access token instead.
remote: Please see https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/ for more information.
fatal: unable to access 'https://github.com/myctw/myctw.github.io/': The requested URL returned error: 403
FATAL Something's wrong. Maybe you can find the solution here: http://hexo.io/docs/troubleshooting.html
Error: remote: Support for password authentication was removed on August 13, 2021. Please use a personal access token instead.
remote: Please see https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/ for more information.
fatal: unable to access 'https://github.com/myctw/myctw.github.io/': The requested URL returned error: 403

at ChildProcess.<anonymous> (/Users/mingyi/Documents/blog/node_modules/hexo-util/lib/spawn.js:37:17)
at ChildProcess.emit (events.js:182:13)
at maybeClose (internal/child_process.js:962:16)
at Socket.stream.socket.on (internal/child_process.js:381:11)
at Socket.emit (events.js:182:13)
at Pipe._handle.close (net.js:606:12)

其實第一句就告訴你了,使用密碼驗證的方式要移除了,建議使用 personal access token


Step1 建立 personal access token

  1. Git 右上角個人 Icon 點下去,找到 settings
    alt
  2. 左邊一排設定中找到 Developer settings
    alt
  3. 左邊一排設定中找到 Personal access tokens
  4. 點選 Generate new token
    alt
  5. Note 欄位就是名稱,基本上有個意義、看得出來是幹嘛的就好
  6. Expiration 強烈建議不要改為永久,因為這就不是 token 了,我是設定一個月啦~怕自己忘記這個操作,乾脆頻繁來使用。
  7. 權限部分就看各位的需求自己設定了,我的目的是只有使用 blog,那麼權限就不應該這麼大
    alt
  8. 接著點選 Generate Token 就可以囉!要記得 token 只會顯示一次,也就是現在,之後只能重新產生了喔!所以一定要先複製好。

Step2 修改 MacOS keychain

閱讀全文 »

大家可以想一下什麼情況下會需要使用 memory cache?

我自己的話,一些比較不常變動的設定值,可以放在記憶體內做快取,定期地去讓它失效,再重新拿 database 的值放回快取更新。

這篇介紹的注意事項有一些特定狀況,並不是所有人都會碰到。這樣寫的情境乍看很像對,但測試起來又不太對,我想應該是對於內建方法GetOrCreate有些誤解。

下面這段程式:

  1. 傳入 string key 希望取得 value
  2. 若 key 值為 key1 則回傳 111,若為其他則會發生錯誤,並且回傳預設值 999。這邊是模擬用其他 key 值查詢 cache 時,遇到不可預期的錯誤。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static class MemoryCacheHelper
{
private static readonly IMemoryCache _memoryCache = new MemoryCache(new MemoryCacheOptions());

public static async Task<int> GetCacheValue(string key)
{
return await _memoryCache.GetOrCreateAsync(key, async data =>
{
try
{
// Get kv data from database
if (key == "key1") return await Task.FromResult(111);

throw new Exception("Unexpected error");
}
catch (Exception)
{
// log error
}
return 999;
}
);
}
}

第一個測試中,傳入 key1,預期會收到 111的結果。
第二個測試,傳入 keyX,模擬取值遇到例外狀況,然後回傳預設值。這次錯誤可以先略過,並且回傳預設值,那麼下一次呼叫快取呢?如果發現快取是空的,那麼理所當然又要去資料庫撈一次。

這時候問題就來了,第二次測試的 key 值 keyX 其實已經存在在 memory cache 內了,所以第三個測試,再次傳入 keyX 只會取得 999,但這個 999 並非來自例外狀況的預設回傳值且不再會 reload database 的資料,直到 keyX/999 這組 kv 自然失效(expire)。

實際執行結果..

1
2
3
4
5
6
7
var key1Value = await MemoryCacheHelper.GetCacheValue("key1");
var keyXValue = await MemoryCacheHelper.GetCacheValue("keyX");
var keyXValue_2ndCall = await MemoryCacheHelper.GetCacheValue("keyX");

Console.WriteLine($"key1_value:{key1Value}");
Console.WriteLine($"keyX_value:{keyXValue}");
Console.WriteLine($"keyX_Value_2ndCall:{keyXValue_2ndCall}");
閱讀全文 »

這篇想來記錄一下 Redis expire 相關指令的用法與意義,有時候時間一長就忘了,自我救助金魚腦。比較深入的 TTL 機制就放到後面再說..

EXPIRE

  • 精確度為 Second(秒級)
  • 替 key 設定存活時間,設定後就無法更改。此失效時間為 TTL (Time to live),單位是秒,也就是還能存活幾秒的意思
  • 可以使用 persist 指令移除失效時間
  • 官方宣稱 2.6 版後的誤差會在 1 ms 內,但我想還是要看當時的忙碌程度。
  • 回傳 1,表示設定成功
  • 回傳 0,表示該 key 不存在

相關指令:

  • TTL (查詢剩餘存活時間)
  • PEXPIRE (精確度為 Millisecond)

EXPIREAT

  • 精確度為 Second(秒級)
  • 替 key 設定失效時間,設定後就無法更改。此時間為 Unix timestamp,時間到了通常會在1秒內被刪除

相關指令:

  • EXPIRETIME (查詢剩餘存活時間)
  • PEXPIRETIME (精確度為 Millisecond)
1
2
3
4
5
6
7
redis> SET key1 value1
"OK"
redis> EXPIREAT key1 1627885364
(integer) 1
redis> EXPIREAT key1 1627885364
(integer) 0
redis>
閱讀全文 »