专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

重新认识下JVM级别的本地缓存框架GuavaCache优秀从

  大家好,又见面了。
  本文是笔者作为掘金技术社区签约作者的身份输出的缓存专栏系列内容,将会通过系列专题,讲清楚缓存的方方面面。如果感兴趣,欢迎关注以获取后续更新。
  不知不觉,这已经是《深入理解缓存原理与实战设计》系列专栏的第6篇文章了。经过前面5篇文章的铺垫,我们系统且全面地介绍了缓存相关的概念与典型问题,也手动实操了如何构建一个本地最简版本的通用缓存框架,还对JAVA主流的本地缓存规范进行了解读。
  秉持着不重复造轮子的理念,本篇文章中,我们就来一起深入剖析JAVA本地缓存的优秀轮子来自Google家族的GuavaCache。聊一聊其实现机制、看一看如何使用。
  GuavaCache初识
  Guava是Google提供的一套JAVA的工具包,而GuavaCache则是该工具包中提供的一套完善的JVM级别的高并发缓存框架。其实现机制类似ConcurrentHashMap,但是进行了众多的封装与能力扩展。作为JVM级别的本地缓存框架,GuavaCache具备缓存框架该有的众多基础特性。当然,GuavaCache能从众多本地缓存类产品中脱颖而出,除了具备上述基础缓存特性外,还有众多贴心的能力增强,绝对算得上是工具包届的超级暖男!为什么这么说呢?我们一起看下GuavaCache的能力介绍,应该可以有所体会。
  支持缓存记录的过期设定
  作为一个合格的缓存容器,支持缓存记录过期是一个基础能力。GuavaCache不但支持设定过期时间,还支持选择是根据插入时间进行过期处理(创建过期)、或者是根据最后访问时间进行过期处理(访问过期)。
  过期策略
  具体说明
  创建过期
  基于缓存记录的插入时间判断。比如设定10分钟过期,则记录加入缓存之后,不管有没有访问,10分钟时间到则
  访问过期
  基于最后一次的访问时间来判断是否过期。比如设定10分钟过期,如果缓存记录被访问到,则以最后一次访问时间重新计时;只有连续10分钟没有被访问的时候才会过期,否则将一直存在缓存中不会被过期。
  实际使用的时候,可以在创建缓存容器的时候指定过期策略即可:基于创建时间过期publicCacheString,UsercreateUserCache(){returnCacheBuilder。newBuilder()。expireAfterWrite(30L,TimeUnit。MINUTES)。build();}基于访问时间过期publicCacheString,UsercreateUserCache(){returnCacheBuilder。newBuilder()。expireAfterAccess(30L,TimeUnit。MINUTES)。build();}
  是不是很方便?
  支持缓存容量限制与不同淘汰策略
  作为内存型缓存,必须要防止出现内存溢出的风险。GuavaCache支持设定缓存容器的最大存储上限,并支持根据缓存记录条数或者基于每条缓存记录的权重(后面会具体介绍)进行判断是否达到容量阈值。
  当容量触达阈值后,支持根据FIFOLRU策略实施具体淘汰处理以腾出位置给新的记录使用。
  淘汰策略
  具体说明
  FIFO
  根据缓存记录写入的顺序,先写入的先淘汰
  LRU
  根据访问顺序,淘汰最久没有访问的记录
  实际使用的时候,同样是在创建缓存容器的时候指定容量上限与淘汰策略,这样就可以放心大胆地使用而不用担心内存溢出问题咯。限制缓存记录条数publicCacheString,UsercreateUserCache(){returnCacheBuilder。newBuilder()。maximumSize(10000L)。build();}限制缓存记录权重publicCacheString,UsercreateUserCache(){returnCacheBuilder。newBuilder()。maximumWeight(10000L)。weigher((key,value)(int)Math。ceil(instrumentation。getObjectSize(value)1024L))。build();}
  这里需要注意:按照权重进行限制缓存容量的时候必须要指定weighter属性才可以生效。上面代码中我们通过计算value对象的字节数(byte)来计算其权重信息,每1kb的字节数作为1个权重,整个缓存容器的总权重限制为1w,这样就可以实现将缓存内存占用控制在100001k10M左右。
  有没有很省心?
  支持集成数据源能力
  在前面文章中,我们有介绍过缓存的三种模型,分别是旁路型、穿透型、异步型。GuavaCache作为一个封装好的缓存框架,是一个典型的穿透型缓存。正常业务使用缓存时通常会使用旁路型缓存,即先去缓存中尝试查询获取数据,如果获取不到则会从数据库中进行查询并加入到缓存中;而为了简化业务端使用复杂度,GuavaCache支持集成数据源,业务层面调用接口查询缓存数据的时候,如果缓存数据不存在,则会自动去数据源中进行数据获取并加入缓存中。publicUserfindUser(CacheString,Usercache,StringuserId){try{returncache。get(userId,(){System。out。println(userId用户缓存不存在,尝试回源查找并回填。。。);returnuserDao。getUser(userId);});}catch(ExecutionExceptione){e。printStackTrace();}returnnull;}
  实际使用的时候如果查询的用户不存在,则会自动去回源查找并写入缓存里,再次获取的时候便可以从缓存直接获取:
  上面的方法里,是通过在get方法里传入Callable实现的方式指定回源获取数据的方式,来实现缓存不存在情况的自动数据拉取与回填到缓存中的。实际使用的时候,除了Callable方式,还有一种CacheLoader的模式,也可以实现这一效果。
  需要我们在创建缓存容器的时候声明容器为LoadingCache类型(下面的章节中有介绍),并且指定CacheLoader处理逻辑:publicLoadingCacheString,UsercreateUserCache(){returnCacheBuilder。newBuilder()。build(newCacheLoaderString,User(){OverridepublicUserload(Stringkey)throwsException{System。out。println(key用户缓存不存在,尝试CacheLoader回源查找并回填。。。);returnuserDao。getUser(key);}});}
  这样,获取不到数据的时候,也会自动回源查询并填充。比如我们执行如下调用逻辑:publicstaticvoidmain(String〔〕args){CacheServicecacheServicenewCacheService();LoadingCacheString,UsercachecacheService。createUserCache();try{System。out。println(cache。get(123));System。out。println(cache。get(124));System。out。println(cache。get(123));}catch(Exceptione){e。printStackTrace();}}
  执行结果如下:123用户缓存不存在,尝试CacheLoader回源查找并回填。。。User(userId123,userName铁柱,department研发部)124用户缓存不存在,尝试CacheLoader回源查找并回填。。。User(userId124,userName翠花,department测试部)User(userId123,userName铁柱,department研发部)
  两种方式都可以实现这一效果,实际可以根据需要与场景选择合适的方式。
  当然,有些时候,可能也会涉及到CacheLoader与Callable两种方式结合使用的场景,这种情况下优先会执行Callable提供的逻辑,Callable缺失的场景会使用CacheLoader提供的逻辑。publicstaticvoidmain(String〔〕args){CacheServicecacheServicenewCacheService();LoadingCacheString,UsercachecacheService。createUserCache();try{System。out。println(cache。get(123,()newUser(xxx)));System。out。println(cache。get(124));System。out。println(cache。get(123));}catch(Exceptione){e。printStackTrace();}}
  执行后,可以看出Callable逻辑被优先执行,而CacheLoader作为兜底策略存在:User(userIdxxx,userNamenull,departmentnull)124用户缓存不存在,尝试CacheLoader回源查找并回填。。。User(userId124,userName翠花,department测试部)User(userIdxxx,userNamenull,departmentnull)
  支持更新锁定能力
  这个是与上面数据源集成一起的辅助增强能力。在高并发场景下,如果某个key值没有命中缓存,大量的请求同步打到下游模块处理的时候,很容易造成缓存击穿问题。
  为了防止缓存击穿问题,可以通过加锁的方式来规避。当缓存不可用时,仅持锁的线程负责从数据库中查询数据并写入缓存中,其余请求重试时先尝试从缓存中获取数据,避免所有的并发请求全部同时打到数据库上。
  作为穿透型缓存的保护策略之一,GuavaCache自带了并发锁定机制,同一时刻仅允许一个请求去回源获取数据并回填到缓存中,而其余请求则阻塞等待,不会造成数据源的压力过大。
  有没有被暖心到?
  提供了缓存相关的一些监控统计
  引入缓存的一个初衷是希望缓存能够提升系统的处理性能,而有限缓存容量中仅存储部分数据的时候,我们会希望存储的有限数据可以尽可能的覆盖并抗住大部分的请求流量,所以对缓存的命中率会非常关注。
  GuavaCache深知这一点,所以提供了stat统计日志,支持查看缓存数据的加载或者命中情况统计。我们可以基于命中情况,不断地去优化代码中缓存的数据策略,以发挥出缓存的最大价值。
  GuavaCache的统计信息封装为CacheStats对象进行承载,主要包含一下几个关键指标项:
  指标
  含义说明
  hitCount
  命中缓存次数
  missCount
  没有命中缓存次数(查询的时候内存中没有)
  loadSuccessCount
  回源加载的时候加载成功次数
  loadExceptionCount
  回源加载但是加载失败的次数
  totalLoadTime
  回源加载操作总耗时
  evictionCount
  删除记录的次数
  缓存容器创建的时候,可以通过recordStats()开启缓存行为的统计记录:publicstaticvoidmain(String〔〕args){LoadingCacheString,UsercacheCacheBuilder。newBuilder()。recordStats()。build(newCacheLoaderString,User(){OverridepublicUserload(Stringkey)throwsException{System。out。println(key用户缓存不存在,尝试CacheLoader回源查找并回填。。。);UseruseruserDao。getUser(key);if(usernull){System。out。println(key用户不存在);}returnuser;}});try{System。out。println(cache。get(123);System。out。println(cache。get(124));System。out。println(cache。get(123));System。out。println(cache。get(126));}catch(Exceptione){}finally{CacheStatsstatscache。stats();System。out。println(stats);}}
  上述代码执行之后结果输出如下:123用户缓存不存在,尝试CacheLoader回源查找并回填。。。User(userId123,userName铁柱,department研发部)124用户缓存不存在,尝试CacheLoader回源查找并回填。。。User(userId124,userName翠花,department测试部)User(userId123,userName铁柱,department研发部)126用户缓存不存在,尝试CacheLoader回源查找并回填。。。126用户不存在CacheStats{hitCount1,missCount3,loadSuccessCount2,loadExceptionCount1,totalLoadTime1972799,evictionCount0}
  可以看出,一共执行了4次请求,其中1次命中,3次回源处理,2次回源加载成功,1次回源没找到数据,与打印出来的CacheStats统计结果完全吻合。
  有着上述能力的加持,前面将GuavaCache称作暖男不过分吧?
  GuavaCache适用场景
  在本系列专栏的第一篇文章《聊一聊作为高并发系统基石之一的缓存,会用很简单,用好才是技术活》中,我们在缓存的一步步演进介绍中提过本地缓存与集中式缓存的区别,也聊了各自的优缺点。
  作为一款纯粹的本地缓存框架,GuavaCache具备本地缓存该有的优势,也无可避免的存在着本地缓存的弊端。
  维度
  简要概述
  优势
  基于空间换时间的策略,利用内存的高速处理效率,提升机器的处理性能,减少大量对外的IO请求交互,比如读取DB、请求外部网络、读取本地磁盘数据等等操作。
  弊端
  整体容量受限,可能对本机内存造成压力。此外,对于分布式多节点集群部署的场景,缓存更新场景会出现缓存漂移问题,导致各个节点之间的缓存数据不一致。
  鉴于上述优劣综合判断,可以大致圈定GuavaCache的实际适用场合:数据读多写少且对一致性要求不高的场景
  这类场景中,会将数据缓存到本地内存中,采用定时触发(或者事件推送)的策略重新加载到内存中。这样业务处理逻辑直接从内存读取需要的数据,修改系统配置项之后,需要等待一定的时间后方可生效。
  很多的配置中心采用的都是这个缓存策略。统一配置中心中管理配置数据,然后各个业务节点会从统一配置中心拉取配置并存储在自己本地的内存中然后使用本地内存中的数据。这样可以有效规避配置中心的单点故障问题,降低了配置中心的请求压力,也提升了业务节点自身的业务处理性能(减少了与配置中心之间的网络交互请求)。对性能要求极其严苛的场景
  对于分布式系统而言,集中式缓存是一个常规场景中很好的选项。但是对于一些超大并发量且读性能要求严苛的系统而言,一个请求流程中需要频繁的去与Redis交互,其网络开销也是不可忍受的。所以可以采用将数据本机内存缓存的方式,分散redis的压力,降低对外请求交互的次数,提升接口响应速度。简单的本地数据缓存,作为HashMapConcurrentHashMap的替代品
  这种场景也很常见,我们在项目中经常会遇到一些数据的需要临时缓存一下,为了方便很多时候直接使用的HashMap或者ConcurrentHashMap来实现。而GuavaCache聚焦缓存场景做了很多额外的功能增强(比如数据过期能力支持、容量上限约束等),可以完美替换掉HashMapConcurrentHashMap,更适合缓存场景使用。
  GuavaCache使用引入依赖
  使用GuavaCache,首先需要引入对应的依赖包。对于Maven项目,可以在pom。xml中添加对应的依赖声明即可:dependencygroupIdcom。google。guavagroupIdguavaartifactIdversion31。1jreversiondependency
  这样,就完成了依赖引入。
  容器创建CacheBuilder
  具体使用前首先面临的就是如何创建GuavaCache实例。可以借助CacheBuilder以一种优雅的方式来构建出合乎我们诉求的Cache实例。
  对CacheBuilder中常见的属性方法,归纳说明如下:
  方法
  含义说明
  newBuilder
  构造出一个Builder实例类
  initialCapacity
  待创建的缓存容器的初始容量大小(记录条数)
  maximumSize
  指定此缓存容器的最大容量(最大缓存记录条数)
  maximumWeight
  指定此缓存容器的最大容量(最大比重值),需结合weighter方可体现出效果
  expireAfterWrite
  设定过期策略,按照数据写入时间进行计算
  expireAfterAccess
  设定过期策略,按照数据最后访问时间来计算
  weighter
  入参为一个函数式接口,用于指定每条存入的缓存数据的权重占比情况。这个需要与maximumWeight结合使用
  refreshAfterWrite
  缓存写入到缓存之后
  concurrencyLevel
  用于控制缓存的并发处理能力,同时支持多少个线程并发写入操作
  recordStats
  设定开启此容器的数据加载与缓存命中情况统计
  基于CacheBuilder及其提供的各种方法,我们可以轻松的进行缓存容器的构建、并指定容器的各种约束条件。
  比如下面这样:publicLoadingCacheString,UsercreateUserCache(){returnCacheBuilder。newBuilder()。initialCapacity(1000)初始容量。maximumSize(10000L)设定最大容量。expireAfterWrite(30L,TimeUnit。MINUTES)设定写入过期时间。concurrencyLevel(8)设置最大并发写操作线程数。refreshAfterWrite(1L,TimeUnit。MINUTES)设定自动刷新数据时间。recordStats()开启缓存执行情况统计。build(newCacheLoaderString,User(){OverridepublicUserload(Stringkey)throwsException{returnuserDao。getUser(key);}});}
  业务层使用
  GuavaCache容器对象创建完成后,可以基于其提供的对外接口完成相关缓存的具体操作。首先可以了解下Cache提供的对外操作接口:
  对关键接口的含义梳理归纳如下:
  接口名称
  具体说明
  get
  查询指定key对应的value值,如果缓存中没匹配,则基于给定的Callable逻辑去获取数据回填缓存中并返回
  getIfPresent
  如果缓存中存在指定的key值,则返回对应的value值,否则返回null(此方法不会触发自动回源与回填操作)
  getAllPresent
  针对传入的key列表,返回缓存中存在的对应value值列表(不会触发自动回源与回填操作)
  put
  往缓存中添加keyvalue键值对
  putAll
  批量往缓存中添加keyvalue键值对
  invalidate
  从缓存中删除指定的记录
  invalidateAll
  从缓存中批量删除指定记录,如果无参数,则清空所有缓存
  size
  获取缓存容器中的总记录数
  stats
  获取缓存容器当前的统计数据
  asMap
  将缓存中的数据转换为ConcurrentHashMap格式返回
  cleanUp
  清理所有的已过期的数据
  在项目中,可以基于上述接口,实现各种缓存操作功能。publicstaticvoidmain(String〔〕args){CacheServicecacheServicenewCacheService();LoadingCacheString,UsercachecacheService。createUserCache6();cache。put(122,newUser(122));cache。put(122,newUser(122));System。out。println(put操作后查询:cache。getIfPresent(122));cache。invalidate(122);System。out。println(invalidate操作后查询:cache。getIfPresent(122));System。out。println(cache。stats());}
  执行后,结果如下:put操作后查询:User(userId122,userNamenull,departmentnull)invalidate操作后查询:nullCacheStats{hitCount1,missCount1,loadSuccessCount0,loadExceptionCount0,totalLoadTime0,evictionCount0}
  当然,上述示例代码中这种使用方式有个明显的弊端就是业务层面对GuavaCache的私有API依赖过深,后续如果需要替换Cache组件的时候会比较痛苦,需要对业务调用的地方进行大改。所以真正项目里面,最好还是对其适当封装,以实现业务层面的解耦。如果你的项目是使用Spring框架,也可以基于SpringCache统一规范来集成并使用GuavaCache,降低对业务逻辑的侵入。
  小结回顾
  好啦,关于GuavaCache的功能与关键特性介绍,以及项目中具体的集成与使用方法,就介绍到这里了。总结一下,GuavaCache其实就是一个增强版的大号ConcurrentHashMap,在保证线程安全的情况下,增加了缓存必备的数据过期、容量限制、回源策略等能力,既保证了本身的精简,又使得整体能力足以满足大部分本地缓存场景的使用诉求。也正是由于这些原因,GuavaCache在JAVA领域广受好评,使用范围非常的广泛。
  下一篇文章中,我们将继续对GuavaCache展开讨论,跳出使用层面,剖析其内部核心实现逻辑。如果有兴趣,欢迎关注后续文章的更新。
  那么,关于本文中提及的内容,你是否有自己的一些想法与见解呢?欢迎评论区一起交流下,期待和各位小伙伴们一起切磋、共同成长。
  补充说明1:本文属于《深入理解缓存原理与实战设计》系列专栏的内容之一。该专栏围绕缓存这个宏大命题进行展开阐述,全方位、系统性地深度剖析各种缓存实现策略与原理、以及缓存的各种用法、各种问题应对策略,并一起探讨下缓存设计的哲学。
  如果有兴趣,也欢迎关注此专栏。
  补充说明2:关于本文中涉及的演示代码的完整示例,我已经整理并提交到github中,如果您有需要,可以自取:https:github。comveezeanJavaBasicSkills
  我是悟道,聊技术、又不仅仅聊技术
  如果觉得有用,请点赞关注让我感受到您的支持。也可以关注下我的公众号【架构悟道】,获取更及时的更新。
  期待与你一起探讨,一起成长为更好的自己。

段刘愚不要期待了,一再给机会,但把握不住机会,郭田雨还有救?对梅州客家的比赛,一些球员的表现有目共睹,不是简单的不给机会,是这些球员表现不好的理由,一次机会把握不住正常,连续的机会把握不住,就是能力的问题。是的,说的就是段刘愚,他就是不行。国庆假期露营受青睐营地生意红火配套活动丰富假期最后一天,约上亲朋好友,带上帐篷烧烤炉架等装备,去户外公园或者海边露营度假,再拍上几张美照发朋友圈,这样的休闲度假方式受到不少市民的青睐。营地生意红火配套活动丰富在位于环岛路的韩国瑜重返高雄站台助阵点燃选情?陈其迈柯志恩差距再度缩小来源台海网台海网10月9日讯综合台媒报道,国民党高雄市长参选人柯志恩7日推出政见,提出减负担顾就业助新创,要帮助青年就业,翻转低薪。对手高雄市长陈其迈表示,高雄青年失业率在他上任前俞祁浩筑建国家冻梁海拔高追求更高原标题第三届科苑名匠俞祁浩视频加载中俞祁浩,中国科学院西北生态环境资源研究院研究员。致力于解决我国冻土区重大工程关键科技难题,系统研究了冻融灾害孕育和致灾机理,深化完善了冻土工程长退役开始摸底,军人如何选择需要认真考虑剑客北海三剑客文剑客北海四季轮回。又到了摸底的时候了。而每每这时,都是几家欢喜几家愁。越是临近摸底,很多人可能越是心里摸不着底。今天讲一个另类故事吧。因为,有利的,平时讲得都比较多民间美食的双子星座就像李白与杜甫并称李杜,并被认为是中国诗歌史上最令人景仰的双子星座一样,腊肉和香肠则是四川春节时民间美食的双子星座,是能够给大多数热爱生活的舌尖带来美好滋味的平凡而又历久弥新的好饮又是上药水老板维护消费者权益倪先生反映,10月5号,他的小舅子去理发,最后充了3000块钱办卡,他仔细一问,听到了一个大家很熟悉的词,上药水。视频加载中倪先生我说你姐本身里面就办了会员卡,平时理发二十多块钱就四川画家一幅肖像画了1年,模特忍不了跑了,后来画作卖了7015万2019年11月20日,在嘉德秋拍会上,一幅画作的出现,瞬间引得在场的人尖叫连连。这是一幅人物肖像画,画中,身着绿衣的女子略微低着头,脸上带着沉思的神情,她的发丝肌肉甚至皮肤瑕疵,华为Mate50E正式上架,性价比不高,但仍然限时限量头条创作挑战赛虽说华为Mate50系列已经开售一段时间,但多数现货都在第三方经销商或黄牛手中,实际销售到消费者手中的数量是有限的,因为需要加价下单,所以人们对于华为Mate50系列对话民间牛散系列丨罗石军投资的核心是要建立大局观点蓝字关注,不迷路民间牛散是市场上颇为神秘的一群人,缺乏专业投研团队的他们是如何凭一己之力穿越牛熊保持投资业绩长期优秀的?相信是投资者非常感兴趣的话题。为此,证券时报时报会客厅特推二十大代表风采丨陈望慧大家一起致富是我的心愿今天的二十大代表风采,带您认识四川小金县冒水村党支部书记陈望慧。这些天,小金县冒水村的旅游体验综合体正在加紧建设,这里将成为当地玫瑰加工和旅游业结合的新载体。四川小金县达维镇冒水村
好人难做吗?世界很精彩,社会很复杂,人心很难测,好人很难做吗?人心复杂,社会现在日益的下滑,道德品质已经没有了底线。做人的标准已经失去了衡量。假货遍地,毒食品非常多,网络上拍着胸脯发誓,却说的伏宇璐把天方夜谭变成了现实一名普通的维修工成功突破进口磨齿机卡脖子技术,这是天方夜谭吗?NO!中车戚墅堰所齿轮传动事业部维修工伏宇璐给出了答案。一个寻常的工作日,齿轮传动事业部生产车间一台高精尖进口磨齿机突脑子出现这三个词,必须及时打住,别让焦虑抓住你焦虑有个特点,就是当你发现它的时候就晚了。不知不觉被焦虑折腾很久了,想跳出来特别难,脑子根本不听你的。有三个敏感词,心烦的时候这些词从脑子里,一冒出来就及时打住。就像刹车,防止你跌外媒看中国经济众多外企眼中不可替代的大市场百胜中国最新财报中暗藏惊喜今年第三季度,这家国际餐饮巨头发现,它的餐厅利润率为近年来最高水平。渣打银行用非常好来形容其近期的中国业务表现,并认为这主要归功于中国坚定的对外开放。近日吸烟时间长的人身上开始出现这几种迹象别忽略吸烟与很多疾病之间的关系都很密切,而最为密切的就是肺癌了,在现有的肺癌患者中,吸烟人群占据了很大一部份,值得关注的是长时间吸烟,不仅使肺癌的患病风险增加了,口腔癌喉癌食道癌以及生殖韶华几许觅佳音,浮沉几梦半流年一曲弦乐传山谷,半梦忧怜惹人醉。几分思绪扰心境,一生过往了红尘。人生几何诉尽世事沧桑,话别离,心悠扬,世事荒凉催人老。01谢逊时光不老,岁月沉香罗素说所谓幸福的生活,必然是指安静的健走队的人和事(402)十四行诗第一部分(1)我们祈盼生命从绝色中繁生,这样美之蔷薇就永不会消失,但既然物过盛而衰皆有时令,就该为年轻的后代留下记忆可你却要娶自己的灿灿明眸,凭自身的燃烧维持你的光焰,对自枯萎的荷,为谁守在冷冷的水中?头条创作挑战赛难得在连续阴雨后有了个晴天,去离家最近的荷花池转转吧,那是从不辜负我的地方。可是,可是啊,真没想到,一场大降温,让池塘里的荷,全部失了颜色,连一点点青绿,都没有剩下。鞋履色彩趋势Get2023年度洋红色,在鞋履行业起飞01PANTONE2023年度代表色VivaMagenta洋红12月2号,全球权威色彩研究机构PANTONE(潘通)公布了2023年度代表色PANTONE181750VivaMag3种酒适量喝有益健康,但是这5种人最好滴酒不沾谈谈饮酒的益和害饮酒有益也有害。那么到底酒对人体有益还是有害,这就要看你饮什么酒和怎么饮法了。酒中含有酒精,适量饮用后可以扩张血管,促进血液循环。有人认为,酒少饮则活血行气,壮神御赵丽颖的风吹半夏火了!90年代新贵们的穿搭风格,太惊艳了赵丽颖的风吹半夏大家看了吗!区花最近一直在追,好看死了!之前赵丽颖在红毯上被嘲又胖脸又垮,实际上都是因为她在为这部剧增肥。这部剧讲的是女主许半夏白手起家,在钢铁行业披荆斩棘的故事。
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网