您的位置:首页 > 数据库 > Redis

redis混合存储实例

2020-03-09 23:57 435 查看

简介:Redis混合存储实例是阿里云自主研发的兼容redis协议和特性的云数据库产品,混合存储实例突破redis数据必须全部存储到内存的限制,使用磁盘存储全量数据,并将热数据缓存到内存,实现访问性能与存储成本的完美平衡

架构及特性

命令兼容
混合存储兼容绝大多数redis命令,与原生redis相比,如下命令不支持或受限制;不支持的主要原因是考虑到性能。

应用场景:
(1)数据量大,有降低成本需求,正在使用Pika、SSDB、ardb等,正在使用大容量redis主备、集群
(2)数据访问有明显冷热特征,热数据能全部存储在内存
(3)对经常访问的数据性能要求高,访问频率低的数据接收更高的延迟
(4)没有大key;大key经常访问,常驻内存;大key很少访问,延时不敏感

具体场景:
视频直播类:
视频直播类业务往往存在大量热点数据,大部分的请求都来自与热门的直播间。使用redis混合存储型实例,内存中保留热门直播间的数据,不活跃的直播间数据被自动存储到磁盘上,可以达到有限内存的最佳利用效果。

电商类:
电商类应用有大量的商品数据,新上架的商品会被频繁访问,而较老的商品访问热度不高;使用redis混合存储型实例,可以轻松突破内存容量限制,将大量的商品数据存储到磁盘,在正常业务请求中,活跃的商品数据会逐步缓存在内存中,以最低的成本满足业务需求。

在线教育类:
在线教育类的场景,有大量的课程、题库、师生交流信息等数据,通常只有热门课程、最新题库会被频繁访问;使用redis混合存储型,将大量的课程信息存储到磁盘,活跃的课程、题库信息会换入到内存并常驻内存,保证高频访问数据的性能,实现性能与存储成本的平衡。

常见问题:
磁盘还有剩余空间,但内存先满啦,导致写入报错OOM error
内存规格太小,导致内存空间不足以容纳所有key及其元数据信息,建议在控制台升级实例规格即可,增大实例内存。

key对应的value比较小,混合存储对应比较小的value(比如小于20byte),不会触发换出到磁盘,因为小的value换出到磁盘,在内存中还是会存储一些meta信息,最终导致换出到磁盘并不能腾出内存空间。

与redis高性能内存型实例差别
Redis高性能内存型实例中,所有的key和Value都存储在内存中以达到极致性能。
Redis混合存储型实例中,所有的Key和经常访问的Value会被保存在内存中,保证绝大部分请求的极致性能。不常访问的Value则会被存储到磁盘上,以达到内存利用最高性价比。

存储模型

在redis混合存储实例中,我们将所有的Key和经常访问的Value保留在内存中,将不经常访问的Value保存在磁盘上。之所以在内存中保留所有的key是处于一下两点考虑:
1、Key的访问频率比Value要高很多。
作为KV数据库,通常的访问请求都需要先查找Key确认Key是否存在,而要确认一个key不存在,就需要以某种形式检查所有key的集合。在内存中保留所有key,可以保证key的查找速度与纯内存版完全一致。

2、Key的大小占比很低
在通常的业务模型里面,即使是普通字符串类型,Value比Key要大几倍。而对于set,list,hash等集合对象,所有成员加起来组成的Value更是比Key大了好几个数量级。

线程模型:

Redis混合存储实例采用单工作线程的模式,主线程为工作线程,负责处理用户请求等主要逻辑。此外,Redis混合存储实例中根据需要会配置若干个独立的IO线程负责与磁盘进行交互读写数据,IO线程读写数据时,主线程仍可继续响应其它用户请求。

数据从内存到磁盘
在周期巡检函数serverCron中,如果发现当前内存快满了,大于设定的阈值vm-max-memory(略小于maxmemory)时,会尝试挑选出一些key,将其Value保存到磁盘;
挑选的维度为最近访问时间和value大小, 公式为swappability = age*log(估算内存大小)。
主线程为挑选出的value生成IO任务,加入到IO任务队列中;
IO线程会从IO任务队列中取出任务,将Value存储到底层存储引擎(RocksDB)中, 并通知主线程。
主线程收到通知后释放Value所占用内存并标记内存中该Key对应的Value已被存储到磁盘上。

数据从磁盘到内存
当Redis混合存储实例收到用户请求时,会先判断请求是否需要读取对应Key的Value;
如果请求不需要读取相关value(比如set foo bar是不需要关心foo这个key原有的值是多少的)或者value已经在内存中,则正常执行该命令;
如果有涉及到的Value不在内存中,主线程会对应生成一个读取Value的IO任务,加入到IO任务队列中;
主线程将需要等待IO任务完成的客户端加入到等待列表,然后继续处理其余客户端的请求;
IO线程获取到读取Value的IO任务时,从底层存储引擎中读取数据,并通知主线程;
主线程收到通知后,依次处理等待该Value的所有客户端请求。

同步IO
在以下情况下,Redis混合存储的异步IO模型会退化成同步方式:

写入量太大导致后台线程不能及时将数据交换到磁盘,内存不断增加到超出maxmemory时。
由于无法预知脚本会操作哪些value以及原子性的要求,lua脚本中涉及到的value如果在磁盘上的话将会采用同步IO的方式从磁盘读取。

  • 点赞
  • 收藏
  • 分享
  • 文章举报
千里阳光号 发布了11 篇原创文章 · 获赞 0 · 访问量 313 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: