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

世纪兴网站建设潍坊网站建设 APP开发小程序

世纪兴网站建设,潍坊网站建设 APP开发小程序,网页设计公司简介代码,大朗镇做网站【内存消耗】 场景#xff1a;业务ID-图片ID#xff08;KV:partnerId-objectId#xff09;。 刚开始#xff0c;我们保存了1亿张图片#xff0c;大约用了6.4GB的内存。 随着图片数据量的不断增加#xff0c;Redis变慢了。 新的认知#xff1a;String类型并不是适…【内存消耗】 场景业务ID-图片IDKV:partnerId-objectId。 刚开始我们保存了1亿张图片大约用了6.4GB的内存。 随着图片数据量的不断增加Redis变慢了。 新的认知String类型并不是适用于所有场合的它有一个明显的短板就是它保存数据时所消耗的内存空间较多。 新的解法集合类型有非常节省内存空间的底层实现结构。 1.String类型的内存空间消耗在哪儿了 2.用什么数据结构可以节省内存 3.如何用集合类型保存单值键值对 【损耗原因】 1.底层数据结构SDS损耗除了记录实际数据还需要额外的内存空间记录数据长度、空间使用等信息这些信息也叫作元数据。 buf字节数组保存实际数据。为了表示字节数组的结束Redis会自动在数组最后加一个“0”这就会额外占用1个字节的开销。 len占4个字节表示buf的已用长度。 alloc也占个4字节表示buf的实际分配长度一般大于len。 SDS中buf保存实际数据而len和alloc本身其实是SDS结构体的额外开销。 2.RedisObject损耗不同数据类型都有些相同的元数据要记录比如最后一次访问的时间、被引用的次数等RedisObject结构体来统一记录这些元数据同时指向实际数据。 一个RedisObject包含了8字节的元数据和一个8字节指针这个指针再进一步指向具体数据类型的实际数据所在例如指向String类型的SDS结构所在的内存地址可以看一下下面的示意图 【类型优化】 当你保存64位有符号整数时String类型会把它保存为一个8字节的Long类型整数这种保存方式通常也叫作int编码方式。 为了节省内存空间Redis还对Long类型整数和SDS的内存布局做了专门的设计。 1.Long类型整RedisObject中的指针就直接赋值为整数数据了这样就不用额外的指针再指向整数了节省了指针的空间开销。 2.字符串数据。字符串小于等于44字节时RedisObject中的元数据、指针和SDS是一块连续的内存区域这样就可以避免内存碎片。这种布局方式也被称为embstr编码方式当字符串大于44字节时SDS的数据量就开始变多了Redis就不再把SDS和RedisObject布局在一起了而是会给SDS分配独立的空间并用指针指向SDS结构。这种布局方式被称为raw编码模式。 【内存占用】 每个int编码的RedisObject元数据部分占8字节指针部分被直接赋值为8字节的整数了。 每个ID会使用16字节加起来一共是32字节。但是另外的32字节去哪儿了呢 Redis会使用一个全局哈希表保存所有键值对哈希表的每一项是一个dictEntry的结构体用来指向一个键值对。 dictEntry结构中有三个8字节的指针分别指向key、value以及下一个dictEntry三个指针共24字节。 但是这三个指针只有24字节为什么会占用了32字节呢这就要提到Redis使用的内存分配库jemalloc了。 【jemalloc】 jemalloc在分配内存时会根据我们申请的字节数N找一个比N大但是最接近N的2的幂次数作为分配的空间这样可以减少频繁分配的次数。 举个例子。如果你申请6字节空间jemalloc实际会分配8字节空间如果你申请24字节空间jemalloc则会分配32字节。所以在我们刚刚说的场景里dictEntry结构就占用了32字节。 好了到这儿你应该就能理解为什么用String类型保存图片ID和图片存储对象ID时需要用64个字节了。 你看明明有效信息只有16字节使用String类型保存时却需要64字节的内存空间有48字节都没有用于保存实际的数据。我们来换算下如果要保存的图片有1亿张那么1亿条的图片ID记录就需要6.4GB内存空间其中有4.8GB的内存空间都用来保存元数据了额外的内存空间开销很大。那么有没有更加节省内存的方法呢 【ziplist】 用什么数据结构可以节省内存 Redis有一种底层数据结构叫压缩列表ziplist这是一种非常节省内存的结构。 我们先回顾下压缩列表的构成。表头有三个字段zlbytes、zltail和zllen分别表示列表长度、列表尾的偏移量以及列表中的entry个数。压缩列表尾还有一个zlend表示列表结束。 压缩列表之所以能节省内存就在于它是用一系列连续的entry保存数据。每个entry的元数据包括下面几部分。 prev_len表示前一个entry的长度。prev_len有两种取值情况1字节或5字节。取值1字节时表示上一个entry的长度小于254字节。虽然1字节的值能表示的数值范围是0到255但是压缩列表中zlend的取值默认是255因此就默认用255表示整个压缩列表的结束其他表示长度的地方就不能再用255这个值了。所以当上一个entry长度小于254字节时prev_len取值为1字节否则就取值为5字节。 len表示自身长度4字节 encoding表示编码方式1字节 content保存实际数据。 这些entry会挨个儿放置在内存中不需要再用额外的指针进行连接这样就可以节省指针所占用的空间。 我们以保存图片存储对象ID为例来分析一下压缩列表是如何节省内存空间的。 每个entry保存一个图片存储对象ID8字节此时每个entry的prev_len只需要1个字节就行因为每个entry的前一个entry长度都只有8字节小于254字节。这样一来一个图片的存储对象ID所占用的内存大小是14字节141814实际分配16字节。 Redis基于压缩列表实现了List、Hash和Sorted Set这样的集合类型这样做的最大好处就是节省了dictEntry的开销。当你用String类型时一个键值对就有一个dictEntry要用32字节空间。但采用集合类型时一个key就对应一个集合的数据能保存的数据多了很多但也只用了一个dictEntry这样就节省了内存。 【hash】 这个方案听起来很好但还存在一个问题在用集合类型保存键值对时一个键对应了一个集合的数据但是在我们的场景中一个图片ID只对应一个图片的存储对象ID我们该怎么用集合类型呢换句话说在一个键对应一个值也就是单值键值对的情况下我们该怎么用集合类型来保存这种单值键值对呢 如何用集合类型保存单值的键值对 在保存单值的键值对时可以采用基于Hash类型的二级编码方法。这里说的二级编码就是把一个单值的数据拆分成两部分前一部分作为Hash集合的key后一部分作为Hash集合的value这样一来我们就可以把单值数据保存到Hash集合中了。 以图片ID 1101000060和图片存储对象ID 3302000080为例我们可以把图片ID的前7位1101000作为Hash类型的键把图片ID的最后3位060和图片存储对象ID分别作为Hash类型值中的key和value。 按照这种设计方法我在Redis中插入了一组图片ID及其存储对象ID的记录并且用info命令查看了内存开销我发现增加一条记录后内存占用只增加了16字节如下所示 127.0.0.1:6379 info memory # Memory used_memory:1039120 127.0.0.1:6379 hset 1101000 060 3302000080 (integer) 1 127.0.0.1:6379 info memory # Memory used_memory:1039136 在使用String类型时每个记录需要消耗64字节这种方式却只用了16字节所使用的内存空间是原来的1/4满足了我们节省内存空间的需求。 不过你可能也会有疑惑“二级编码一定要把图片ID的前7位作为Hash类型的键把最后3位作为Hash类型值中的key吗”其实二级编码方法中采用的ID长度是有讲究的。 在第2讲中我介绍过Redis Hash类型的两种底层实现结构分别是压缩列表和哈希表。 那么Hash类型底层结构什么时候使用压缩列表什么时候使用哈希表呢其实Hash类型设置了用压缩列表保存数据时的两个阈值一旦超过了阈值Hash类型就会用哈希表来保存数据了。 这两个阈值分别对应以下两个配置项 hash-max-ziplist-entries表示用压缩列表保存时哈希集合中的最大元素个数。 hash-max-ziplist-value表示用压缩列表保存时哈希集合中单个元素的最大长度。 如果我们往Hash集合中写入的元素个数超过了hash-max-ziplist-entries或者写入的单个元素大小超过了hash-max-ziplist-valueRedis就会自动把Hash类型的实现结构由压缩列表转为哈希表。 一旦从压缩列表转为了哈希表Hash类型就会一直用哈希表进行保存而不会再转回压缩列表了。在节省内存空间方面哈希表就没有压缩列表那么高效了。 为了能充分使用压缩列表的精简内存布局我们一般要控制保存在Hash集合中的元素个数。所以在刚才的二级编码中我们只用图片ID最后3位作为Hash集合的key也就保证了Hash集合的元素个数不超过1000同时我们把hash-max-ziplist-entries设置为1000这样一来Hash集合就可以一直使用压缩列表来节省内存空间了。 小结 这节课我们打破了对String的认知误区以前我们认为String是“万金油”什么场合都适用但是在保存的键值对本身占用的内存空间不大时例如这节课里提到的的图片ID和图片存储对象IDString类型的元数据开销就占据主导了这里面包括了RedisObject结构、SDS结构、dictEntry结构的内存开销。 针对这种情况我们可以使用压缩列表保存数据。当然使用Hash这种集合类型保存单值键值对的数据时我们需要将单值数据拆分成两部分分别作为Hash集合的键和值就像刚才案例中用二级编码来表示图片ID希望你能把这个方法用到自己的场景中。 最后我还想再给你提供一个小方法如果你想知道键值对采用不同类型保存时的内存开销可以在这个网址里输入你的键值对长度和使用的数据类型这样就能知道实际消耗的内存大小了。建议你把这个小工具用起来它可以帮助你充分地节省内存。 每课一问 按照惯例给你提个小问题除了String类型和Hash类型你觉得还有其他合适的类型可以应用在这节课所说的保存图片的例子吗 欢迎在留言区写下你的思考和答案我们一起交流讨论也欢迎你把今天的内容分享给你的朋友。
http://www.dnsts.com.cn/news/216323.html

