最近在寫一個(gè)短鏈服務(wù),提供兩個(gè)API給用戶使用,一個(gè)API用于生成短鏈,一個(gè)API用于根據(jù)短鏈獲取長(zhǎng)鏈接。
生成短鏈的實(shí)現(xiàn)原理是把數(shù)據(jù)庫(kù)表的遞增ID根據(jù)規(guī)則轉(zhuǎn)換為4到7個(gè)字母數(shù)字組合。該組合作為長(zhǎng)鏈接的key,利用數(shù)據(jù)庫(kù)的主鍵保證了長(zhǎng)鏈接和key的唯一性。
數(shù)據(jù)庫(kù)主鍵id是十進(jìn)制的數(shù)字。字母數(shù)字的組合加上大小寫字母一共有62位,所以轉(zhuǎn)換規(guī)則就是把10進(jìn)制的ID轉(zhuǎn)換為62進(jìn)制。具體做法就是循環(huán)對(duì)62進(jìn)行取余,每次取余之后都除以62直到等于零。100萬的十進(jìn)制數(shù)會(huì)對(duì)應(yīng)4個(gè)字母數(shù)字組合,1億的十進(jìn)制數(shù)對(duì)應(yīng)5個(gè),100億對(duì)應(yīng)6個(gè),1萬億對(duì)應(yīng)7個(gè),足夠使用了。
具體生成短鏈的過程時(shí)用戶過來一個(gè)請(qǐng)求時(shí),先把保存一條記錄到數(shù)據(jù)庫(kù)中,然后獲取該記錄的ID,進(jìn)行轉(zhuǎn)換,獲取字母數(shù)字組合,再保存到數(shù)據(jù)庫(kù)中。
在測(cè)試的時(shí)候發(fā)現(xiàn)這樣的做法只能支持每秒3個(gè)用戶同時(shí)進(jìn)行訪問,用戶多時(shí)就會(huì)由于在數(shù)據(jù)庫(kù)中給短鏈設(shè)置了唯一索引而報(bào)錯(cuò),因?yàn)橥瑫r(shí)保存了空值到數(shù)據(jù)庫(kù)中。
之后考慮添加事務(wù)進(jìn)行解決,在插入記錄會(huì)出現(xiàn)MySQL error “Deadlock found when trying to get lock; try restartingtransactionn,性能幾乎沒有提升。
最后加入ReentrantLock鎖,在保存數(shù)據(jù)庫(kù)之前加鎖,更新數(shù)據(jù)庫(kù)成功之后進(jìn)行解鎖,性能得到了提升,本機(jī)測(cè)試每秒200個(gè)用戶同時(shí)訪問沒有出現(xiàn)失敗的情況。
參考銜接
https://javadoop.com/post/url-shortener