redis的value

2020-02-18  本文已影响0人  爱读书的夏夏

1.value的类型有哪些?

string、list、set、hash、sorted set

2.value的类型如何选择?

根据业务数据类型选用合适的redis数据结构。

示例:
产品基本信息缓存,可使用string

全量城市数据:map

热门榜单景点id:list或者set

如果需要按优先级排序:sorted set

坏示例:
全量城市数据序列化成string,redis数据类型选用string。实际上每次get出来的map,只会用到一个key,却将全量城市数据都get出来了,增加了网络传输时间。

3.避免大key

redis各类型value最大值 大key的性能测试
大key潜在的问题

首先大Key在传输键值对时,会对网络造成压力(带宽问题),并且有的proxy会将大内容分片传输,进而再次增加了网络传输时间
其次,如list、hash这类结构,如果使用时间复杂度为O(n)的指令或者使用del命令,那么会造成严重的阻塞

如何缓存大key

参考美团在Redis上踩过的一些坑-4.redis内存使用优化
https://www.iteye.com/blog/carlosfu-2254572

redis大key举例

问题表现
每次在dumper推送数据期间,会造成大量的访问异常(服务500)

问题查找
1、通过error log发现服务异常时,会有大量的redis链接超时

2、通过dumper执行日志,查找耗时的执行流程,且是对redis操作的,发现产生链接超时和对redis执行耗时的操作时间重叠

通过分析dumper代码,发现是由于对 5 库 cm=all_all_redis_ad(数据长度1kw左右) 进行删除时采用的del key,阻塞20-30s

左右,在读取 3 库 de_qp_redis(22w左右)时采用的hkeys,阻塞1.5s左右,redis阻塞导致的链接超时

问题解决
1、解决删除5库cm=all_all_redis_ad的阻塞

解决方法:在dumper时,不对该key进行删除,通过写新key,在把该key rename成旧key,在把新key rename 成该key,解决问题

好处:通过写新key,在dumper数据时原key还可以提供服务,rname操作耗时可以忽略,对服务营销最小;

      然后再通过hscan分批删除或unlink(redis 4.0以上版本,python 客户端最新),异步删除旧key,解决删除时造成的阻塞

2、解决hkeys引起的阻塞

解决方法:通过hscan分批读取取代hkeys

问题总结
由于redis是典型的单线程架构,造成阻塞就会影响其他的服务

生产环境中,慎用 keys,hgetall,hkeys等操作,这些操作的时间复杂度都是O(n),大对象上做这些操作会造成阻塞

知识总结
1、对于低版本的redis(2.8以上4.0以下),采用hscan获取大key的元素,分批次删除,直到删除大key的所有元素

2、redis 4.0 以上版本,使用unlink,其执行惰性删除策略,只是将key从keyspace元数据中删除,真正删除时在后台线程异步删除;

3、redis相关配置:

 lazyfree-lazy-eviction  默认关闭

 针对redis内存使用达到maxmeory,并设置有淘汰策略时;在被动淘汰键时,是否采用lazy free机制;

 注意:开启lazy free, 可能使用淘汰键的内存释放不及时,导致redis内存超用,超过maxmemory的限制。此场景使用时,请结合业务测试。

 lazyfree-lazy-expire 默认关闭

 针对设置有TTL的键,达到过期后,被redis清理删除时是否采用lazy free机制;

 此场景建议开启,因TTL本身是自适应调整的速度。

 lazyfree-lazy-server-del 默认关闭

 针对有些指令在处理已存在的键时,会带有一个隐式的DEL键的操作。如rename命令,当目标键已存在,redis会先删除目标键,如果这些目标键是一个big key,那就会引入阻塞删除的性能问题;

 此参数设置就是解决这类问题,建议可开启。

 replica-lazy-flush 默认关闭

 针对slave进行全量数据同步,slave在加载master的RDB文件前,会运行flushall来清理自己的数据场景;

 参数设置决定是否采用异常flush机制。如果内存变动不大,建议可开启。可减少全量同步耗时,从而减少主库因输出缓冲区爆涨引起的内存使用增长。
上一篇下一篇

猜你喜欢

热点阅读