最近發現公司用的公共jar包裏生成惟一主鍵的方法居然用的是當前時間戳,這種方式有明顯弊端,參考了網上各類生成惟一id的方式以後,作下總結。java
1、數據庫自增IDmysql
使用mysql數據庫的自增id,數據庫的自增id的優勢是很是明顯的:第一是速度快,並且是按序自增,檢索很是有利。第二是自增的id都是數字型,佔用空間小,易於程序中排序。 第三是新增記錄時能夠不用指定id,不用擔憂主鍵重複問題。
算法
固然,使用數據庫自增ID也有缺點:第一是手動插入指定ID的記錄時會比較麻煩。第二是當新老系統合併作數據遷移時,新舊系統都是數字型,會致使多個主鍵id衝突,或新舊系統主鍵不一樣是數字型就會致使修改主鍵數據類型。第三若是ID是連續的,惡意用戶的扒取工做就很是容易作了,直接按照順序下載指定URL便可;若是是訂單號就更危險了,競對能夠直接知道咱們一天的單量。因此在一些應用場景下,會須要ID無規則、不規則。sql
2、UUID數據庫
UUID保證對在同一時空中的全部機器都是惟一的。UUID由如下幾部分的組合:
(1)當前日期和時間,UUID的第一個部分與時間有關,若是你在生成一個UUID以後,過幾秒又生成一個UUID,則第一個部分不一樣,其他相同。
(2)時鐘序列。
(3)全局惟一的IEEE機器識別號,若是有網卡,從網卡MAC地址得到,沒有網卡以其餘方式得到。
數組
java中提供了兩個對應的方法:安全
randomUUID() ,適用於生成惟一訂單號。 服務器
nameUUIDFromBytes(byte[] n)會根據n產生惟一的uuid。只要有用戶的惟一性信息。就能保證此用戶的uuid的惟一性。網絡
優勢:性能很是高:本地生成,沒有網絡消耗。app
缺點:第一是不易存儲,UUID太長,16字節128位,一般以36長度的字符串表示,不少場景不適用。第二是信息不安全,基於MAC地址生成UUID的算法可能會形成MAC地址泄露,這個漏洞曾被用於尋找梅麗莎病毒的製做者位置。
下面是UUID及生成8位UUID的java實例:
public class UUIDTest {
public static String[] chars = new String[]
{
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
};
public static void main(String[] args) {
System.out.println(UUID.randomUUID().toString().replace("-", ""));
System.out.println(getShortUuid());
}
public static String getShortUuid() {
StringBuffer stringBuffer = new StringBuffer();
String uuid = UUID.randomUUID().toString().replace("-", "");
for (int i = 0; i < 8; i++) {
String str = uuid.substring(i * 4, i * 4 + 4);
int strInteger = Integer.parseInt(str, 16);
stringBuffer.append(chars[strInteger % 0x3E]);
}
return stringBuffer.toString();
}
}複製代碼
其中生成8位UUID的思路是:將32位UUID按每四位截取,將截取的每組字符串轉換成10進制的數字,而後對0x3E(十進制爲62)取餘,根據取餘獲得的結果找到ASCII字符數組中(總共62個字符)的位置,將每組的結果拼接就獲得一個8位的UUID字符串。
3、SnowFlake雪花算法
雪花ID生成的是一個64位的二進制正整數,而後轉換成10進制的數。64位二進制數由以下部分組成:
優勢
缺點