我需要生成一个独特的用户友好代码并将其保存到 Redis 中,直到受邀用户对其进行评分或过期。 由于代码必须用户友好,我决定使用 6 位数字,前端会将其分成两组,例如xxx-xxx.
现在,在后端,我有 NodeJS 和 node_redis。 这就是我生成随机字符串并将其保存到 Redis 中的方式:
var invCode = Math.floor(Math.random() * 90000) + 100000;
var key = "invitation-code:" + invCode;
const TTL = 3 * 24 * 60 * 60; // 3 days
redis.client.existsAsync(key)
.then(res => {
if (!res) {
// ok, I can add the key, value pair
return redis.client.setAsync(key, value, 'EX', TTL);
} else {
// I have to generate new key and check it again
// how can I re-iterate the process???
return null;
}
})
.then(res => {
logger.info('InvitationCodeController::generate added <' + key + ', ' + value + '> pair');
})
.catch(error => {
logger.error('InvitationCodeController::generate Error ' + error);
});
现在,我想不通的一点是——如果生成的代码已经存在,我该如何重新迭代这个过程,即生成另一个随机字符串、格式化它、 checkin Redis 等等。 由于我有异步调用,我认为任何类型的循环都不适合我?
有什么想法吗?
最佳答案
您可以使用如下所示的“尝试”过程。
您也可以通过删除 --n
部分来类似地创建一个 while 循环。
此外,我认为您应该为“SETNX”使用“NX”参数——当值不存在时设置。否则有可能在你检查redis的key是否存在的时间和你实际设置它的时间之间,你可以覆盖一些其他的key。此时您甚至可以重写它,因此依赖于 SETNX 在设置失败时抛出错误,而不是每次都检查值。
const process = require('process');
const redis = require("redis");
const Bluebird = require('bluebird')
Bluebird.promisifyAll(redis.RedisClient.prototype)
Bluebird.promisifyAll(redis.Multi.prototype)
const winston = require('winston');
const logger = winston.createLogger({
level: 'silly',
format: winston.format.json(),
transports: [new winston.transports.Console({
format: winston.format.simple()
})]
});
const client = redis.createClient({
host:'redis-19141.c16.us-east-1-3.ec2.cloud.redislabs.com',
port:'19141'
});
client.auth('I6C2ISvac4suTbxSYcbsjWiz635NK8Wv');
// client.set("string key", "string val", redis.print);
var invCode = Math.floor(Math.random() * 90000) + 100000;
// test invCode being the same --- retry.
invCode = 111111;
var key = "invitation-code:" + invCode;
const TTL = 3 * 24 * 60 * 60; // 3 days
let value = "test";
const trySet = function(key,n){
const used = process.memoryUsage().heapUsed / 1024 / 1024;
logger.info(`The script uses approximately ${Math.round(used * 100) / 100} MB`);
return client.existsAsync(key)
.then(res => {
logger.info("existsAsync res",res);
if (!res) {
logger.info("Key does not exist!");
return client.setAsync(key, value, 'NX','EX', TTL)
.then(res => {
logger.info('InvitationCodeController::generate added <' + key + ', ' + value + '> pair');
return true;
})
} else {
logger.info("Key already exists!");
if(n > 0){
return trySet(key,--n);
}else{
return false;
}
}
})
.catch(error => {
logger.error('InvitationCodeController::generate Error ' + error);
return false;
});
}
trySet(key,50).then(function(res){
if(res){
logger.info('trySet::success');
}else{
logger.info('trySet::failed');
}
}).catch(error => {
logger.error('trySet::error');
});
关于javascript - 如何保证邀请码在Redis中是唯一的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51966660/