Redis进行大批量数据查询,预防内存耗尽处理方案

在最近的需求开发中,有个需求是要拿一批词【每个作品对应的词不同,大概1000个左右】去另一批词进行匹配查询【数据是动态的,更新不频繁,大概有3w个词】,考虑到速度和性能的影响,不能每次查询都走mysql,所以结合Redis进行开发,下面开发及优化的过程:

一、PHP中array_intersect()方法处理

从数据库中查出全部词放入Redis中,然后拿到每次进行查询的时候从缓存中取出词,然后使用array_intersect()方法获取交集,这种其实查询速度倒没什么影响,就是每次将3w个词塞入到变量中,该部分用户访问的还很频繁,虽然每次用完就会unset(),但是还是就会导致内存耗尽,影响系统的运行。

二、Redis中哈希分块处理

根据上述的考虑,想着是将3w个词分组塞入到缓存中,循环取词进行查询,比如:刚开始查出3w个词,使用array_chunk()分成5000个一组,也就是6组词,然后使用塞入到哈希中,使用下标命名key,每次先使用HLEN查询哈希中字段数量长度,如上则为6,然后通过拼接key进行循环查询,使用array_intersect()获取交集,这样虽然相对来说减少了内存的消耗,但是效果不佳,如果词组增加,循环次数也会相应增加。

三、Redis中集合处理

使用Redis集合处理,将词组全部查出来塞入到集合中,集合未提供批量查询值的方法,所以每次查询前,将查询词塞入到另一个集合中,通过去集合中交集方法,就能获取到两组词的交集,这种效率和对内存的使用都是最优解,如下所示

 	
 	/**
     * 获取筛选词组
     * @param $words
     * @param $id
     * @return array
     */
    function getWord($words, $id) {

        $key = "word:set";

        $redis = Redis::connection()->client();

        // 缓存源数据
        if (!RedisHelper::sCard($key)) {

            $wordKey = "word:list";

            if ($redisWords = Redis::get($wordKey)) {

                $redisWords = json_decode($redisWords, 1);

            } else {

                $redisWords = Word::pluck('keyword')
                    ->toArray();

                Redis::set($wordKey, json_encode($redisWords));

            }

            array_unshift($redisWords, $key);

            // 塞入到集合中
            call_user_func_array([$redis, 'sadd'], $redisWords);

            $filterWords = array_intersect($words, $redisWords);

        } else {

            $idKey = "word:set:{$id}";

            array_unshift($words, $idKey);

            // 将查询词组塞入到集合中
            call_user_func_array([$redis, 'sadd'], $words);

            // 获取交集
            $filterWords = Redis::SINTER($key, $idKey);

            Redis::DEL($idKey);

        }

        return $filterWords;

    }
    

你可能感兴趣的:(Redis,PHP,redis,数据库)