游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

缓存空间优化实践

  作者:京东科技董健
  缓存Redis,是我们最常用的服务,其适用场景广泛,被大量应用到各业务场景中。也正因如此,缓存成为了重要的硬件成本来源,我们有必要从空间上做一些优化,降低成本的同时也会提高性能。
  下面以我们的案例说明,将缓存空间减少70的做法。场景设定
  1、我们需要将POJO存储到缓存中,该类定义如下publicclassTestPOJOimplementsSerializable{privateStringtestStatus;privateStringuserPin;privateStringinvestor;privateDatetestQueryTime;privateDatecreateTime;privateStringbizInfo;privateDateotherTime;privateBigDecimaluserAmount;privateBigDecimaluserRate;privateBigDecimalapplyAmount;privateStringtype;privateStringcheckTime;privateStringpreTestStatus;publicObject〔〕toValueArray(){Object〔〕array{testStatus,userPin,investor,testQueryTime,createTime,bizInfo,otherTime,userAmount,userRate,applyAmount,type,checkTime,preTestStatus};returnarray;}publicCreditRecordfromValueArray(Object〔〕valueArray){具体的数据类型会丢失,需要做处理}}
  2、用下面的实例作为测试数据TestPOJOpojonewTestPOJO();pojo。setApplyAmount(newBigDecimal(200。11));pojo。setBizInfo(XX);pojo。setUserAmount(newBigDecimal(1000。00));pojo。setTestStatus(SUCCESS);pojo。setCheckTime(20230202);pojo。setInvestor(ABCD);pojo。setUserRate(newBigDecimal(0。002));pojo。setTestQueryTime(newDate());pojo。setOtherTime(newDate());pojo。setPreTestStatus(PROCESSING);pojo。setUserPin(ABCDEFGHIJ);pojo。setType(Y);
  常规做法System。out。println(JSON。toJSONString(pojo)。length());
  使用JSON直接序列化、打印length284,这种方式是最简单的方式,也是最常用的方式,具体数据如下:
  {applyAmount:200。11,bizInfo:XX,checkTime:20230202,investor:ABCD,otherTime:2023041017:45:17。717,preCheckStatus:PROCESSING,testQueryTime:2023041017:45:17。717,testStatus:SUCCESS,type:Y,userAmount:1000。00,userPin:ABCDEFGHIJ,userRate:0。002}
  我们发现,以上包含了大量无用的数据,其中属性名是没有必要存储的。
  改进1去掉属性名System。out。println(JSON。toJSONString(pojo。toValueArray())。length());
  通过选择数组结构代替对象结构,去掉了属性名,打印length144,将数据大小降低了50,具体数据如下:
  〔SUCCESS,ABCDEFGHIJ,ABCD,2023041017:45:17。717,null,XX,2023041017:45:17。717,1000。00,0。002,200。11,Y,20230202,PROCESSING〕
  我们发现,null是没有必要存储的,时间的格式被序列化为字符串,不合理的序列化结果,导致了数据的膨胀,所以我们应该选用更好的序列化工具。
  改进2使用更好的序列化工具我们仍然选取JSON格式,但使用了第三方序列化工具System。out。println(newObjectMapper(newMessagePackFactory())。writeValueAsBytes(pojo。toValueArray())。length);
  选取更好的序列化工具,实现字段的压缩和合理的数据格式,打印length92,空间比上一步又降低了40。
  这是一份二进制数据,需要以二进制操作Redis,将二进制转为字符串后,打印如下:
  SUCCESSABCDEFGHIJABCDj6XXj6?bMiQY20230202PROCESSING
  顺着这个思路再深挖,我们发现,可以通过手动选择数据类型,实现更极致的优化效果,选择使用更小的数据类型,会获得进一步的提升。
  改进3优化数据类型
  在以上用例中,testStatus、preCheckStatus、investor这3个字段,实际上是枚举字符串类型,如果能够使用更简单数据类型(比如byte或者int等)替代string,还可以进一步节省空间。其中checkTime可以用Long类型替代字符串,会被序列化工具输出更少的字节。publicObject〔〕toValueArray(){Object〔〕array{toInt(testStatus),userPin,toInt(investor),testQueryTime,createTime,bizInfo,otherTime,userAmount,userRate,applyAmount,type,toLong(checkTime),toInt(preTestStatus)};returnarray;}
  在手动调整后,使用了更小的数据类型替代了String类型,打印length69
  改进4考虑ZIP压缩
  除了以上的几点之外,还可以考虑使用ZIP压缩方式获取更小的体积,在内容较大或重复性较多的情况下,ZIP压缩的效果明显,如果存储的内容是TestPOJO的数组,可能适合使用ZIP压缩。
  但ZIP压缩并不一定会减少体积,在小于30个字节的情况下,也许还会增加体积。在重复性内容较少的情况下,无法获得明显提升。并且存在CPU开销。
  在经过以上优化之后,ZIP压缩不再是必选项,需要根据实际数据做测试才能分辨到ZIP的压缩效果。
  最终落地
  上面的几个改进步骤体现了优化的思路,但是反序列化的过程会导致类型的丢失,处理起来比较繁琐,所以我们还需要考虑反序列化的问题。
  在缓存对象被预定义的情况下,我们完全可以手动处理每个字段,所以在实战中,推荐使用手动序列化达到上述目的,实现精细化的控制,达到最好的压缩效果和最小的性能开销。
  可以参考以下msgpack的实现代码,以下为测试代码,请自行封装更好的Packer和UnPacker等工具:dependencygroupIdorg。msgpackgroupIdmsgpackcoreartifactIdversion0。9。3versiondependencypublicbyte〔〕toByteArray()throwsException{MessageBufferPackerpackerMessagePack。newDefaultBufferPacker();toByteArray(packer);packer。close();returnpacker。toByteArray();}publicvoidtoByteArray(MessageBufferPackerpacker)throwsException{if(testStatusnull){packer。packNil();}else{packer。packString(testStatus);}if(userPinnull){packer。packNil();}else{packer。packString(userPin);}if(investornull){packer。packNil();}else{packer。packString(investor);}if(testQueryTimenull){packer。packNil();}else{packer。packLong(testQueryTime。getTime());}if(createTimenull){packer。packNil();}else{packer。packLong(createTime。getTime());}if(bizInfonull){packer。packNil();}else{packer。packString(bizInfo);}if(otherTimenull){packer。packNil();}else{packer。packLong(otherTime。getTime());}if(userAmountnull){packer。packNil();}else{packer。packString(userAmount。toString());}if(userRatenull){packer。packNil();}else{packer。packString(userRate。toString());}if(applyAmountnull){packer。packNil();}else{packer。packString(applyAmount。toString());}if(typenull){packer。packNil();}else{packer。packString(type);}if(checkTimenull){packer。packNil();}else{packer。packString(checkTime);}if(preTestStatusnull){packer。packNil();}else{packer。packString(preTestStatus);}}publicvoidfromByteArray(byte〔〕byteArray)throwsException{MessageUnpackerunpackerMessagePack。newDefaultUnpacker(byteArray);fromByteArray(unpacker);unpacker。close();}publicvoidfromByteArray(MessageUnpackerunpacker)throwsException{if(!unpacker。tryUnpackNil()){this。setTestStatus(unpacker。unpackString());}if(!unpacker。tryUnpackNil()){this。setUserPin(unpacker。unpackString());}if(!unpacker。tryUnpackNil()){this。setInvestor(unpacker。unpackString());}if(!unpacker。tryUnpackNil()){this。setTestQueryTime(newDate(unpacker。unpackLong()));}if(!unpacker。tryUnpackNil()){this。setCreateTime(newDate(unpacker。unpackLong()));}if(!unpacker。tryUnpackNil()){this。setBizInfo(unpacker。unpackString());}if(!unpacker。tryUnpackNil()){this。setOtherTime(newDate(unpacker。unpackLong()));}if(!unpacker。tryUnpackNil()){this。setUserAmount(newBigDecimal(unpacker。unpackString()));}if(!unpacker。tryUnpackNil()){this。setUserRate(newBigDecimal(unpacker。unpackString()));}if(!unpacker。tryUnpackNil()){this。setApplyAmount(newBigDecimal(unpacker。unpackString()));}if(!unpacker。tryUnpackNil()){this。setType(unpacker。unpackString());}if(!unpacker。tryUnpackNil()){this。setCheckTime(unpacker。unpackString());}if(!unpacker。tryUnpackNil()){this。setPreTestStatus(unpacker。unpackString());}}场景延伸
  假设,我们为2亿用户存储数据,每个用户包含40个字段,字段key的长度是6个字节,字段是分别管理的。
  正常情况下,我们会想到hash结构,而hash结构存储了key的信息,会占用额外资源,字段key属于不必要数据,按照上述思路,可以使用list替代hash结构。
  通过Redis官方工具测试,使用list结构需要144G的空间,而使用hash结构需要245G的空间(当50以上的属性为空时,需要进行测试,是否仍然适用)
  在以上案例中,我们采取了几个非常简单的措施,仅仅有几行简单的代码,可降低空间70以上,在数据量较大以及性能要求较高的场景中,是非常值得推荐的。:
  使用数组替代对象(如果大量字段为空,需配合序列化工具对null进行压缩)
  使用更好的序列化工具
  使用更小的数据类型
  考虑使用ZIP压缩
  使用list替代hash结构(如果大量字段为空,需要进行测试对比)

