热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

关于redis:Redis系列之如何高效使用

本文将从避免阻塞和内存节约两个方面介绍如和高效应用Reids。应用Redis时,咱们须要联合具体业务和Redis个性两方面来思考如何设计应用计划。须要两个从两个方

本文将从避免阻塞和内存节约两个方面介绍如和高效应用Reids。

应用Redis时,咱们须要联合具体业务和Redis个性两方面来思考如何设计应用计划。须要两个从两个方面思考:

  1. 避免阻塞
  2. 节约内存

上面,咱们将就下面两个点开展阐明如何高效正当应用Redis。

避免阻塞

阻塞章节咱们晓得,引起Redis阻塞可能的起因有内因外因两方面。

内因躲避

缩小简单命令的应用,或者有节制的应用。上面这些命令能够看做简单命令(工夫复杂度为O(N)或者更高):SETRANGE, GETRANGE, MSET, MGET, MSETNX, HMSET, HMGET, HKEYS,HVALS, HGETALL, HSCAN, LTRIM, LINDEX, SMEMBERS, SUNION, SUNIONSTORE, SDIFF, SDIFFSTORE, ZUNIONSTORE, ZINTERSTORE, SINTER, SINTERSTORE。这些命令当操作的key或者field过多时将会导致Redis过程阻塞。
举例来说,对一个蕴含上十万甚至百万个fieldhash执行hgetall操作,hgetall命令的工夫复杂度为O(N),此时N页特地大(上十万甚至百万)必然耗时很长。
从这个例子,咱们能够发现至多两个不合理的中央:

  1. 这种有大量元素的数据不应该存在,因为,咱们并不能确定什么时候咱们对它执行了简单命令。
  2. 如果真的不可躲避超多元素的状况,在获取多个元素或者全量元素时,务必应用scan之类命令,且确保每次获取元素数量在肯定范畴,比方50等。

防止频繁生成RDB和AOF重写,尤其是高峰期。失常状况下,Redis比拟时候缓存类型数据,当然为了保证数据不失落,能够进行导出RDB和从新AOF。但须要确保一下几点:

  1. 不要执行save等同步命令;
  2. 尽量不要在高峰期进行长久化操作;
  3. 尽量在从实例上做长久化操作;

如果必须频繁长久化,须要确保如下几点:

  1. 保障CPU、内存短缺,倡议CPU和内存留出肯定的buffer
  2. 不要绑定CPU
  3. 防止和CPU密集型服务混布
  4. 如果多个Redis实例部署在同一台机器,留神布局好系统资源,能够思考错峰长久化,防止同时长久化导致系统资源开销霎时突增
  5. 零碎尽量不要开启HugePage,避免复制内存页过大而拖慢执行工夫,且会导致长久化期间内存耗费增长

防止单Redis实例负载过高。Redis是单线程服务,当负载过大必然影响整体性能,能够通过如下计划进步读写能力:

  1. 能够通过读写拆散,从实例承接局部读申请,来升高主实例压力;
  2. 如果读写压力都很大的话,须要思考集群计划。

外因躲避

通常,引起服务的外因无外乎CPU、内存和网络,导致Redis阻塞的起因同样也须要从这几方面去思考。
CPU竞争导致Redis阻塞的问题起因在阻塞章节曾经具体介绍过,对于解决方案,能够通过以下伎俩来躲避:

  1. 过程CPU资源竞争,倡议不要和其余多线程CPU密集型服务混布,尤其是线上环境。另外,如果流量趋势有稳定的服务,比方有早晚顶峰,倡议不要把流量稳定统一的服务混布。
  2. 绑定CPU,绑定CPU(设置CPU亲和力affinity)是为了升高Redis过程在不同CPU来回切换导致缓存命中率降落等引起的性能问题,然而,过程的CPU亲和力会继承给子过程,Redis过程fork出的子过程也共享该CPU。因而,如果须要频繁长久化的Redis不倡议绑定CPU。

节约内存

系统优化

