当前位置: 首页 > news >正文

电子商务网站功能页面/个人网站怎么建立

电子商务网站功能页面,个人网站怎么建立,宁波网站制作哪家全面,手机在线查看html源代码对象共享、内存优化对象的引用计数对象共享为什么开启maxmemory和LRU淘汰策略后对象池无效?(面试题)为什么Redis不共享包含字符串的对象?(面试题)对象的空转时长内存消耗内存使用统计内存消耗划分对象内存缓冲内存内存碎片子进程内存消耗内存管理设置内存…

对象共享、内存优化

  • 对象的引用计数
  • 对象共享
    • 为什么开启maxmemory和LRU淘汰策略后对象池无效?(面试题)
    • 为什么Redis不共享包含字符串的对象?(面试题)
  • 对象的空转时长
  • 内存消耗
    • 内存使用统计
    • 内存消耗划分
      • 对象内存
      • 缓冲内存
      • 内存碎片
    • 子进程内存消耗
  • 内存管理
    • 设置内存上限
    • 动态调整内存上限
  • 内存回收策略(重要!!!)
    • 删除过期键对象
    • 内存溢出控制策略
  • 内存优化
    • 了解redisObjec对象
    • 缩减键值对象(长度)
    • 共享对象池
    • 字符串优化(embstr编码)
    • 编码(类型)优化(重要!!!)
      • Redis为什么对一种数据结构实现多种编码方式?(面试题)
      • 短(数据)结构
    • 控制键的数量(选择数据类型同时也牵扯编码类型)
      • hash键和field键的设计
    • 分片结构(待完善)

对象的引用计数

因为C语言并不具备自动内存回收功能,所以Redis在自己的对象系统中构建了一个引用计数(reference counting)技术实现的内存回收机制
通过这一机制,程序可以通过跟踪对象的引用计数信息,在适当的时候自动释放对象并进行内存回收

每个对象的引用计数信息由redisObject结构的refcount属性记录:

typedef struct redisObject {// ...// 引用计数int refcount;// ...
} robj;

对象的引用计数信息 会随着 对象的使用状态而不断变化

  • 在创建一个新对象时,引用计数的值会被初始化为1
  • 当对象被一个新程序使用时,它的引用计数值会被增一
  • 当对象不再被一个程序使用时,它的引用计数值会被减一
  • 当对象的引用计数值变为0时,对象所占用的内存会被释放

对象的整个生命周期可以划分为创建对象、操作对象、释放对象三个阶段

对象共享

除了用于实现引用计数内存回收机制之外,对象的引用计数属性还带有对象共享的作用

假设键A创建了一个包含整数值100的字符串对象作为值对象
如果这时键B也要创建一个同样保存了整数值100的字符串对象作为值对象,那么服务器有以下两种做法:

  1. 为键B新创建一个包含整数值100的字符串对象
  2. 让键A和键B共享同一个字符串对象

以上两种方法很明显是第二种方法更节约内存

在Redis中,让多个键共享同一个值对象需要执行以下两个步骤:

  1. 将 数据库键 的 值指针 指向 一个现有的值对象
  2. 将 被共享的值对象 的 引用计数 增一

目前来说,Redis会在初始化服务器时,创建一万个字符串对象,这些对象包含了从0到9999的所有整数值,当服务器需要用到值为0到9999的字符串对象时,服务器就会使用这些共享对象,而不是新创建对象
创建共享字符串对象的数量可以通过修改redis.h/REDIS_SHARED_INTEGERS常量来修改
可以通过object refcount命令查看对象引用数验证是否启用整数对象池技术

这些共享对象 不单单只有 字符串键可以使用,那些 在数据结构中 嵌套了 字符串对象的对象(linkedlist编码的列表对象、hashtable编码的哈希对象、hashtable编码的集合对象,以及zset编码的有序集合对象)都可以使用这些共享对象
对于ziplist编码的值对象,即使内部数据为整数也无法使用共享对象池,因为ziplist使用压缩且内存连续的结构,对象共享判断成本过高

当设置maxmemory并启用LRU相关淘汰策略如:volatile-lru,allkeys-lru时,Redis禁止使用共享对象池

