在工作中,同事遇到一个需要批量生成不重复码的功能,之前我处理的都是用php 直接用数组 in_array解决的,那时候生成的数量倒还不多,大概也就几万个,所以直接将php的运行内存提高一点,然后就解决问题了。但是这次要处理的数据量比较大,是五千万个,就容易出现问题。
首先,运行内存是肯定不够的,然后存储空间也会受到限制,代码的效率在php超时的情况下会出现问题。30秒对于这样的数据处理而言还是太短了,从生成情况来看,前面的生成比较快,后面的生成就逐渐的慢下来了,因为要保证和前面的不重复,如果不判断是否重复,也是很快的。
我们的第一种方案是,先以100万为批次的生成,然后导入数据库,在数据库的表中以该字段做主键,后来发现这样的方式导入比较慢,改为主键自增导入,然后加快了速度,全部导入后,采用group by 分组 查询那些出现重复的,删除掉,再补充相应数量的码即可。
经前同事提醒,给我提供了第二种思路,采用redis的存储比对来完成数据不重复的功能,在redis中有一个哈希的类型,不断的将生成的码放入该键中,使用 hset方法,这个方法会覆盖或者新增某个键对应的值 我用的核心代码如下
$result=$redis->hset("code_list",$code,$code);
这样能根据生成的码 本身做键,来存储和替换,如果生成了重复了 就把之前的覆盖掉了,这样能正确的计算数量。然而在实际的redis操作过程发现,自己电脑内存不够用,当生成三千三百万数据的时候,输入info查看到memory的情况如下
很明显已经达到了5.04G,我的电脑已经卡顿,打字和移动鼠标逐渐变得困难,就没有继续实验了。这个增长速度也是刚开始很快,后来逐渐的变慢了。然后增长的也越来越慢,而电脑也越来越卡,实验终止了,我想如果以后有机会我还是会尝试的,毕竟这个思路是很独特,可以借鉴一下,但是这个本身是在NOSQL上面实验,内存的耗费上容易出现问题。为什么mysql没有出现这样的问题呢?因为mysql本身把数据存储在物理磁盘上了,redis的数据还在内存中,这是不能比的。在本次试验中,发现2千万以前的数据还是比较好生成的,超过3千万,就容易出问题,我电脑配置是