缩小内存碎片,失常的碎片率(mem_fragmentation_ratio)在1.03左右。然而当存储的数据长短差别较大时,以下场景容易呈现高内存碎片问题:

  1. 频繁做更新操作,例如频繁对已存在的键执行appendsetrange等更新操作。
  2. 大量过期键删除,键对象过期删除后,开释的空间无奈失去充分利用,导致碎片率回升。

呈现高内存碎片问题时常见的解决形式如下:

  1. 数据对齐:在条件容许的状况下尽量做数据对齐,比方数据尽量采纳数字类型或者固定长度字符串等,然而这要视具体的业务而定,有些场景无奈做到。
  2. 平安重启:重启节点能够做到内存碎片重新整理,因而能够利用高可用架构,如Sentinel或Cluster,将碎片率过高的主节点转换为从节点,进行平安重启。

RDB生成和AOF重写会fork子过程,进而导致内存耗费。总结如下:

  1. 失常状况下Redis产生的子过程并不需要耗费1倍的父过程内存,理论耗费依据期间写入命令量决定,然而仍然要预留出一些内存避免溢出。
  2. 须要设置sysctl vm.overcommit_memory=1容许内核能够调配所有的物理内存,避免Redis过程执行fork时因零碎残余内存不足而失败。
  3. 排查以后零碎是否反对并开启THP,如果开启倡议敞开,避免copy-onwrite期间内存适度耗费。

用户优化

减小键值字符串长度

  1. key能够通过字符串缩减来缩小长度
  2. value能够通过序列化和压缩来缩小存储,也能够能够通过业务侧优化缩小不必要的字段

尽量应用set而非append

因为字符串(SDS)存在预分配机制,日常开发中要小心预调配带来的内存节约。

表-2 set & append 比照测试

操作 数据量 key大小 value大小 used_memory_human used_memory_rss_human mem_fragmentation_ratio 阐明
set 100w 20B 100B 176.66M 180.19M 1.02 —
set 100w 20B 200B 283.47M 287.66M 1.01
set && append 100w 20B 100B+100B 497.10M 503.19M 1.01 先set,value大小为100B,随后append大小100B的数据

从下面的试验能够看出,同样存储100w条key大小为20B,value大小为200B的数据,通过setappend操作实现的和间接应用set实现多了近75% 的存储耗费。

字符串重构

字符串重构:指不肯定把每份数据作为字符串整体存储,像json这样的数据能够应用hash构造,这样做有如下收益:

  1. 应用二级构造存储也能帮咱们节俭内存。
  2. 同时能够应用hmget、hmset命令反对字段的局部读取批改,而不必每次整体存取。

留神,这样样做的一个前提是json key-value对中value绝对较小,上面是一个测试例子。

{
"id" : "12345678",
"title" : "redis-memory-optimization",
"chinese_url" : "http://www.redis.cn/topics/memory-optimization.html",
"english_url" : "https://redis.io/topics/memory-optimization"
}

代码-2 一个json实例

表-3 hash优化测试

数据量 数据结构 编码 key value 配置 used_memory_human used_memory_rss_human mem_fragmentation_ratio 阐明
100w string raw 20B json字符串 默认 252.95M 258.04M 1.02
100w hash hashtbale 20B key-value hash-max-ziplist-value 50 474.21M 484.27M 1.02
100w hash ziplist 20B key-value hash-max-ziplist-value 64 252.95M 258.09M 1.02

依据测试构造,hash-max-ziplist-value 50配置下应用hash类型,内存耗费岂但没有升高反而比字符串存储多出2倍,而调整hash-max-ziplist-value 64之后内存升高为252.95M。因为json的chinese_url属性长度是51,调整配置后hash类型外部编码方式变为ziplist,相比字符串在内存应用上至多持平且反对属性的局部操作。
intset编码:intset编码是汇合(set)类型编码的一种,外部体现为存储有序、不反复的整数集。当汇合只蕴含整数且长度不超过set-max-intset-entries配置时被启用。

typedef struct intset {
uint32_t encoding;
uint32_t length;
int8_t contents[];
} intset;