为什么开启maxmemory和LRU淘汰策略后对象池无效?(面试题)

LRU算法 需要获取 对象最后被访问时间,以便淘汰最长未访问数据,每个对象最后访问时间存储在redisObject对象的lru字段
对象共享意味着多个引用共享同一个redisObject,这时lru字段也会被共享,导致无法获取每个对象的最后访问时间
如果没有设置maxmemory,直到内存被用尽Redis也不会触发内存回收,所以共享对象池可以正常工作

为什么Redis不共享包含字符串的对象?(面试题)

当服务器 考虑 将一个 共享对象 设置为 键的值对象时,程序需要先检查 给定的共享对象 和 键想创建的目标对象 是否完全相同
只有在共享对象和目标对象完全相同的情况下,程序才会将共享对象用作键的值对象
而一个共享对象保存的值越复杂,验证共享对象和目标对象是否相同所需的复杂度就会越高,消耗的CPU时间也会越多

  • 如果共享对象是保存整数值的字符串对象,那么验证操作的复杂度为O(1)
  • 如果共享对象是保存字符串值的字符串对象,那么验证操作的复杂度为O(N)
  • 如果共享对象是包含了多个值(或者对象的)对象,比如列表对象或者哈希对象,那么验证操作的复杂度将会是O(N 2)

因此,尽管共享更复杂的对象可以节约更多的内存,但受到CPU时间的限制,Redis只对包含整数值的字符串对象进行共享

对象的空转时长

除了type、encoding、ptr和refcount四个属性之外,redisObject结构包含的最后一个属性为lru属性,该属性记录了对象最后一次被命令程序访问的时间

typedef struct redisObject {// ...unsigned lru:22;// ...
} robj;

OBJECT IDLETIME命令可以打印出给定键的空转时长,这一空转时长 就是通过 将当前时间 减去 键的值对象的lru时间计算得出的

redis> SET msg "hello world"
OK
# 等待一小段时间
redis> OBJECT IDLETIME msg
(integer) 20
# 等待一阵子
redis> OBJECT IDLETIME msg
(integer) 180
#访问msg键的值
redis> GET msg
"hello world"
# 键处于活跃状态,空转时长为0 
redis> OBJECT IDLETIME msg
(integer) 0

OBJECT IDLETIME命令的实现是特殊的,这个命令在访问键的值对象时,不会修改值对象的lru属性

除了可以被OBJECT IDLETIME命令打印出来之外,键的空转时长还有另外一项作用:如果服务器打开了maxmemory选项,并且服务器用于回收内存的算法为volatile-lru或者allkeys-lru,那么当服务器占用的内存数超过了maxmemory选项所设置的上限值时,空转时长较高的那部分键会优先被服务器释放,从而回收内存

内存消耗

内存使用统计

Redis自身使用内存的统计数据可通过执行info memory命令获取内存相关指标
在这里插入图片描述在这里插入图片描述
需要重点关注的指标有used_memory_rssused_memory以及它们的比值mem_fragmentation_ratio

  • mem_fragmentation_ratio>1时,说明used_memory_rss - used_memory多出的部分内存 并没有用于 数据存储,而是被内存碎片所消耗,如果两者相差很大,说明碎片率严重
  • mem_fragmentation_ratio<1时,这种情况一般出现在 操作系统 把Redis内存交换(Swap)到硬盘导致,出现这种情况时要格外关注,由于硬盘速度远远慢于内存,Redis性能会变得很差,甚至僵死

内存消耗划分

Redis进程内消耗主要包括:自身内存 + 对象内存 + 缓冲内存 + 内存碎片
其中Redis空进程自身内存消耗非常少,通常used_memory_rss在3MB左右,used_memory在800KB左右,一个空的Redis进程消耗内存可以忽略不计

在这里插入图片描述

对象内存

对象内存是Redis内存占用最大的一块,存储着用户所有的数据
Redis所有的数据都采用key-value数据类型,每次创建键值对时,至少创建两个类型对象:key对象和value对象

对象内存消耗可以简单理解为sizeof(keys)+sizeof(values)
键对象都是字符串,在使用Redis时很容易忽略键对内存消耗的影响,应当避免使用过长的键

