Redis:性能优化之Redis使用的规范

文章目录

  • 【关于作者】
  • 1.键值对使用规范
    • 1.1.key的命名规范
    • 1.2.规避使用bigkey
    • 1.3.采取高效序列化方法和压缩方法
    • 1.4.使用整数对象共享池
  • 2.数据保存规范
    • 2.1.使用redis保存热数据
    • 2.2.不同的业务数据分实例存储
    • 2.3.数据保存时,设置过期时间
    • 2.4.控制实例的容量
  • 3.命令使用规范
    • 3.1.线上禁用部分命令
    • 3.2.慎用MONITOR命令
    • 3.3.慎用全量操作的命令
  • 4.运维层面

【关于作者】

关于作者,目前在蚂蚁金服搬砖任职,在支付宝营销投放领域工作了多年,目前在专注于内存数据库相关的应用学习,如果你有任何技术交流或大厂内推及面试咨询,都可以从我的个人博客(https://0522-isniceday.top/)联系我

1.键值对使用规范

1.1.key的命名规范

  • 按照业务用于区分key,使用冒号进行分割

    这样能够将相同的业务key放到一个db,减少切换db的开销

    规范的命令有利于key的匹配,keys命令。例如客户端缓存的key的监控、scan等操作

  • 控制key的长度

    redis中key也是字符串存储,因此也是使用SDS进行存储,因此控制key的长度有利于节省内存空间
    Redis:性能优化之Redis使用的规范_第1张图片

1.2.规避使用bigkey

Redis针对读写命令的处理是单线程的,因此bigkey的操作会阻塞线程,尤其是针对时间复杂度为O(n)的数据结构进行并交集、全量查询等耗时的操作

bigkey也分为两种:

  • 键值对的value本身就很大,例如String本身就有10mb,建议把String的大小控制在10kb(10 * 1024字节,大部分编码格式下,一个中文占用4个字节,字母占用2个字节),如果value确实很大,此时我们可以考虑将数据进行压缩
  • 集合类型的元素数量特别多,建议控制在1万个元素个数之下,可通过拆分list的方式

Redis的4种集合类型List、Hash、Set和Sorted Set,在集合元素个数小于一定的阈值时,会使用内存紧凑型的底层数据结构(压缩列表)进行保存,从而节省内存。例如,假设Hash集合的hash-max-ziplist-entries配置项是1000,如果Hash集合元素个数不超过1000,就会使用ziplist保存数据。

1.3.采取高效序列化方法和压缩方法

但是,不同的序列化方法,在序列化速度和数据序列化后的占用内存空间这两个方面,效果是不一样的。比如说,protostuff和kryo这两种序列化方法,就要比Java内置的序列化方法(java-build-in-serializer)效率更高。

此外,业务应用有时会使用字符串形式的XML和JSON格式保存数据。

这样做的好处是,这两种格式的可读性好,便于调试,不同的开发语言都支持这两种格式的解析。

缺点在于,XML和JSON格式的数据占用的内存空间比较大。为了避免数据占用过大的内存空间,我建议使用压缩工具(例如snappy或gzip),把数据压缩后再写入Redis,这样就可以节省内存空间了

1.4.使用整数对象共享池

Redis内部维护了09999这一万个整数对象,并将其作为对象池使用,因此再业务允许的情况下,能用整数就用整数,因为如果使用到了整数,不管有多少键值对,其实真是的引用地址都是一个,这样可以大大的节省空间哟

但是整数共享池在某些场景不会起作用:

  • 使用了设置maxmemory及LRU淘汰策略的情形下,LRU需要统计键值对的使用时间,如果都使用的一个对象,那么就无法统计
  • 集合类型采取压缩列表的方式存储,压缩列表本质还是一个数组,数组中都是直接存储元素而不是指针,判断整数对象的共享情况效率低

2.数据保存规范

2.1.使用redis保存热数据

redis保存热数据能够提供高性能的访问,如果写场景比较多的话,也需要将数据同步的开销算进去,还有就是需要考虑

缓存失效导致的缓存击穿,因为尽量将数据不设置过期时间,还有就是可以将同步缓存的操作用分布式锁锁住,这样就不会有大量请求打向数据库了

2.2.不同的业务数据分实例存储

把不同的业务数据放到不同的 Redis 实例中。这样一来,既可以避免单实例的内存使用量过大,也可以避免不同业务的操作相互干扰

2.3.数据保存时,设置过期时间

根据业务的时长,设置合理的过期时间,因为如果不设置过期时间,redis实例内存满了会触发数据淘汰,这个时候会释放内存的操作会阻塞主进程,并且设置过期时间时候尽量避免批量过期的情况

2.4.控制实例的容量

建议设置在2~6GB,实例数据量过大会加大RDB快照的fork的耗时,以及主从实例数据同步的耗时

3.命令使用规范

3.1.线上禁用部分命令

Redis是单线程处理读写命令,如果一些耗时的命令或操作会阻塞主进程,其中包括:

  • KEYS:返回匹配key内容的key,这个操作会扫描全局哈希表,严重阻塞redis的主进程,可用SCAN命令进行替代
  • FLUSHALL,删除Redis实例上的所有数据,如果数据量很大,会严重阻塞Redis主线程,可以加上ASYNC,让redis后台线程异步删除
  • FLUSHDB,删除当前数据库中的数据,如果数据量很大,同样会阻塞Redis主线程,解决方案同FLUSHALL

线上如何禁用呢?管理员用rename-command命令在配置文件中对这个命令重命名,让客户端无法使用

3.2.慎用MONITOR命令

Redis使用MONITOR命令后,会持续监控后续命令的执行情况,这个时候会将执行情况输入到输出缓存区,如果输出缓冲区满了之后就会影响Redis性能及造成redis崩溃

建议不使用MONITOR命令,除非十分需要监测某些命令的执行,可以短时间内使用

3.3.慎用全量操作的命令

对于集合数据类型而言,慎重使用SCAN等操作,因为这些操作会对底层的数据进行全表扫描,如果数据量比较大则会阻塞主线程

解决方案如下:

  • 使用SSCAN、HSCAN分批返回集合中的数据
  • 将结构数据看是否能够在符合业务的情况下进行拆分,例如根据不同的维度拆分
  • 如果使用hash存储的对象的键值信息,并且每次都是全量返回的话,可以使用String的方式进行存储,将value序列化为JSON的形式

4.运维层面

  • 建议部署主从集群,并分布在不同机器上,slave 设置为 readonly
  • 实例设置最大连接数,防止过多客户端连接导致实例负载过高,影响性能
  • 设置合理的 slowlog 阈值,并对其进行监控,slowlog 过多需及时报警
  • 设置合理的 repl-backlog,降低主从全量同步的概率,具体的参数设置可看:
  • 设置合理的 slave client-output-buffer-limit,避免主从复制中断情况发生(缓冲区溢出)
  • 调整 maxmemory 时,注意主从节点的调整顺序,顺序错误会导致主从数据不一致
  • 对实例部署监控,采集 INFO 信息时采用长连接,避免频繁的短连接
  • 做好实例运行时监控,重点关注 expired_keys、evicted_keys、latest_fork_usec,这些指标短时突增可能会有阻塞风险

强制:表示如果不遵守会给redis带来极大的性能影响

推荐:代表可以直接运用在实践中

建议:结合业务场景考量再决定是否使用

你可能感兴趣的:(redis,redis,性能优化,数据库)