性能优化

  1. 避免慢查询命令

    当发现redis性能变慢的时候,可以通过redis日志,或者是latency monitor工具,查询变慢的请求,根据请求对应的具体命令以及官方文档,确认下是否采用了复杂度高的查询,如果确实存在大量的慢查询命令则优化

    1. 用其他高效的命令替代

      eg:当需要返回一个set中的所有成员时,使用sscan多次迭代返回代替smembers(避免一次返回大量数据,造成线程阻塞)

    2. 当需要执行排序、并集、交集操作时,可以在客户端完成,而不要使用sort、sunion、sinter这些命令,以拖慢redis实例

  2. 生产环境禁用keys命令

    keys命令是慢查询命令,因为keys命令需要遍历存储的键值对,所以操作的时延很高,在生产环境使用可能导致redis阻塞

  3. keys需要设置过期时间

    redis作为内存数据库,一切的数据都是在内存中,一旦内存占用过大则会大大影响性能。因此需要设置过期时间,这样redis能够定时的删除过期的数据

  4. 禁止批量的给keys设置相同的过期时间

    默认情况下,Redis每100毫秒会删除一些过期key

    1. 采样ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP个数的key,并将其中过期的key全部删除

    2. 如果超过25%的key过期了,则重复删除过程,直到过期key的比例降至25%以下

      ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP是redis的一个参数,默认是20,一秒内基本有200个过期key会被删除。这一策略对清除过期key、释放内存空间很有帮助,而且并不会对redis的性能造成太大的影响

      • 但是如果触发了第2条,redis就会一直删除以释放内存空间。删除操作是阻塞的(redis4.0后可以用异步线程机制来减少阻塞影响)所以,一旦该条件触发,redis的线程就会一直执行删除,会导致无法正常呢服务其他键值操作,就会进一步引起其他键值操作的延迟增加,redis就会变慢。

      • 频繁使用带有相同时间参数的EXPIRE命令设置过期key将会触发第2条,这就会导致在一秒内存在大量的keys过期

  5. 谨慎选择数据结构

    redis常用的数据结构一共有5种:string、hash、list、set、zset

    1. string:单个的缓存结果,不与其他的KV之间有联系
    2. hash:一个Object包含很多属性,且这些属性需要单独存储。这种情况下如果使用string会占据更多的内存
    3. list:一个Object包含很多数据,且这些数据允许重复、要求有顺序性
    4. set:一个Object包含很多数据,不要求数据有顺序,旦不允许重复
    5. zset:一个Object包含很多数据,且这些数据自身还包含一个权重值,可以利用这个权重值来排序

    扩展类型

    1. HyperLogLog:适用于基数统计,比如PV,UV的统计,存在误差,不适合精确统计
    2. BitMap:适合二值状态的统计,比如签到打卡,要么打卡了,要么未打卡
  6. 检查持久化策略

    1. AOF日志:采用文件追加的方式将命令记录在日志中的策略
    2. RDB快照:以快照的方式,将某一时刻的内存数据,以二进制的方式写入磁盘
    3. AOF和RDB混用:结合两种各自的优点,在RDB快照的时间段内使用AOF日志记录这段时间操作的命令,这样一旦发生宕机,将不会丢失两段快照中间的数据

    由于写入磁盘有IO性能瓶颈,因此不是将redis作为数据库的话(可以从后端恢复),建议禁用持久化或者调整持久化策略

  7. 采用高速的固态硬盘作为日志写入设备

    由于AOF日志的重写对磁盘的压力较大,可能会阻塞,如果需要使用到持久化,建议使用高速的固态硬盘作为日志写入设备

  8. 使用物理机而非虚拟机

    由于虚拟机增加了虚拟化软件层,与物理机相比,虚拟机本身就存在性能的开销

  9. 增加机器内存或使用redis集群

    物理机器的内存不足将会导致操作系统内存的swap

    1. 内存swap是操作系统里将内存数据在内存和磁盘间来回换入和换出的机制、涉及到磁盘的读写,所以一旦触发swap,无论是被换入数据的进程,还是被换出数据的进程,其性能都会受到慢速磁盘读写的影响

    2. redis是内存数据库,内存使用量大,如果没有控制好内存的使用量,或者其他内存需求大的应用一起运行了,就可能受到swap的影响,从而导致性能变慢

    3. 正常情况下,redis的操作是直接通过访问内存就能完成,一旦swap被触发了,redis的请求操作需要等到磁盘数据读写完成才行。swap触发后影响的是redis主io线程,这会极大地增加redis的响应时间

      因此增加机器的内存或者使用redis集群能够有效的解决操作系统内存的swap,提高性能

  10. 使用Pipeline批量操作数据

    Pipeline(管道技术)是客户端提供的一种批处理技术,用于一次处理多个redis命令,从而提高整个交互的性能

  11. 客户端优化使用

    在客户端的使用上除了要尽量使用Pipeline的技术外,还需要注意尽量使用redis连接池,而不是频繁创建和销毁redis连接,这样可以减少网络传输的次数和减少了非必要调用指令

  12. 使用分布式架构来增加读写速度

    1. 主从复制

      使用主从同步功能我们可以把写入放在主库上执行,把读功能转移到从服务上,因此就可以在单位时间内处理更多的请求,从而提升redis的整体运行速度

    2. 哨兵模式

      此模式是对主从功能的升级,当主节点奔溃之后,无需人工干预就能自动恢复redis的正常使用

    3. redis cluster集群

      • 通过将数分散存储到多个节点上,来平衡各个节点的负载压力
      • 采用虚拟哈希槽分区,所有的键根据哈希函数映射到0~16383整数槽内,计算公式:slot = CRC16(key) & 16383,每一个节点负责维护一部分槽以及槽所映射的键值数据,这样redis就可以把读写压力从一台服务器,分散给多台服务器,大大的提高性能

      redis cluster是首选方案,它可以把读写压力自动的分担给更多的服务器,并且具有自动容灾的能力

  13. 避免内存碎片

    频繁的新增修改会导致内存碎片增多,因此需要时刻的清理内存碎片

    redis查看内存的使用信息的命令:INFO memory

    • men_fragmentation_ratio:内存碎片率
    • used_memory_rss:操作系统实际分配给redis的物理内存空间
    • used_memory:redis为了保存数据实际申请使用的空间

    当men_fragmentation_ratio大于1.5,这表明内存碎片率已经超过了50%,这个时候需要采取一些措施来降低内存碎片率

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