value对象更复杂些,主要包含5种基本数据类型:字符串、列表、哈希、集合、有序集合
其他数据类型都是建立在这5种数据结构之上实现的,如:Bitmaps和HyperLogLog使用字符串实现,GEO使用有序集合实现等
每种value对象类型根据使用规模不同,占用内存不同。
使用时一定要合理预估并监控value对象占用情况,避免内存溢出

缓冲内存

缓冲内存主要包括:客户端缓冲、复制积压缓冲区、AOF缓冲区

客户端缓冲 指的是 所有接入到Redis服务器TCP连接 的 输入输出缓冲
输入缓冲无法控制,最大空间为1G,如果超过将断开连接
输出缓冲通过参数client-output-buffer-limit控制,有以下几种客户端:

  • 普通客户端:除了复制和订阅的客户端之外的所有连接,Redis的默认配置是:client-output-buffer-limit normal 0 0 0,Redis并没有对普通客户端的输出缓冲区做限制,一般普通客户端的内存消耗可以忽略不计,但是当有大量慢连接客户端接入时这部分内存消耗就不能忽略了,可以设置maxclients做限制。特别是 当使用 大量数据输出的命令 且 数据无法及时推送给客户端时,如monitor命令,容易造成Redis服务器内存突然飙升
  • 从客户端:主节点会为每个从节点单独建立一条连接用于命令复制,默认配置是:client-output-buffer-limit slave 256mb 64mb 60。当主从节点之间网络延迟较高 或 主节点挂载大量从节点时 这部分内存消耗将 占用很大一部分,建议主节点挂载的从节点不要多于2个,主从节点不要部署在较差的网络环境下,如异地跨机房环境,防止复制客户端连接缓慢造成溢出
  • 订阅客户端:当使用发布订阅功能时,连接客户端 使用 单独的输出缓冲区,默认配置为:client-output-buffer-limit pubsub 32mb 8mb 60,当订阅服务的消息生产快于消费速度时,输出缓冲区会产生积压造成输出缓冲区空间溢出

复制积压缓冲区:Redis在2.8版本之后提供了一个 可重用的 固定大小缓冲区 用于实现 部分复制功能,根据repl-backlog-size参数控制,默认1MB
对于复制积压缓冲区整个主节点只有一个,所有的从节点共享此缓冲区,因此可以设置较大的缓冲区空间,如100MB,这部分内存投入是有价值的,可以有效避免全量复制

AOF缓冲区:这部分空间用于 在Redis重写期间 保存 最近的写入命令,AOF缓冲区空间消耗用户无法控制,消耗的内存取决于AOF重写时间和写入命令量,这部分空间占用通常很小

内存碎片

Redis默认的内存分配器采用jemalloc,可选的分配器还有:glibc、tcmalloc
内存分配器为了更好地管理和重复利用内存,分配内存策略一般采用固定范围的内存块进行分配

内存碎片问题虽然是所有内存服务的通病,但是jemalloc针对碎片化问题专门做了优化,一般不会存在过度碎片化的问题,正常的碎片率(mem_fragmentation_ratio)在1.03左右
但是当存储的数据长短差异较大时,以下场景容易出现高内存碎片问题:

  • 频繁做更新操作,例如频繁对已存在的键执行append、setrange等更新操作
  • 大量过期键删除,键对象过期删除后,释放的空间无法得到充分利用,导致碎片率上升

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

  • 数据对齐:在条件允许的情况下尽量做数据对齐,比如数据尽量采用数字类型或者固定长度字符串等,但是这要视具体的业务而定,有些场景无法做到
  • 安全重启:重启节点可以做到内存碎片重新整理,因此可以利用高可用架构,如Sentinel或Cluster,将碎片率过高的主节点转换为从节点,进行安全重启

子进程内存消耗

子进程内存消耗 主要指 执行AOF/RDB重写时 Redis创建的子进程 内存消耗
Redis执行fork操作 产生的子进程内存占用量 对外表现为 与父进程相同,理论上需要一倍的物理内存来完成重写操作
但Linux具有写时复制技术(copy-on-write),父子进程会共享相同的物理内存页
当 父进程 处理写请求时 会对 需要修改的页 复制出一份 副本完成写操作,而 子进程依然读取 fork时 整个父进程的内存快照

