POABOB

小小工程師的筆記分享

0%

URL Shortener - 自增id亂數產生ShortId

一、前言

由於上一篇實作URL Shortener雖然在效能上有不錯的效果,可是當我們使用自增id順序的方式導致ShortId容易被眼尖的資安人員(or駭客)發現是有跡可循的,一來觀感不太好,二來容易預測導致被惡意使用。
那麼我們要如何在不改變現有的架構下,完美的解決這個問題呢?
於是我想到,如果在資料表中,id已經被生成好,但是欄位值是空的狀態下,是不是就可以搜尋特定範圍的空值,以更新的方式來代替插入?

二、改善方法

  1. 新增 url_random 表預先插滿1,074,000,000筆空值資料,並且準備額外計數表(url_random_nums)來COUNT()非空值數量

    • 因為我們使用64進位的方式產生5位數字串,所以1,074,000,000筆剛好滿足我們這五位數的需求

    • 準備額外表是因為Innodb不會把表的列數額外儲存,所以如果要COUNT()表會導致花費很多時間,所以才額外建立一個表

  2. 開啟服務前固定時間,判斷 url_random_nums 的值為多少,並且以固定單位來迴圈計算總共多少筆

    • 在開啟服務後,如果Client端第一筆新增資料發現沒有計算總共多少列,那麼他就要額外等待一段時間的操作,所以建議先在開啟服務前先操作

    • 固定時間使用Cronjob的方式,每天一次以迴圈的方式來去COUNT url_random 中url是空的值,計算完成後跳出迴圈,更新Mysql url_random_nums,更新Redis

  3. 使用Math.random()亂數隨機抽取一筆資料並更新(手法類似步驟2)

    • 我預設以10000為單位,如果url空值總筆數介於1 ~ 10000之間,就使用Math.random() * 10000 = randomId,再以’WHERE id >= randomId LIMIT 1’的方式,來隨機搜尋一筆在url為空值的id,並且更新它

    • 如果更新成功,Redis中筆數 + 1,並更新時間戳

    • 如果更新失敗,那就代表id >= randomId的值都滿了,改成使用id < randomId,最後Redis中筆數 + 1,並更新時間戳

三、實作

1. 新增 url_random 表預先插滿1,074,000,000筆空值資料,並且準備額外計數表(url_random_nums)來COUNT非空值數量

  1. 建立一個Table叫做 url_random 來實現我們亂數ShortId的提案
1
2
MariaDB [shortURL]> CREATE TABLE `shortURL`.`url_random` (`id` int(11) NOT NULL AUTO_INCREMENT,`url` text NOT NULL DEFAULT '0', `expireAt` int(11) NOT NULL DEFAULT 0, PRIMARY KEY (`id`), KEY `url` (`url`(1024))) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.120 sec)
  1. 建立一個 url_random_nums 紀錄 url_random 中url不為’0’的欄位數

    • 使用’0’是因為用NULL在搜尋的時候會對Mysql造成額位的負擔
1
2
3
MariaDB [shortURL]> CREATE TABLE `shortURL`.`url_random_nums` (`id` int(11) NOT NULL AUTO_INCREMENT,`urlNums` int(11) UNSIGNED NOT NULL,  PRIMARY KEY (`id`)) ENGINE=Inno
DB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.165 sec)
  1. 插入一筆總數為0的值至 url_random_nums
1
2
3
4
5
6
7
8
9
10
MariaDB [shortURL]> INSERT INTO `url_random_nums`(urlNums) VALUES (0);
Query OK, 1 row affected (0.057 sec)

MariaDB [shortURL]> select * from url_random_nums;
+----+---------+
| id | urlNums |
+----+---------+
| 1 | 0 |
+----+---------+
1 row in set (0.001 sec)
  1. url_random 資料表插滿1,074,000,000筆資料,剛好把64 ^ 5次方的額度用滿(大概花費 4.4hrs)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const mysql = require('../db/mysql');