代码-3 intset构造

encoding:整数示意类型,依据汇合内最长整数值确定类型,整数类型划分为三种:int-16、int-32、int-64。intset保留的整数类型依据长度划分,当保留的整数超出以后类型时,将会触发主动降级操作且降级后不再做回退。降级操作将会导致从新申请内存空间,把原有数据按转换类型后拷贝到新数组。
应用intset编码的汇合时,尽量放弃整数范畴统一,如都在int-16范畴内。避免个别大整数触发汇合降级操作,产生内存节约。

控制键的数量

通过在客户端预估键规模,把大量键分组映射到多个hash构造中升高键的数量。简略的说就是复用key前缀

总结

内存是绝对贵重的资源,通过正当的优化能够无效地升高内存的使用量,内存优化的思路包含:

  1. 精简键值对大小,键值字面量精简,应用高效二进制序列化工具。
  2. 应用对象共享池优化小整数对象。
  3. 数据优先应用整数,比字符串类型更节俭空间。
  4. 优化字符串应用,防止预调配造成的内存节约。
  5. 应用ziplist压缩编码优化hash、list等构造,重视效率和空间的均衡。
  6. 应用intset编码优化整数汇合。
  7. 应用ziplist编码的hash构造升高小对象链规模。

reference

Redis官网

Redis开发与运维

How Twitter Uses Redis To Scale – 105TB RAM, 39MM QPS, 10,000+ Instances

Latency Numbers Every Programmer Should Know


推荐阅读
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • Monkey《大话移动——Android与iOS应用测试指南》的预购信息发布啦!
    Monkey《大话移动——Android与iOS应用测试指南》的预购信息已经发布,可以在京东和当当网进行预购。感谢几位大牛给出的书评,并呼吁大家的支持。明天京东的链接也将发布。 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • Windows7 64位系统安装PLSQL Developer的步骤和注意事项
    本文介绍了在Windows7 64位系统上安装PLSQL Developer的步骤和注意事项。首先下载并安装PLSQL Developer,注意不要安装在默认目录下。然后下载Windows 32位的oracle instant client,并解压到指定路径。最后,按照自己的喜好对解压后的文件进行命名和压缩。 ... [详细]
  • RouterOS 5.16软路由安装图解教程
    本文介绍了如何安装RouterOS 5.16软路由系统,包括系统要求、安装步骤和登录方式。同时提供了详细的图解教程,方便读者进行操作。 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • 上图是InnoDB存储引擎的结构。1、缓冲池InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。因此可以看作是基于磁盘的数据库系统。在数据库系统中,由于CPU速度 ... [详细]
  • Hibernate延迟加载深入分析-集合属性的延迟加载策略
    本文深入分析了Hibernate延迟加载的机制,特别是集合属性的延迟加载策略。通过延迟加载,可以降低系统的内存开销,提高Hibernate的运行性能。对于集合属性,推荐使用延迟加载策略,即在系统需要使用集合属性时才从数据库装载关联的数据,避免一次加载所有集合属性导致性能下降。 ... [详细]
  • 本文介绍了如何使用PHP向系统日历中添加事件的方法,通过使用PHP技术可以实现自动添加事件的功能,从而实现全局通知系统和迅速记录工具的自动化。同时还提到了系统exchange自带的日历具有同步感的特点,以及使用web技术实现自动添加事件的优势。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • 微信官方授权及获取OpenId的方法,服务器通过SpringBoot实现
    主要步骤:前端获取到code(wx.login),传入服务器服务器通过参数AppID和AppSecret访问官方接口,获取到OpenId ... [详细]
  • 本文讨论了如何使用GStreamer来删除H264格式视频文件中的中间部分,而不需要进行重编码。作者提出了使用gst_element_seek(...)函数来实现这个目标的思路,并提到遇到了一个解决不了的BUG。文章还列举了8个解决方案,希望能够得到更好的思路。 ... [详细]
author-avatar
稚气忖托气质_844
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有