子进程内存消耗总结如下:

  • Redis产生的子进程并不需要消耗1倍的父进程内存,实际消耗根据期间写入命令量决定,但是依然要预留出一些内存防止溢出
  • 需要设置sysctl vm.overcommit_memory=1允许内核可以分配所有的物理内存,防止Redis进程执行fork时因系统剩余内存不足而失败
  • 排查当前系统是否支持并开启THP,如果开启建议关闭,防止copy-on-write期间内存过度消耗

内存管理

设置内存上限

Redis使用maxmemory参数限制最大可用内存。限制内存的目的主要有:

  • 用于缓存场景,当超出内存上限maxmemory时使用LRU等删除策略释放空间
  • 防止所用内存超过服务器物理内存

需要注意,maxmemory 限制的是 Redis实际使用的 内存量,也就是used_memory统计项对应的内存
由于内存碎片率的存在,实际消耗的内存可能会比maxmemory设置的更大,实际使用时要小心这部分内存溢出

通过设置内存上限 可以非常方便地实现 一台服务器部署多个Redis进程的内存控制

比如一台24GB内存的服务器,为系统预留4GB内存,预留4GB空闲内存给其他进程或Redis fork进程,留给Redis16GB内存,这样可以部署4个maxmemory=4GB的Redis进程。得益于Redis单线程架构和内存限制机制,即使没有采用虚拟化,不同的Redis进程之间也可以很好地实现CPU和内存的隔离性

动态调整内存上限

Redis的内存上限可以通过config set maxmemory进行动态修改,即修改最大可用内存

Redis-1>config set maxmemory 6GB
Redis-2>config set maxmemory 2GB

通过动态修改maxmemory,可以实现在当前服务器下动态伸缩Redis内存的目的

Redis默认无限使用服务器内存,为防止极端情况下导致系统内存耗尽,建议所有的Redis进程都要配置maxmemory

在保证物理内存可用的情况下,系统中所有Redis实例可以调整maxmemory参数来达到自由伸缩内存的目的

内存回收策略(重要!!!)

Redis的内存回收机制主要体现在以下两个方面:

  • 删除到达过期时间的键对象
  • 内存使用达到maxmemory上限时触发内存溢出控制策略

删除过期键对象

Redis所有的键都可以设置过期属性,内部保存在过期字典中
由于进程内保存大量的键,维护每个键精准的过期删除机制会导致消耗大量的CPU,对于单线程的Redis来说成本过高,因此Redis采用惰性删除和定时任务删除机制实现过期键的内存回收

  • 惰性删除:惰性删除 用于 当客户端读取带有超时属性的键时,如果已经超过键设置的过期时间,会执行删除操作并返回空,这种策略是出于节省CPU成本考虑,不需要单独维护TTL链表来处理过期键的删除。但是单独用这种方式存在内存泄露的问题,当过期键一直没有访问将无法得到及时删除,从而导致内存不能及时释放。正因为如此,Redis还提供另一种定时任务删除机制作为惰性删除的补充
  • 定时任务删除:Redis内部维护一个定时任务,默认每秒运行10次(通过配置hz控制)。定时任务中 删除过期键逻辑 采用了自适应算法,根据键的过期比例、使用快慢两种速率模式回收键

阅读参考:Redis的过期键删除策略(惰性删除、定时删除、 定期删除)及备份和复制对于过期键处理

内存溢出控制策略

当Redis所用内存达到maxmemory上限时会触发相应的溢出控制策略
具体策略受maxmemory-policy参数控制,Redis支持6种策略,如下所示:

  1. noeviction:默认策略,不会删除任何数据,拒绝所有写入操作并返回客户端错误信息(error)OOM command not allowed when used memory,此时Redis只响应读操作
  2. volatile-lru:根据LRU算法 删除 设置了超时属性(expire)的键,直到腾出足够空间为止。如果没有可删除的键对象,回退到noeviction策略
  3. allkeys-lru:根据LRU算法删除键,不管数据有没有设置超时属性,直到腾出足够空间为止
  4. allkeys-random:随机删除所有键,直到腾出足够空间为止
  5. volatile-random:随机删除过期键,直到腾出足够空间为止
  6. volatile-ttl:根据键值对象的ttl属性,删除最近将要过期数据。如果没有,回退到noeviction策略

