【原创】完美的缓存层设计方案
一、数据型缓存:
1、概念
为什么会被称之为数据型缓存,因为这类缓存是根据数据的变化而变化,即时更新,一旦缓存逻辑创建完毕,无需人工维护,完全自动化实现更新。
2、缓存类型:
1)主键型数据缓存【Memcache】:依据主键ID创建的数据缓存【以主键ID为缓存key】,如果主键ID所对应的数据发生变化,缓存就会发生对应的更新【删除并重建】,缓存key示例:data_play_id【数据标识+Model类型+主键ID】,主键型数据缓存比较好理解。
2)关系型数据缓存【Memcache】:依据关系ID创建的关系型缓存
(1)示例:例如唯一索引 i_cus_course(用户+课程),则缓存key可以设置为data_play_customerId_courseId【数据标识+Model类型+关系型ID(用户ID+课程ID)】,当然,一个缓存key对应的不仅仅是一条数据即一对一,还有可能是一对多的关系,例如,课程1有哪些人播放,则以课程ID为缓存key,创建对应缓存,缓存key示例:data_play_list_courseId【数据标识+Model类型+列表标识+关系型ID】,类似业务有这个作品有哪些人点赞,这个人有哪些人关注,有哪些人收藏等等【只需要缓存对应的用户ID就行了】。
3)总数型数据缓存【Memcache】:主要解决千万、亿级数据的总数据条数统计的需求
(1)示例:比如需要显示总计有多少个用户,多少条记录等等,在查询的时候特别耗时的需求,在初始化创建的时候,会非常耗时,比较慢,但是创建了数据缓存之后,每次数据条数有增加或者删除,就会在总数上面进行对应的操作,就不会那么耗时了。
(2)实现原理:将初始化查询放到Redis队列里,进行一步操作,如果查询超时或者失败,继续查询创建,也就是说这个缓存key一定会被创建,之后的增加或者减少,则放在底层进行操作,对外调用的方法正常使用即可,使用者无感知。
4)是否型数据缓存【Redis,哈希】:主要用于是否型的需求【解决空Key方面的问题,极大解决了缓存暂用的问题】。
(1)什么叫空key:例如这个人是否是黑名单用户,100个用户,你可能会创建100个缓存key,存储value值为1或者0等,或者说缓存存不存在,就代表这个人是否是黑名单,因为value值特别小,或者不存在,我们就称这类缓存key为空key。
(2)缓存计算:因为缓存key和value同样都会占用缓存空间,简单分析一下,这种类型的缓存,key假如暂用10个位置(因为缓存key里面会带有不同的服务,不同的Model标识,所以,长度会比较长,预估10个位置),value暂用1个位置,之前100个空key,会占用10*100+100 = 1100个位置,如果将100个空key设置成一个缓存key,即100个数值全部存到一个key里面,10+(3+1)*100 = 410个位置(3代表唯一标识,预估占用3个位置),这个时候我们就可以看到,使用了是否型数据缓存策略之后,至少可以节省一半的缓存空间。
3、设置要求:
1)前置条件:CacheModel,需要封装,具有删除缓存【rmMulti】、添加数据到缓存中【addMulti】、查询缓存【getMulti】等基本功能;
2)继承:需要用到的数据缓存的数据表(例如PlayModel),对应Model继承CacheModel即可,这样可自动集成主键型数据缓存,如果不继承,则代表无需集成数据缓存,
3)扩展:如果需要用到关系型和是否型数据缓存的话,则需要继承CacheModel的同时,还需要根据条件对数据进行查询【getRealDataByIdKeys】、组装【changeToCacheData】,由CacheModel将组装好的缓存数据依照固定规则写入到缓存中,查询数据的时候再依照固定的规则从缓存中读取【getInfoByIdKey,getinfoByIdKeys】。
二、列表型缓存:有序集合
1、存储位置:Redis
2、应用场景:非即时性更新,主要用于数据分页使用,例如,首页推荐,向下无限极分页,每页展示20条数据等。
3、分页形式:
1)依据ID进行分页:依据主键ID进行分页,可以杜绝数据重复情况的发生,就像首页推荐,可采用这种形式。分页原理,查询第一页数据的时候,可一次性查询100条数据添加到数据缓存当中,后面查询到第4页的时候,如果第5页数据不够一页,或者刚够,则继续向下查询100条数据,并添加到缓存当中,之后其他人在访问这个首页的时候,已经加入到缓存当中的数据,则无需再从数据库中查询,直接从缓存中获取就行,如果缓存当中没有,则查询,并添加到数据缓存当中。
2)依据页码进行分页:可能会产生重复数据,对重复率要求严格的场景不适合使用此方法。
三、业务缓存:
1、概念:即不需要根据数据库数据的变化而变化,而是根据需求来变化的数据,这部分数据就是业务数据,业务数据所形成的缓存,就叫业务缓存。
2、示例:比如举办某个活动,需要对活动的相关数据创建缓存,示例:年底促销搞活动,需要根据这个用户不同的登陆次数奖励不同的奖品,活动结束之后只需要相对应的活动结果即可,那么,这个用户在活动期间的登录次数和所对应的登录时间这些就可以记录到业务缓存当中。
课外:Redis和Memcached整体对比
Redis的作者Salvatore Sanfilippo曾经对这两种基于内存的数据存储系统进行过比较,总体来看还是比较客观的,现总结如下:
1)性能对比:由于Redis只使用单核,而Memcached可以使用多核,所以平均每一个核上Redis在存储小数据时比Memcached性能更高。而在100k以上的数据中,Memcached性能要高于Redis,虽然Redis最近也在存储大数据的性能上进行优化,但是比起 Memcached,还是稍有逊色。
2)内存使用效率对比:使用简单的key-value存储的话,Memcached的内存利用率更高,而如果Redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于Memcached。
3)Redis支持服务器端的数据操作:Redis相比Memcached来说,拥有更多的数据结构和并支持更丰富的数据操作,通常在Memcached 里,你需要将数据拿到客户端来进行类似的修改再set回去。这大大增加了网络IO的次数和数据体积。在Redis中,这些复杂的操作通常和一般的 GET/SET一样高效。所以,如果需要缓存能够支持更复杂的结构和操作,那么Redis会是不错的选择。
备注:主键型数据缓存、关系型数据缓存以及总数型数据缓存普遍都是简单的key-value结构,所以一般建议使用Memcache,是否型的数据缓存其存储结构更适合采用Redis的哈希,列表型缓存由于需要用到排序,所以,只能用Redis的有序集合,业务型缓存就随意了,但是一般Redis比较多点。
PS:基本上,一个创业型的公司,其项目缓存层只要一开始集成了上述的各种缓存形式,在整个服务器和数据库成本不变的情况下,提升项目抗压能力上百倍还是很easy的!