redis中的唯一安全短代码(使用节点)

时间:2014-04-29 01:17:19

标签: javascript node.js asynchronous redis

我让用户使用他们提供的短代码访问网址,例如example.com/ABCD。我正在运行节点并使用node_redis模块,尽管我认为它不重要。生成唯一代码的安全方法是什么?

我可以随机生成一些内容并检查它是否正在使用中,但考虑到我对redis的调用的异步性质,那么它有可能在被保存回redis之前在其他地方使用

一些想法:

  • 我并不担心有限的命名空间,如果需要我可以扩展它但很可能不会
  • ...但是保持代码简短(易于在移动设备上输入)的目标意味着我希望保持名称空间较小,从而增加发生碰撞的可能性。
  • 我想我可以在内存中保留已使用(或未使用的)代码列表,这不是最糟糕的事情,但似乎是一个奇怪的举动。
  • 我知道我可以让redis自动增加,但我不想使用数字(我不想连续)。

如果我不想将列表保留在内存中,我应该切换数据存储吗?我是否认为将列表保留在内存中是正确的但不是很好?

1 个答案:

答案 0 :(得分:1)

请从2013年7月开始查看我的答案:https://stackoverflow.com/a/17597649/1253312

我会将其复制到此处以便妥善保管:


我建议实际使用Redis执行此任务。它具有使该任务适合其使用的所有功能。最重要的是,它非常擅长搜索大值列表。

我们将创建两个列表buffered_idsused_ids。一个cronjob将每5分钟(或你喜欢的任何间隔)运行,这将检查buffered_ids的长度并保持在长度上,例如5000。当您需要使用ID时,请从buffered_ids弹出,然后将其添加到used_ids

Redis有sets,它们是集合中的唯一项目。可以把它想象成一个散列,其中键是唯一的,所有值都是" true"。

你的cronjob,用bash:

log(){ local x=$1 n=2 l=-1;if [ "$2" != "" ];then n=$x;x=$2;fi;while((x));do let l+=1 x/=n;done;echo $l; }
scale=`redis-cli SCARD used_ids`
scale=`log 16 $scale`
scale=$[ scale + 6]
while [ `redis-cli SCARD buffered_ids` -lt 5000 ]; do
    uuid=`cat /dev/urandom | tr -cd "[:alnum:]" | head -c ${1:-$scale}`
    if [ `redis-cli SISMEMBER used_ids $uuid` == 1]; then
        continue
    fi
    redis-cli SADD buffered_ids $uuid
done

获取下一个uid以便在你的应用程序中使用(因为你没有指定语言,所以是伪代码)

$uid = redis('SPOP buffered_ids');
redis('SADD used_ids ' . $uid);

编辑实际上那里有竞争条件。要安全地弹出值,请先将其添加到used_ids,然后将其从buffered_ids中删除。

$uid = redis('SRANDMEMBER buffered_ids');
redis('SADD used_ids ' . $uid);
redis('SREM buffered_ids ' . $uid);