内存溢出控制策略可以采用config set maxmemory-policy{policy}动态配置

Redis支持丰富的内存溢出应对策略,可以根据实际需求灵活定制,比如当设置volatile-lru策略时,保证具有过期属性的键可以根据LRU剔除,而未设置超时的键可以永久保留
还可以采用allkeys-lru策略把Redis变为纯缓存服务器使用

当Redis因为内存溢出删除键时,可以通过执行info stats命令查看evicted_keys指标找出当前Redis服务器已剔除的键数量

每次Redis执行命令时如果设置了maxmemory参数,都会尝试执行回收内存操作
当Redis一直工作在**内存溢出(used_memory > maxmemory)**的状态下 且 设置非noeviction策略时,会频繁地触发回收内存的操作,影响Redis服务器的性能

频繁执行回收内存成本很高,主要包括查找可回收键和删除键的开销,如果当前Redis有从节点,回收内存操作对应的删除命令会同步到从节点,导致写放大的问题,如下所示:
在这里插入图片描述

建议线上Redis内存工作在maxmemory > used_memory状态下,避免频繁内存回收开销

对于需要收缩Redis内存的场景,可以通过调小maxmemory来实现快速回收
比如对一个实际占用6GB内存的进程设置maxmemory=4GB,之后第一次执行命令时,如果使用非noeviction策略,它会一次性回收到maxmemory指定的内存量,从而达到快速回收内存的目的
注意,此操作会导致数据丢失和短暂的阻塞问题,一般在缓存场景下使用

内存优化

了解redisObjec对象

Redis存储的数据都使用redisObject来封装,包括string、hash、list、set、zset在内的所有数据类型。理解redisObject对内存优化非常有帮助
在这里插入图片描述

  • type字段:表示当前对象使用的数据类型,Redis主要支持5种数据类型:string、hash、list、set、zset。可以使用type {key}命令查看对象所属类型,type命令返回的是值对象类型,键都是string类型

  • encoding字段:表示Redis内部编码类型,encoding在Redis内部使用,代表 当前对象内部 采用哪种数据结构实现。理解Redis内部编码方式对于优化内存非常重要,同一个对象采用不同的编码实现内存占用存在明显差异

  • lru字段:记录对象最后一次被访问的时间,当配置了maxmemorymaxmemory-policy=volatile-lru或者allkeys-lru时,用于辅助LRU算法删除键数据。可以使用object idletime {key}命令在不更新lru字段情况下查看当前键的空闲时间

    可以使用scan + object idletime命令 批量查询 哪些键 长时间未被访问,找出长时间不访问的键进行清理,可降低内存占用。

  • refcount字段:记录 当前对象 被引用的次数,用于通过引用次数回收内存,当refcount=0时,可以安全回收当前对象空间。使用object refcount {key}获取当前对象引用。当对象为整数且范围在[0-9999]时,Redis可以使用共享对象的方式来节省内存

  • *ptr字段:与对象的数据内容相关,如果是整数,直接存储数据;否则 表示 指向数据的指针。Redis在3.0之后 对 值对象 是 字符串且长度<=39字节的数据,内部编码为embstr类型,字符串sds和redisObject一起分配,从而只要一次内存操作即可

    高并发写入场景中,在条件允许的情况下,建议字符串长度控制在39字节以内,减少创建redisObject内存分配次数,从而提高性能,阅读参考:Redis数据类型(二)-字符串对象

缩减键值对象(长度)

