wqbala 2020-02-20
最近做的某个feature需要在很短的时间内上千万次请求其他部门的web服务,为了减少请求次数和提升系统响应速度决定采用cache来缓存数据。
说到cache最出名的就是memcached和redis了,因为目前公司内用redis的项目用的更多,有专门的集群和运维工程师,就果断选了redis。
一言以蔽之,Redis就是在内存中存储key-value结构。key一般就是string, value又分成好几种数据类型:string, list,hashmap,set和sortset,bitmap等。
我们需求比较简单并不需要利用value数据类型的特性进行排序或者部分查询之类的操作,只是需要简单的存取,所以直接用的spring-data-redis提供的RedisTemplate,key value都序列化成了byte数组更省时省空间。
作为初阶用户,重点说一下redis的几种模式和一些限制。
1. Master-Slave模式。master写,salve复制,可实现读写分离。支持一master对应多个slave。当一个新的slave找到master时,master会把自己的全量数据以文件的形式copy给slave,然后增量数据以命令的形式发给slave。slave自己也可以向另一个slave同步数据,这个就跟传统的master-slave架构的路子不一样了,比如ES是从primary shard发数据给所有的replice shard,Kafka也是从主partition发给所有副本partiton。我理解redis能这么做的原因与它底层采用的是gossip协议有关,gossip协议是无中心化的,每个节点都保持所有的元信息或者说都有相同的地位,无中心也就每个都是中心可以分散压力,缺点就是完成所有的更新会比较拖沓,延时较大。
2.哨兵模式。主从模式的基础上引入哨兵,提升可用性。哨兵就是监控master是否挂了然后自动选择一个slave提升为master,也可以配多个哨兵,共同做failover同时哨兵之间进行监控。感觉哨兵跟mongoDB的arbiter比较相似。
3. cluster模式。我们没有用,因为我们数量不大单机内存就能搞定。cluster模式主要是为大数据量场景用的,可以横向扩展多个master,每个master存一部分数据,跟其他分布式存储系统的策略一样,也是通过hash(key)算法决定数据存在哪个master,master上的数据再复制到slave,整个数据存储模型跟ES, Kafka,MongoDB都差不多。
redis缓存数据过期策略:
redis对过期数据的删除比较务实,没有采用比较重的定期全局scan所有数据删除过期数据,也没有给每个数据定一个过期自动触发的trigger。
当Client要获取redis的某个key的时候会先进行过期判定,如果改key已经过期先删除。如果client永远都不访问那个key呢,会每隔一段时间随机抽取一批进行过期检测和删除过期数据,如果抽取的这批数据里过期数据占比超过了threshold,立即进行下一批次的抽取和删除工作。算是一种比较柔和的删除方式,当然总有一些漏网之鱼删不掉,这就会造成内存不够用,从而会引入一定的内存回收策略进行兜底: