2020-04-30 18:05:00
围观(4984)
数字无处不在, 在一些应用场景就特别需要, 比如 订单号 / 防伪码 / 抽奖 / 用户编号 等.
订单号一般都是即时生成的, 比如很多都是用下单时间或者时间戳 如:2020043018010005 或者 1588240860000 还能再加上用户 ID 和随机数, 所以就没什么难度.
但是有些应用场景就不一样了, 比如防伪码和用户编号, 防伪码可能有十万个或者更多, 就需要一次性批量的生成了, 并且还要保证唯一性, 另外因为防伪码的特殊性还需要保证无序. 如果用户编号想做到无序也是一样, 需要先批量生成存储到某个容器, 然后依次拿出使用.
查阅了一些资料, 想了解一下怎么样才能又快又能保证唯一性和无序的大量生成数字, 看到了 "雪花算法", 但是感觉有点难. 劝退了...
博主有简单学一下 Python , 所以就拿 Python 写一下(献丑了)
import random lst_number = [] lst_selected_number = [] start_number = 1000000 # 开始数字 end_number = 9999999 # 结束数字 num = 100000 # 生成数量 if end_number <= start_number: print('结束数字不能小于开始数字') exit() for x in range(start_number, end_number): lst_number.append(x) lst_selected_number = random.sample(lst_number, num) print(lst_selected_number)
将上面代码复制保存到 number.py 并运行. 会打印出一个装满了十万个数字的列表:
这样一下子就生成出来了十万个无序且唯一的数字.
逻辑很简单, 就是先设置一个空列表, 然后循环遍历开始数字到结束数字, 比如从 1000000 开始, 到 9999999 结束, 将每个遍历出来的数字装入列表, 那么这个列表的元素就有 1000001, 1000002 1000003 ... 直到 9999998. 遍历完成后列表就一共有九百万个数字, 使用 random.sample 函数就能直接从列表的九百万个数字中抽取十万个数字出来, 且是不重复的抽. 所以就拿到了十万个唯一且无序的数字.
拿到数字之后可以保存到一些容器按需使用, 但是仔细看上图, 每个数字的长度都是七位. 假如防伪码需要的是十一位呢, 可以修改代码的开始数字为 10000000000 到 99999999999 然后运行代码会发现, 没反应了... 再打开系统任务管理器, 发现 Python 占用的内存极高.
再过没多久, 就直接报错了.
内存不够了...
盲猜是因为遍历存入列表, 列表数据太多把内存撑爆了, 所以使用 Redis 的列表进行存储:
import random import redis pool = redis.ConnectionPool(host = 'localhost', port = 6379, decode_responses = true) container_box = redis.Redis(connection_pool = pool) # 连接池 start_number = 10000000000 # 开始数字 end_number = 99999999999 # 结束数字 if end_number <= start_number: print('结束数字不能小于开始数字') exit() for x in range(start_number, end_number): container_box.lpush("list1", x) print(container_box.llen("list1"))
执行代码, Redis 会开始存储数字, 使用可视化工具看得很直观
但是问题来了, 按照之前代码(本文第一段代码)生成九百万个数字的效率, 时间应该是两秒, 第二段代码生成十一位的数字就是九百亿个, 假设一秒能完成九百万个数字, 那也要 10000 秒, 就是最快也要 3 个小时... 但实际肯定是不止的.
博主用了大概两个半小时才生成了七千万个数字就放弃了...
如果已经完成数字遍历并将数字存入了 Redis, 接下来要做的就是按需使用, 需要使用数字的时候, 从 0 到 90000000000 (九百亿) 取一个随机数字, 拿列表中这个随机数字(Key)的元素, 拿取之后记得删除该元素.
经过博主的测试, 生成十万个长度八位(10000000 - 99999999 之间)的数字(无序且唯一)需要用时 17 秒(不使用 Redis)左右.
九位及以上就爆内存了.. 运行代码的机器是 16G 的. 如果电脑有 32G 或许可以挑战一下11位.
本文地址 : bubaijun.com/page.php?id=177
版权声明 : 未经允许禁止转载!
上一篇文章: Python开发 - 微信公众号文章采集
下一篇文章: Laravel使用GatewayWorker开发即时聊天