小米平板5防窥钢化保护膜开售双侧30176防窥,售价99元IT之家2月16日消息,小米平板5官方防窥钢化保护膜今日全渠道开售,售价99元。京东小米平板防窥钢化保护膜99元直达链接据介绍,该保护膜支持双侧30防窥,采用百叶窗……小米12Pro即将全球发布骁龙8双尺寸旗舰,已出现在印度尼西IT之家1月13日消息,自小米12Pro系列推出以来已经过去了两周,但仍然没有关于其全球发布的消息。近日,印度尼西亚电信认证网站上的新列表显示,小米12(2201123G……京东4。27潮玩数码品类日爆款手机配件五折起京东潮玩数码超级品类日现已开启,全场好价:点此前往主会场。本次大促除了有手机配件,还可领1299499神券,更有大牌厂商至高立减500元,还有半价商品可以抢购。投影……曝一加Ace新机本月发布搭载天玑8100与LCD高刷屏,未来感谢IT之家网友蓝海岸Nibiru、迷一样的菠萝、幻雪之影的线索投递!IT之家5月8日消息,一加近日入网了一款型号为PGZ110的新机,搭载天玑8100,采用6。59英寸……中国花滑创造历史,金博洋开导朱易接纳失败享受比赛褪去电光石火的硝烟,奏响冰上芭蕾的乐曲,从短道速滑切换到花样滑冰,首都体育馆的冰面再次见证中国军团创造历史。尽管小将朱易没能发挥出最佳水准,在女子单人滑短节目比拼中排名末……支持率98看捷克如何ampampquot吞并ampampqu一场真正的互联网风暴已经在捷克共和国肆虐了一个星期。这是由一个关于加里宁格勒地区加入捷克共和国的备忘录引起的,在捷克加里宁格勒又被称为克拉罗韦茨。这一切开始于……同方公布新款超翔国产PC搭载青松主板腾锐D20008核处理器IT之家5月6日消息,据同方官方消息,新款同方超翔TK630v0501台式计算机现已发布,基于青松主板打造,配备飞腾腾锐D20008核处理器。同方表示,这款PC产品经专业……不止K50电竞版,消息称小米Redmi一大波新机正在路上搭载IT之家1月22日消息,据数码博主数码闲聊站爆料,一大波新机正在路上。除了已经定档2月中下旬的RedmiK50电竞版,正在打磨中的包括RedmiK50系列的骁龙870、天玑80……SA海思半导体受到制裁打击,智能手机AP芯片出货量Q3下降9IT之家12月24日消息,今日上午,StrategyAnalytics发布报告称,2021年Q3,全球智能手机应用处理器(AP)市场收益增长17,达到83亿美元。IT之家……王楚钦将会成为下一个张继科,那樊振东也会成为下一个林高远吗?前一段国乒举行了教练竞聘,李隼被聘为国乒总教头,王皓马琳升任为男女乒主教练,随后各个队员也找到了自己心仪的教练,其中有两人的教练引起了球迷的关注,小将王楚钦投到了神奇教练肖战的……上市首日股价大涨70,但星空华文还没找到下一个中国好声音12月29日,《中国好声音》《这!就是街舞》IP运营商星空华文控股有限公司(下称星空华文)正式挂牌港交所,股票代码6698,截至29日收盘,股价为45。2港元,较发行价26。5……小米12Pro手机3699元起,雷军谈双尺寸双旗舰如何选择IT之家12月30日消息,在12月28日召开的新品发布会上,小米正式发布了小米12、小米12Pro和小米12X三款手机。其中,小米12售价3699元起,小米12Pro售价469……
台媒高通将发动价格战,5G芯片跌破20美元据台湾《经济日报》报道,业界传出消息,高通公司为了降低华为禁令干扰,扩大市场占有率,将发动价格战,中低端芯片降幅高达30甚至腰斩,低端版本跌破20美元。高通公司不予回应。……阿里巴巴发布物流机器人小蛮驴4度电能跑100多公里,每天最多IT之家9月17日消息在9月17日云栖大会上,阿里巴巴发布第一款机器人小蛮驴,同时发布机器人平台,正式进军机器人赛道。根据阿里云总裁张建锋介绍,小蛮驴机器人集成了达摩院最……29999元,64核发烧级AMD锐龙ThreadripperIT之家2月7日消息在1月7日的AMDCES发布会上,苏姿丰隆重推出了线程撕裂者3990X处理器。今天2月7日,AMD锐龙Threadripper3990X处理器正式上市……112终结比赛!陈梦拒绝爆冷赢球,东京奥运曾连扳四局逆转对方经历了世乒赛和WTT世界杯赛表现不佳的历程后,休整了一段时间的陈梦,在WTT澳门赛再次扬帆起航。对陈梦而言,WTT澳门赛并不是陈梦的福地,上一届的赛事,陈梦曾在3:0大比……惠普推出ENVY创作者台式机可选i7RTX2060SuperIT之家3月1日消息根据日本媒体PCWatch的报道,日本惠普株式会社推出了面向创作者的台式电脑ENVYDesktopTE01,造型紧凑,最高可选i79700,显卡可选RTX2……惠普公布17英寸大屏轻薄本ENVY17,搭载i71065G7感谢IT之家网友顽果度的线索投递!IT之家2月25日消息IT之家在惠普荷兰官方了解到,惠普已经公布了其17英寸大屏轻薄本ENVY17的配置信息。据介绍,这款笔记本搭……北京冬残奥会参与者感受坚持与信心,一起向未来可期多年以后,郭雨洁也许会常常想起北京2022年冬残奥会的那些闪闪发光的瞬间。3月11日,中国选手郭雨洁在北京2022年冬残奥会残奥冬季两项女子长距离(站姿)比赛中。她最终获……惠普新款暗影精灵笔记本曝光搭载i510300GTX1650TIT之家2月18日消息IT之家曾报道,今年新款的游戏本有望在3月底发布,目前尚不确定是否会因为疫情而推迟。现在,根据爆料者rogame的消息,新款惠普暗影精灵的数据已经流出了。……未来漫评春节的团圆里是浓浓的家国情怀回家过年是中国人亘古不变的主题,它被赋予了太多的情感,不仅承载着人们团圆的喜悦,更寄托着游子对于家乡的守望。作为疫情进入新阶段的第一个春节,今年,人们回家团圆的愿望更加迫切。……VAIO国内推出SX12笔记本899克重,配6核i7IT之家2月18日消息根据VAIO官方消息,2020年2月18日,VAIO在中国大陆地区推出2020年款SX12、SX14两款笔记本新机型,分别搭载12。5英寸和14英寸屏幕,……华硕G15轻薄游戏本价格曝光R74800HSGTX1660T感谢IT之家网友顽果度的线索投递!IT之家2月18日消息IT之家CES曾报道,AMD在发布会上宣布华硕ROGG系列笔记本将会首发锐龙4000H系列处理器。华硕ROGG系列……微星Prestige14粉白配色上架i7GTX1650,99IT之家2月17日消息IT之家2月7日报道,微星在国内推出了全新的粉色和白色款的Prestige14笔记本,搭载i7GTX1650MaxQ,首发价都是9999元,现已在京东开启……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网