redis中KEYS和SCAN命令對比
阿新 • • 發佈:2019-01-05
redis中KEYS和SCAN命令對比
根據官方文件所述,KEYS命令時間複雜度是O(N),耗費時間很少,在筆記本上掃描100w個key的資料庫使用了40ms。不推薦在實際生產環境使用KEYS命令,在資料量比較大的情況下執行該命令會有很大的效能損耗,這個命令是用來除錯和其他特殊用途,比如,改變key空間的佈局。在正式應用程式碼裡使用SCAN和sets代替KEYS。
KEYS就是將redis中所有的key與KEYS引數一一匹配,但是這個匹配過程對伺服器效能有很大的損耗。而SCAN則是將所有key分頁處理,每次處理的條數通過引數傳入。處理後返回一個遊標,下次再次請求的時候攜帶該遊標。
下面對KEYS和SCAN的效能和使用方式進行對比。
測試環境:
server:redis_version:5.0.2 執行在docker容器裡,宿主機配置 i7-6700K,IP為192.168.1.160。image: redis:alpine, cpu預設配置可以佔滿一個核,映射出來的埠為6380。
client: ubuntu16.04 程式語言為node.js v10.15.0,依賴庫 redis: 2.8.0,uuid: 3.3.2。
首先我先在redis中插入100w條資料。程式碼如下:
const { v4 } = require('uuid');
const { createClient } = require('redis');
const client = createClient({
host: '192.168.1.160',
port: 6380,
});
const set = (key) => {
return new Promise((resolve, reject) => {
client.set(key, key, (err, reply) => {
if (err)
reject(err);
return resolve();
});
});
};
let uuidList = [];
const run = async () => {
const start = new Date().getTime();
for (let i = 0; i < 100; i++) {
for (let i = 0; i < 10000; i++) {
uuidList.push(v4( ));
}
await Promise.all(uuidList.map(uuid => {
return set(uuid);
}));
uuidList = [];
}
console.log('duration', new Date().getTime() - start);
};
run();
接下來測試KEYS查詢,程式碼如下:
const { createClient } = require('redis');
const client = createClient({
host: '192.168.1.160',
port: 6380,
});
const start = new Date().getTime();
client.keys('*ccccc*', (err, reply) => {
const duration = new Date().getTime() - start;
console.log('duration');
console.log(reply.sort());
});
搜尋到的結果為:
[ '2aaf224c-a31f-4555-8269-ccccc4b68244',
'317c73a2-40ef-4084-a7fa-8c2ccccc8817',
'3ccccc6b-bd15-4cc1-b857-2eb2ee35c147',
'8b4ce8df-17d5-40f5-a44a-86971f9ccccc',
'a8de5fe2-181a-4628-80dc-eccccc613f9f',
'a981dea3-1d9b-4038-a2f6-7ccccc9e88e1',
'd8ccccc5-3c5b-4bf8-b73b-c6c45c8ce41f',
'f137ad17-5b21-43d1-a77c-2eae5cccccdd' ]
平均耗時為:310ms。
接下來測試SCAN查詢,程式碼如下:
const { createClient } = require('redis');
const client = createClient({
host: '192.168.1.160',
port: 6380,
});
const scan = (cursor, keys, count) => {
return new Promise((reslove, reject) => {
client.scan(cursor, 'MATCH', keys, 'COUNT', count, (err, res) => {
if (err) {
reject(err);
}
const [cursor, matched] = res;
return reslove({ cursor, matched });
});
});
};
const run = async () => {
const result = [];
const start = new Date().getTime();
let cursor = 0;
const keys = '*ccccc*';
while (true) {
const { matched, cursor: newCursor } = await scan(cursor, keys, process.argv[2]);
result.push(...matched);
cursor = newCursor;
if (cursor === '0') {
console.log('duration', new Date().getTime() - start);
break;
}
}
console.log(result.sort());
};
run();
COUNT分頁大小與平均耗時:
大小 | 耗時 |
---|---|
1k | 2790ms |
1w | 664ms |