降低Redis内存使用最直接的方式就是缩减键和值的长度

  • key长度:如在设计键时,在完整描述业务情况下,键值越短越好

  • value长度:值对象缩减比较复杂,常见需求是把业务对象序列化成二进制数组放入Redis

    首先应该在业务上精简业务对象,去掉不必要的属性避免存储无效数据
    其次在序列化工具选择上,应该选择更高效的序列化工具来降低字节数组大小
    以Java为例,内置的序列化方式无论从速度还是压缩比都不尽如人意,这时可以选择更高效的序列化工具,如:protostuff、kryo等

    值对象除了存储二进制数据之外,通常还会使用通用格式存储数据比如:json、xml等作为字符串存储在Redis中
    这种方式优点是方便调试和跨语言,但是同样的数据相比字节数组所需的空间更大,在内存紧张的情况下,可以使用通用压缩算法压缩json、xml后再存入Redis,从而降低内存占用,例如使用GZIP压缩后的json可降低约60%的空间(面试可能会被问到如何优化json保存redis)

共享对象池

参考上面的对象共享

字符串优化(embstr编码)

首先要了解字符串数据结构,阅读参考:

  • Redis数据结构(一)-简单动态字符串(simple dynamic string,SDS)
  • Redis数据类型(二)-字符串对象

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

字符串 之所以采用 预分配的方式 是防止 修改操作 需要 不断重分配内存 和 字节数据拷贝
字符串预分配每次并不都是翻倍扩容,空间预分配规则如下:

  1. 第一次创建len属性等于数据实际大小,free等于0,不做预分配
  2. 修改后如果已有free空间不够且数据小于1M,每次预分配一倍容量。如原有len=60byte,free=0,再追加60byte,预分配120byte,总占用空间:60byte+60byte+120byte+1byte
  3. 修改后如果已有free空间不够且数据大于1MB,每次预分配1MB数据。如原有len=30MB,free=0,当再追加100byte,预分配1MB,总占用空间:1MB+100byte+1MB+1byte

尽量减少字符串频繁修改操作如append、setrange,改为直接使用set修改字符串,降低 预分配 带来的内存浪费 和 内存碎片化

编码(类型)优化(重要!!!)

首先要了解对象编码类型,阅读参考:Redis数据类型(一)-对象(常说的数据类型)
在这里再次回顾一下,数据类型 和 编码方式 关系如下:
在这里插入图片描述编码类型转换 在 Redis写入数据时 自动完成,这个转换过程是不可逆的
转换规则只能从小内存编码向大内存编码转换

Redis之所以不支持编码回退,主要是数据增删频繁时,数据向压缩编码转换非常消耗CPU,得不偿失

具体编码配置如下:

在这里插入图片描述在这里插入图片描述理解编码转换流程和相关配置之后,可以使用config set命令 设置 编码相关参数 来满足 使用压缩编码的条件
对于已经采用 非压缩编码类型的数据 如hashtable、linkedlist等,设置参数后 即使 数据 满足 压缩编码条件,Redis也不会做转换,需要重启Redis重新加载数据才能完成转换

Redis为什么对一种数据结构实现多种编码方式?(面试题)

主要原因是Redis作者 想通过 不同编码 实现 效率和空间的平衡

比如当存储只有10个元素的列表,当使用双向链表数据结构时,必然需要维护大量的内部字段如每个元素需要:前置指针,后置指针,数据指针等,造成空间浪费,如果采用连续内存结构的压缩列表(ziplist),将会节省大量内存,而由于数据长度较小,存取操作时间复杂度即使为O(n2)性能也可满足需求

短(数据)结构

在列表、散列和有序集合的长度较短或者体积较小的时候,Redis可以选择使用压缩列表(ziplist)的紧凑存储方式来存储这些结构
压缩列表是列表、散列和有序集合这3种不同类型的对象的一种非结构化(unstructured)表示

与Redis在通常情况下使用双链表表示列表、使用散列表表示散列、使用散列表加上跳跃表(skiplist)表示有序集合的做法不同

压缩列表会以序列化的方式存储数据,这些序列化数据每次被读取的时候都要进行解码,每次被写入的时候也要进行局部的重新编码,并且可能需要对内存里面的数据进行移动

控制键的数量(选择数据类型同时也牵扯编码类型)

相较于使用字符串作为key,hash结构可以降低键数量
hash的field可用于记录原始key字符串,方便哈希查找
hash的value保存原始值对象,确保不要超过hash-max-ziplist-value限制

同样的数据使用ziplist编码的hash(数据)类型存储 比 string(数据)类型节约内存

  • 节省内存量 随着 value空间(值大小)的减少越来越明显
  • hash(数据类型)-ziplist(编码类型)类型 比 string类型写入耗时,但随着value空间(值大小)的减少,耗时逐渐降低

