美文网首页
redis sadd 使用和优化案例

redis sadd 使用和优化案例

作者: 西5d | 来源:发表于2020-03-18 15:53 被阅读0次

    redis 集合结构介绍

    redis集合(Set)结构类似java中的set,可以保证元素的唯一性,而sadd命令用于向集合中添加一个或多个成员,已经在集合中的元素将被忽略,key不存在则创建集合。

    场景描述

    要求创建一个用户集合,这个集合是每天从其他数据源获取,构造任务处理这些数据,提供给下游来判断某个用户是否在这个集合中。集合内容是一些用户标识,32位的md5值,数据量较大,文本大概800MB,行数约2700万,但还不算特别大的数据量,所以计划放到redis中。

    遇到的问题

    首先很明显, redis的set结构是可以满足需求的,开始也考虑到不能全部都放到一个key里。简单了解到redis set 单个key可以支持2^32-1 的个数,且根据md5值的特征,每一位都是16进制,所以取最后一位生成key, 比如2020-03-17:e。这样就可以有16个key,可以分担key的数据量,减少压力。同时程序中,使用MultiMap,在超过10000大小后,再开始批量写入redis,最后给这些固定的key设置过期时间为2天,本地根据样本数据跑通了整个流程,然后开始根据实际数据量进行。
    问题是在部署取到实际的数据后,执行任务,执行近2小时,依然没有将数据全部导入到redis中,按理说800MB文本不算很大量的。 同时观察redis集群监控,CPU从2%-3%升高到10%左右,此时不得不中断任务。
    回顾现状,总的数据量约2700万,现有16个key, 每个key会有167万左右的数据,其中每个value的值是32位md5值,空间占32B,每个key占的空间大约54MB(167W*32B)。首先想到还是单个key太大了,才导致压力升高,于是考虑增加key的数量,来减少set中单个key的元素数量。同时也了解到,一般情况set的单个key下最好不要超过1MB,当前肯定是大大超过的。1MB按单个值32B计算,大约可以存3.2万个key,当然这是非常理想的情况,还有其他一些必须的内容也要占用空间,所以建议的单个key中元素也就在2-3万左右。

    引申

    这里介绍几个Redis相关命令,用于查询当前key状态情况和排查问题:

    1. scard

    获取set 某个key下的元素个数,比如

    10.118.xx.xx:xxx> scard users:2020-03-17:aff
    
    

    2. memory usage

    查看某个key所占的内存,返回内存大小,单位是字节。比如。

    10.136.xxx.xxx:xxx> memory usage users:2020-03-18:000
    (integer) 457389
    

    3. pttl 和 ttl

    pttl获取毫秒级别的有效时间,注意是实际精度的,不是秒级别换算的值;ttl获取秒级别的有效时间

    解决方法

    目标确定是减少单个key的数据量,还是从md5本身出发。之前取最后一位作为键后缀,有16个key,如果再往前取就可以增加key的个数,总的数据量是一定的,从而可以减少单个key的数据量。 这里改成取后三位来做key后缀,会有0x000-0xfff共4096(16*16*16)个key。而单个key中元素数量骤减,变成2700W/4096,大约6500左右。(从167万降到6500)。

    后续追踪

    修改后开始用实际数据验证,开始任务后,监控到redis CPU升高仅1%,从3%到4%左右,任务最终持续时间45分钟,至此整个任务开发完成。这里有几个点可以进一步优化,首先是没有引入多线程写入redis,其次可以对文件进行拆分,来运用并发读取,还有redis查询方面,可以换bitmap,当然这样整个逻辑是要变的,后续如果数据量更大可以再考虑。我们看到对这种数据量较大的问题的处理,前期的调研和计算还是非常重要的,很多功能组件在数据量较少和大量的情况下,表现可能是完全不一样的,大数据量的处理会有更多未知的问题。

    相关文章

      网友评论

          本文标题:redis sadd 使用和优化案例

          本文链接:https://www.haomeiwen.com/subject/bzqcyhtx.html