今天有個業務需求
產生一組六位英文大寫字母的亂號
然後冠上年月
比如 202508GUHJAN

很直覺的就是從26個字母
隨機拿6個出來
然後寫入DB
26的六次方是3億多
應該怎麼樣都不會碰撞

1
2
3
4
5
6
7
8
9
10
11
12
13
public static string GernerateRandomText1(int length)
{
const string letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var random = new Random();
char[] result = new char[length];

for (int i = 0; i < length; i++)
{
result[i] = letters[random.Next(letters.Length)];
}

return new string(result);
}

沒想到測試跑下去
大約兩萬筆資料時
就發生編號重覆的狀況

以為是我臉太黑,運氣不好
再跑了好幾次
沒想到都跑不過4萬
顛覆我對亂數看法
birth-paradox-1.png
birth-paradox-2.png
birth-paradox-3.png
birth-paradox-4.png

問了一下ChatGPT
才知道這個叫做 生日悖論

一年365天
不過其實只要23人
裡面的人生日重覆的機率就就會高於50
嚴格來說不是「悖論」
而是違反人的直覺

我的狀況也是一樣
分母雖然超大
但如果實際上要重覆
其實只要很少的量就可以做到了

難怪需要GUID這種絕對不重複的值
但當初就是嫌GUID太長
才改用亂數字母
沒想到會這麼頻繁的碰撞

不過好在每個月須要產生的亂數不多
不會超過1000筆
加上資料庫有加上唯一索引
失敗的話就重新取一筆即可

下次遇到這種亂數就要特別小心
數量一多
就會遇到生日悖論的陷阱