Redis性能优化
性能优化避免慢查询命令当发现redis性能变慢的时候,可以通过redis日志,或者是latency monitor工具,查询变慢的请求,根据请求对应的具体命令以及官方文档,确认下是否采用了复杂度高的查询,如果确实存在大量的慢查询命令则优化用其他高效的命令替代eg:当需要返回一个set中的所有成员时,使用sscan多次迭代返回代替smembers(避免一次返回大量数据,造成线程阻塞)当需要执行排序、
性能优化
-
避免慢查询命令
当发现redis性能变慢的时候,可以通过redis日志,或者是latency monitor工具,查询变慢的请求,根据请求对应的具体命令以及官方文档,确认下是否采用了复杂度高的查询,如果确实存在大量的慢查询命令则优化
-
用其他高效的命令替代
eg:当需要返回一个set中的所有成员时,使用sscan多次迭代返回代替smembers(避免一次返回大量数据,造成线程阻塞)
-
当需要执行排序、并集、交集操作时,可以在客户端完成,而不要使用sort、sunion、sinter这些命令,以拖慢redis实例
-
-
生产环境禁用keys命令
keys命令是慢查询命令,因为keys命令需要遍历存储的键值对,所以操作的时延很高,在生产环境使用可能导致redis阻塞
-
keys需要设置过期时间
redis作为内存数据库,一切的数据都是在内存中,一旦内存占用过大则会大大影响性能。因此需要设置过期时间,这样redis能够定时的删除过期的数据
-
禁止批量的给keys设置相同的过期时间
默认情况下,Redis每100毫秒会删除一些过期key
-
采样ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP个数的key,并将其中过期的key全部删除
-
如果超过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过期
-
-
-
谨慎选择数据结构
redis常用的数据结构一共有5种:string、hash、list、set、zset
- string:单个的缓存结果,不与其他的KV之间有联系
- hash:一个Object包含很多属性,且这些属性需要单独存储。这种情况下如果使用string会占据更多的内存
- list:一个Object包含很多数据,且这些数据允许重复、要求有顺序性
- set:一个Object包含很多数据,不要求数据有顺序,旦不允许重复
- zset:一个Object包含很多数据,且这些数据自身还包含一个权重值,可以利用这个权重值来排序
扩展类型
- HyperLogLog:适用于基数统计,比如PV,UV的统计,存在误差,不适合精确统计
- BitMap:适合二值状态的统计,比如签到打卡,要么打卡了,要么未打卡
-
检查持久化策略
- AOF日志:采用文件追加的方式将命令记录在日志中的策略
- RDB快照:以快照的方式,将某一时刻的内存数据,以二进制的方式写入磁盘
- AOF和RDB混用:结合两种各自的优点,在RDB快照的时间段内使用AOF日志记录这段时间操作的命令,这样一旦发生宕机,将不会丢失两段快照中间的数据
由于写入磁盘有IO性能瓶颈,因此不是将redis作为数据库的话(可以从后端恢复),建议禁用持久化或者调整持久化策略
-
采用高速的固态硬盘作为日志写入设备
由于AOF日志的重写对磁盘的压力较大,可能会阻塞,如果需要使用到持久化,建议使用高速的固态硬盘作为日志写入设备
-
使用物理机而非虚拟机
由于虚拟机增加了虚拟化软件层,与物理机相比,虚拟机本身就存在性能的开销
-
增加机器内存或使用redis集群
物理机器的内存不足将会导致操作系统内存的swap
-
内存swap是操作系统里将内存数据在内存和磁盘间来回换入和换出的机制、涉及到磁盘的读写,所以一旦触发swap,无论是被换入数据的进程,还是被换出数据的进程,其性能都会受到慢速磁盘读写的影响
-
redis是内存数据库,内存使用量大,如果没有控制好内存的使用量,或者其他内存需求大的应用一起运行了,就可能受到swap的影响,从而导致性能变慢
-
正常情况下,redis的操作是直接通过访问内存就能完成,一旦swap被触发了,redis的请求操作需要等到磁盘数据读写完成才行。swap触发后影响的是redis主io线程,这会极大地增加redis的响应时间
因此增加机器的内存或者使用redis集群能够有效的解决操作系统内存的swap,提高性能
-
-
使用Pipeline批量操作数据
Pipeline(管道技术)是客户端提供的一种批处理技术,用于一次处理多个redis命令,从而提高整个交互的性能
-
客户端优化使用
在客户端的使用上除了要尽量使用Pipeline的技术外,还需要注意尽量使用redis连接池,而不是频繁创建和销毁redis连接,这样可以减少网络传输的次数和减少了非必要调用指令
-
使用分布式架构来增加读写速度
-
主从复制
使用主从同步功能我们可以把写入放在主库上执行,把读功能转移到从服务上,因此就可以在单位时间内处理更多的请求,从而提升redis的整体运行速度
-
哨兵模式
此模式是对主从功能的升级,当主节点奔溃之后,无需人工干预就能自动恢复redis的正常使用
-
redis cluster集群
- 通过将数分散存储到多个节点上,来平衡各个节点的负载压力
- 采用虚拟哈希槽分区,所有的键根据哈希函数映射到0~16383整数槽内,计算公式:slot = CRC16(key) & 16383,每一个节点负责维护一部分槽以及槽所映射的键值数据,这样redis就可以把读写压力从一台服务器,分散给多台服务器,大大的提高性能
redis cluster是首选方案,它可以把读写压力自动的分担给更多的服务器,并且具有自动容灾的能力
-
-
避免内存碎片
频繁的新增修改会导致内存碎片增多,因此需要时刻的清理内存碎片
redis查看内存的使用信息的命令:INFO memory
- men_fragmentation_ratio:内存碎片率
- used_memory_rss:操作系统实际分配给redis的物理内存空间
- used_memory:redis为了保存数据实际申请使用的空间
当men_fragmentation_ratio大于1.5,这表明内存碎片率已经超过了50%,这个时候需要采取一些措施来降低内存碎片率
更多推荐
所有评论(0)