相关文章:

  • 学校网站首页模板网站关键词扩展
  • 做网站如何选主机中国做网站最好的公司
  • 网站域名怎么查询备案价格深圳网站建设服务哪个便宜点
  • 池州市建设工程造价管理网站网站制作一个人可以做吗
  • 校体育网站建设的好处软件开放和网站开发
  • 沭阳网站建设shy1z人人商城小程序
  • 建设视频网站费用吗做贸易要看什么网站
  • 设计师去哪个网站找工作织梦怎么制作网站
  • 深圳市建设培训中心网站企业网站登录
  • 做网站要学编程麽海南网站制作一网站建设
  • 无锡网站建设套餐南头手机公司网站建设
  • wordpress 4.8.2中文搜索引擎优化seo多少钱
  • 网站建设项目分析报告网络安全培训最强的机构
  • 设计制作一个企业类型网站seo的基本步骤包括哪些
  • windows 做网站服务器网站文章内容页keyword设置
  • 可以申请做cpa广告的网站北京企业网站开发费用
  • 网站建设与管理怎么样烟台 网站建设多少钱
  • 红光网站建设网站建设公司广州
  • 网站发布时间更改企业seo关键字优化
  • 做网站用软件如何做网站平台销售
  • 做网站建设多少钱网站dns设置
  • 企业网站 app小区物业管理网站开发报告
  • 个人能否做网站怎么制作宣传海报图片
  • 网站编辑工具软件手机特效视频制作软件免费
  • 网站搜索系统视频网站直播怎么做
  • 江苏省住房和建设部网站漳州博大网站建设
  • 安徽静安集团网站建设如何在网站做qq群链接
  • 专门做特产的网站网站开发所需经费
  • 东莞制作企业网站河南省城乡和住房建设厅网站首页
  • 好看的网站设计公司广州哪家做网站