基于php实现多进制转换与唯一码生成的探索

栏目: PHP · 发布时间: 8年前

内容简介:基于php实现多进制转换与唯一码生成的探索

最近要做一个兑换码生成的功能,之前有做过32位唯一码生成器,但是在业务需求中,32位的兑换码有些过长了,用户在应用内填写的时候会比较麻烦,不是很友好,倒是可以做成二维码的形式扫一下就行了,但是业务中还是存在输入兑换码的行为,所以本篇主要是关于以尽量短的字符来生成唯一码,同时要保证唯一性以及生成机制复用性(也就是利用这套机制可以生成不同种类的兑换码)的探索

以下示例代码均基于 TPRCMS 编写

探索一: 进制转换

生成的32位唯一码是16进制的一串字符,我就在想是不是可以通过提高进制来缩短字符串长度,所以有了如下的代码

代码地址: 多进制转换器ConvertLogic

其中关于10进制与62进制互转的部分,参考了 《PHP 10进制与62进制互转,可用于生成短网址》

实例代码

$uuid = "cd5fd2cfeb40aafe060f4d9597348be7";
$str = ConvertLogic::convert( $uuid, 16, 62);

输出

string(32) "cd5fd2cfeb40aafe060f4d9597348be7"
string(22) "6fxdxREtzxq6qNdSghGm7t"

经过转换后发现,长度最多压缩到21~22位,感觉还是有些长

探索二: uniqid()转62进制

uniqid()可以生成一个13位以上的16进制唯一码,将它转为62进制,会到一个更短的字符串

实验代码

$uuid = uniqid('code');
$resule = ConvertLogic::convert( $uuid, 16, 62);

//输出
//string(17) "5a5c5b182386"
//string(12) "7hoyVkRTi "

通过多次生成,从结果观察来看,有以下几个不足:

1.用这种方法生成的一批兑换码,只有后5位是变动的,前面的都不变,可能会造成结果比较好猜,容易被爆破试出来。

2.唯一性不足。在批量并发多机器生成的时候,很难保证唯一性

探索三: 伪随机生成12位字符串,用 redis 保证唯一性

示例代码

//$category_uniq是类目的hash,下面这句代码主要目的是保证同一类目下不存在相同的兑换码
RedisService::redis()->switchDB()->hSetNx('code_hash_list_'.$category_uniq,  $code, $category_uniq);
//如果同类目下已存在相同的兑换码,会返回false

伪随机字符生成代码

private static function uniq($uniq, $times)
    {
        if ($times == 0) {
            return $uniq;
        }
        $temp = substr(ConvertLogic::convert(uniqid(), 16, 62), 7);
        $uniq = $uniq . $temp;
        $times--;
        return self::uniq($uniq, $times);
    }

通过串行100万次随机生成发现,一开始差不多是4万分之一的重复率,之后会逐渐上升

探索四: redis"领票",用事务操作保证计数器的准确,一个兑换码领一个票

4位票号 + 12位伪随机码

4位票号的目的是为了保证唯一性,伪随机码是为了防止被轻易试出正确值。

这样即便知道了前面4位是票号,加一就行,但是后面12位可就难试了。

而且4位的票号可以支持一个类目有14538000个兑换码(61进制,"ZZZZ"-"1000"),即便是票号不够了,那票码长度+1即可

这个机制还有一个好处就是,可以根据情况自由修改兑换码长度

比如,只需生成几百个码,而且对安全性没有太多要求,那就可以只需要“2位票码+4位随机符”就可以了

  • 领票代码
private static function ticket($category_uniq , $baseCount){
        $key = 'code_ticket_'.$category_uniq;
        RedisService::redis()->switchDB()->watch('code_ticket_'. $category_uniq);

        $count = RedisService::redis()->switchDB()->multi()
            ->incr($key)
            ->exec();
        if($count === false){
            return self::ticket($category_uniq, $baseCount);
        }
        $ticket = $baseCount + $count;

        return $ticket;
    }

兑换码批量生成完整逻辑代码 : CodeLogic


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Natural Language Processing with Python

Natural Language Processing with Python

Steven Bird、Ewan Klein、Edward Loper / O'Reilly Media / 2009-7-10 / USD 44.99

This book offers a highly accessible introduction to Natural Language Processing, the field that underpins a variety of language technologies, ranging from predictive text and email filtering to autom......一起来看看 《Natural Language Processing with Python》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

MD5 加密
MD5 加密

MD5 加密工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试