使用hash重构后节省内存量效果非常明显,特别对于存储小对象的场景,内存只有不到原来的1/5

这种内存优化技巧的关键点如下

  1. hash类型节省内存的原理 是 使用ziplist编码,如果使用hashtable编码方式反而会增加内存消耗
  2. ziplist长度需要控制在1000以内,否则由于存取操作时间复杂度在O(n)到O(n2)之间,长列表会导致CPU消耗严重,得不偿失
  3. ziplist适合存储小对象,对于大对象 不但 内存优化效果不明显 还会增加 命令操作耗时
  4. 需要预估 键的规模,从而确定每个hash结构需要存储的元素数量
  5. 根据hash长度和元素大小,调整hash-max-ziplist-entrieshash-max-ziplist-value参数,确保hash类型使用ziplist编码

hash键和field键的设计

  • 当键离散度较高时,可以按字符串位截取,把后三位作为哈希的field,之前部分作为哈希的键
  • 当键离散度较低时,可以使用哈希算法打散键,如:使用crc32(key)&10000函数把所有的键映射到“0-9999”整数范围内,哈希field存储键的原始值
  • 尽量减少hash键和field的长度,如使用部分键内容

使用hash结构控制键的规模虽然可以大幅降低内存,但同样会带来问题,需要提前做好规避处理。如下所示:

  • 客户端 需要预估 键的规模并设计hash分组规则,加重客户端开发成本
  • hash重构后 所有的键 无法再使用超时(expire) 和 LRU淘汰机制自动删除,需要手动维护删除
  • 对于大对象,如1KB以上的对象,使用hash-ziplist结构控制键数量反而得不偿失

分片结构(待完善)

http://www.lbrq.cn/news/1532683.html

相关文章:

  • 西安网站设计西安搜推宝/app拉新放单平台
  • 安阳手机网站建设/免费发布推广的网站有哪些
  • 部门网站建设宗旨/百度大数据分析平台
  • 公众号在哪里找/seo挂机赚钱
  • 做时彩网站违法吗/培训机构招生方案
  • 地接做的网站/百度竞价推广教程
  • 孙俪做的网站广告/精准营销平台
  • 动态网站开发过程/苏州seo报价
  • 网站手机模板的特点/yandex搜索引擎
  • 专门做童装的网站有哪些/国家新闻最新消息今天
  • 网站商城系统/最近三天的新闻大事
  • php抗议小卫士填报代码网页制作网站/百度一下你知道主页官网
  • 鞍山站/搜索引擎优化的流程
  • wordpress页面的添加背景音乐/网站seo诊断
  • jsp网站开发详解 pdf/百度关键词搜索排名
  • 制作logo的网站/软文营销方法有哪些
  • 南京浦口做网站点/我要推广
  • 建设网站要不要投资钱/2000元代理微信朋友圈广告
  • 大丰市市城乡建设局网站/友情链接交易平台
  • 厦门建设网站/电商运营培训课程
  • 湖北工程建设信息网/石家庄seo扣费
  • 交互式网站备案难吗/企业培训公司
  • 南宁网站建设产品/网络营销项目策划
  • 望城做网站找谁/抖音账号权重查询入口
  • 织梦模板如何安装/福州短视频seo推荐
  • 网站建设经费方案/百度指数人群画像
  • 京东网站设计的特点/2023年新闻摘抄十条
  • 哈尔滨微网站建设/google推广技巧
  • 淳安县建设局网站/网络推广代理怎么做
  • 软件开发工具平台/seo是什么化学名称
  • 健康常识查询系统|基于java和小程序的健康常识查询系统设计与实现(源码+数据库+文档)
  • 新手向:使用STM32通过RS485通信接口控制步进电机
  • 吱吱企业通讯软件保证内部通讯安全,搭建数字安全体系
  • c#联合halcon的基础教程(案例:亮度计算、角度计算和缺陷检测)(含halcon代码)
  • GEO 优化专家孟庆涛:技术破壁者重构 AI 时代搜索逻辑
  • NestJS 依赖注入方式全解