//每次插入3000筆
const insert = async () => {
const values = [
['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],
['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],
['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],
['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],
['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],
['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],['0', 0],
];
const sql = "INSERT INTO url_random (url, expireAt) VALUES ?";
const Start = Date.now()
for(let i = 0; i < 358000; i++ ) {
await mysql.exec(sql, [values])
console.log(`${(i+1) * 3000} rows inserted...`);
}
const End = Date.now()
console.log(`Start at ${Start}, End at ${End}/, Total time: ${(End - Start) / 1000} seconds...`)
}

src/model/index.js

1
2
3
4
5
6
7
8
9
PS C:\Users\poabob\Desktop\Dcard\src\model> node .\index.js
3000 rows inserted...
.
.
.
1073994000 rows inserted...
1073997000 rows inserted...
1074000000 rows inserted...
Start at 1648244701597, End at 1648260709265, Total time: 16007.668 seconds...

2. 在開啟服務前固定時間,判斷 url_random_nums 的值為多少,並且以固定單位來迴圈計算總共多少筆

  1. 直接先找找看Redis中有無值

  2. 有且未過期,那就直接關閉

  3. 沒有或過期

    1. 先判斷Mysql中 url_random_nums 總共記錄多少筆總數

    2. 設定大小區間,我使用100萬當作一個固定範圍

      • Ex. 假設目前總數有5000筆,那麼COUNT的範圍就是1~100萬

      • Ex. 假設目前總數為100萬又5000筆,那麼COUNT的範圍就是1000001~200萬

    3. 利用迴圈搜尋Mysql中 url_random 來累計

      • 如果剛好該範圍內的總數剛好等於100萬,那就區間上下限各自加100萬,往下一個區間去COUNT(),直到結果<100萬才會break
    4. 迴圈停止後,更新Mysql中 url_random_nums 的總數

    5. 更新Redis中的key url_random_nums,資料構造為 { urlNums: count, expireAt: Math.floor(Date.now() / 1000) + 12 * 60 * 60 }

      • urlNums:是總數

      • expireAt:為了避免程式短時間開關一直計算總數,所以設定12小時候再度執行才會更新到Mysql中(cronjob也是)

src/model/index.js

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
const { get, set } = require('../db/redis');
const { ErrorModel, BaseModel } = require('../utils/response');
const { HOST_CONF } = require('../config/url');
const { getURL, insertURL, getRandomURL, insertRandomURL} = require('../model/index');
const { validateUrl, validateExpire, convertIdToShortId, convertShortIdToId } = require("../utils/url");
const { datetimeRegex } = require("../utils/const");

//開啟服務或cronjob時,COUNT資料
const selectCountForeach = async () => {
try {
const Start = Date.now()
let count = 0;
let TotalTime;
//先判斷Redis有多少rows和是不是最近幾分鐘更新的
let result = await get('url_random_nums');

//如果get沒有或超過12小時沒更新
if(result === null || !validateExpire(result['expireAt'])) {
console.log(`result is null or reslut is expired!!!`);
// redis沒有,往mysql找
let sql = `SELECT urlNums FROM url_random_nums WHERE id=1 LIMIT 1;`;
result = await mysql.exec(sql);
result = result[0]['urlNums'];

let idCountMin = parseInt(result / 1000000) * 1000000 + 1
let idCountMax = (parseInt(result / 1000000) + 1) * 1000000

while(true) {
//找尋範圍內
sql = `SELECT COUNT(id) as id FROM url_random WHERE id >= ${idCountMin} AND id <= ${idCountMax} AND url != '0';`;
const nums = await mysql.exec(sql);
nums['id'] = nums[0]['id'];

count += nums['id'];
// 如果滿了 繼續往下100萬筆計算
if(nums['id'] < 1000000) {
break;
}

console.log('loop', count, nums);
idCountMin += 1000000;
idCountMax += 1000000;
}

///更新url_random_nums
sql = `UPDATE url_random_nums SET urlNums=${count} WHERE id = 1;`;
mysql.exec(sql);

//更新Redis urlNums,設定12小時候過期
result = { urlNums: count, expireAt: Math.floor(Date.now() / 1000) + 12 * 60 * 60 }
set('url_random_nums', result)

//關閉連線
mysql.end();
} else {
const End = Date.now()
console.log(result)
TotalTime = ((End - Start) / 1000)
console.log(`Start at ${Start}, End at ${End}/, Normal Total time: ${TotalTime} seconds`)
//關閉連線
quit();
return;
}
} catch(e) {
console.log(`${e.stack}`);
}
}
  • 我把執行檔 count.js 寫在根目錄,並配置npm指令,開啟服務的時候就會執行

package.json

1
2
3
"scripts": {
"dev": "node ./count.js && cross-env NODE_ENV=dev nodemon ./bin/www.js",
},

count.js

1
2
3
//url_random
const { selectCountForeach } = require('./src/model/index');
selectCountForeach();

3. 使用Math.random()亂數隨機抽取一筆資料並更新(手法類似步驟2)

src/model/index.js

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
49
50
51
52
53
54
55
56
57
58
59
60
61
//Random增
const insertRandomURL = async (url, expireAt) => {
try {
const Start = Date.now()
let idInsertMin, idInsertMax, id, TotalTime, sqlReturn;
//先判斷Redis有多少rows和是不是最近幾分鐘更新的
let result = await get('url_random_nums');

//如果Redis沒有
if(result === null) {
//查詢Mysql,返回時並插入Redis
let sql = `SELECT urlNums FROM url_random_nums WHERE id=1 LIMIT 1;`;
result = await mysql.exec(sql);
result = result[0]['urlNums'];
//插入總數到Redis
result = { urlNums: result, expireAt: Math.floor(Date.now() / 1000) + 12 * 60 * 60 };
set('url_random_nums', result);

} else {
//利用result['urlNums'],以1萬為範圍找url為'0'的id
idInsertMin = parseInt(result['urlNums'] / 10000) * 10000 + 1;
idInsertMax = (parseInt(result['urlNums'] / 10000) + 1) * 10000;

//亂數產生搜尋的值
id = parseInt(Math.random() * idInsertMax);

const sql1 = `SELECT id FROM url_random WHERE id >=${id} AND id <=${idInsertMax} AND url='0' LIMIT 1;`;
const sql2 = `SELECT id FROM url_random WHERE id >=${idInsertMin} AND id <=${id} AND url='0' LIMIT 1;`;

sqlReturn = await mysql.exec(sql1);
//如果sql1語句執行失敗,代表介於id~idInsertMax已經沒有空值
if(sqlReturn.length === 0) {
sqlReturn = await mysql.exec(sql2);
//如果sql2語句執行失敗,代表介於idInsertMin~id已經沒有空值,不正常
if(sqlReturn.length === 0) {
console.log(`ERROR CAN\'T GET id`)
return [];
}
}

//獲取id後,更新url和expireAt
const returnId = sqlReturn[0]['id']
sql = `UPDATE url_random SET url='${url}', expireAt=${expireAt} WHERE id = ${returnId};`
sqlReturn = await mysql.exec(sql);

if(sqlReturn['affectedRows'] === 0) {
console.log(`ERROR CAN\'T UPDATE`);
return [];
}

//Redis總數+1
set('url_random_nums', { urlNums: result['urlNums'] + 1, expireAt: Math.floor(Date.now() / 1000) + 12 * 60 * 60 })
const End = Date.now()
TotalTime = ((End - Start) / 1000)
console.log(`Start at ${Start}, End at ${End}/, Random Total time: ${TotalTime} seconds`)
return {id: returnId};
}
} catch(e) {
console.log(`${e.stack}`);
}
};

四、比較

  1. 亂數生成

    • 平均回應時間:54/ms

URL

  1. 順序生成
    • 平均回應時間:17/ms

URL_RANDOM

  1. 結論
  • 雖然順序新增在性能上比亂數還要快3倍,但是也要考慮到順序新增它的欄位數沒有亂數那麼多(100 v.s. 1,074,000,000),所以當表越來越大之後,可能性能表現還會在慢一點點。

  • 還有亂數新增方式不能刪除資料(頂多只能UPDATE url=’0’, expireAt=0),因為如果錯刪了一筆資料,當我們在累計總數的時候就會產生問題,導致可能找不到插入的id。

不過搞了這麼久,其實還有很多方式可以解決,只不過我想在原本這個架構上作延伸,優化我想解決的問題,之後還會有一篇關於nginx限流的部分,做完大致上這個作業應該就完整了。

------ 本文結束 ------