一、概述

当前KV数据库从存储介质可以分为两种模式,一种是以内存为主持久化为辅,如memcache(无持久化)、redis等;一种是以持久化为主内存为辅,如ssdb(基于leveldb/rocksdb存储引擎)。这两种模式代表了两种不同的选择策略和哲学,适应不同的业务场景。简单地说,以内存为主的模式侧重高性能,信奉“内存是新的硬盘”的哲学;以持久化为主的模式则侧重大容量,兼顾性能。

对于以持久化为主的模式,因其天然支持大容量数据的快速读写,实现冷热数据分离是相对比较容易的,当前用到的数据就认为是热数据,只要把热数据保留于指定大小的内存即可。而对于以内存为主的模式,即使有持久化,也只是顺序写的持久化,在需要读硬盘时不能做到快速读取。因此这种模式要实现冷热分离,需要准确区分冷热数据、精心设计落地策略并保证可以快速读取。

这里冷热分离方案主要基于redis或者基于redis协议及命令实现。

二、方案汇总

2.1 方案一  改造redis,使之支持冷热分离

l  实现描述:

ü  可以使用开源的rocksdb或lmdb引擎读写落地数据;

ü  写操作全部记录在内存,不同步写磁盘;

ü  常驻写子进程定时将内存中的数据写到磁盘;

ü  内存中标记不存在的key,如果一个key在磁盘上不存在,则在标记之后不用再去磁盘查看这个值是否存在;

ü  读操作先读内存,如内存中不存在且key未被标识磁盘不存在,则由读子进程从磁盘读并写回到redis(key不存在才写回)。之后子进程通知主进程再次读取,此过程会阻塞主进程上单个连接的处理。

l  优点:真正意义上实现单机redis的冷热分离。Redis和落地数据在同一台机器,容易保证数据一致性。

l  缺点:实现较复杂。因为是基于redis做二次开发,后续不方便升级redis,不过单机redis已经非常稳定,后续升级可能性较小。

l  分析:

redis定位是内存KV数据库,只支持所有数据存放在内存,持久化只是数据安全性的一种保障方式。基于redis做冷热分离的例子有两个,一个是v2.0-2.4版的原生redis,一个是jimdb S,这两个做得都不成功。

redis 2.0版加入支持VM机制,VM机制即虚拟内存机制,参考操作系统的虚拟内存机制实现,暂时把不经常访问的数据从内存交换到磁盘中,需要时再从磁盘交换回内存,可以实现冷热数据分离。但由于VM机制在某些情况下会导致redis重启、保存和同步数据等太慢及代码复杂,所以2.4版后就不再支持了。

Jimdb S是京东云平台基于redis2.8实现的KV数据库,用SSD持久化数据。使用Jimdb S可以保存全量数据,把缓存+数据库的两层架构用一层架构取代。写操作时先写内存,再异步写cycledb。读操作如数据不在内存,则创建后台任务读cycledb。这个后台任务的作用是预热,读到数据后并不把结果载入内存,执行完成后由前台主线程再次读取,这次在内存中读不到则直接读取cycledb并载入内存。目前了解到的情况是使用不广泛,而且即将下线。主要原因是性能不如纯内存的redis,但不知道是否还有其它缺陷。

从以上redis删除VM机制和jimdb S的实践情况看,直接改造redis做冷热分离可能并不是一个很好的发展方向,即使做出来也很可能是一个平庸的产品。最根本的原因是纯内存的redis性能更好,而用户对性能的期望是没有最好,只有更好。随着内存越来越大、越来越便宜,更多的数据可以直接放到内存,会进一步导致冷热分离成为一个鸡肋功能。另外一个原因是实现冷热分离会导致redis代码复杂性增加不少,不利于后续的维护。

方案二  改造备redis和proxy,备redis落地数据

l  实现描述:

ü  写操作时proxy正常写主redis,由改造备redis写rocksdb;

ü  读操作时proxy先正常读主redis,如无数据,则读改造备redis;改造备redis在内存中读不到数据则读rocksdb,proxy从改造备redis读到数据再写主redis。

l  优点:写操作和当前流程完全一样;读操作和当前迁移流程中rrw流程基本一致,可以复用。不影响纯内存的原生redis使用,风险可控。

l  缺点:proxy和redis均需修改。在原有一主一备redis基础上需要增加改造备redis部署。

l  分析:

最大特点是不影响纯内存的原生redis使用,且proxy改动较小。

可以视情况选择部署一个或两个改造备redis。只部署一个改造备redis时落地数据是单点,可用于数据丢失不重要或后端另存有全量数据的场景。部署两个改造备redis可以避免单点,因为是链式同步,对主redis几乎无影响。

方案三  改造proxy,使用ssdb落地数据

l  实现描述:

ü  写操作时proxy先正常写主redis,再同步或异步写ssdb;

ü  读操作时proxy先正常读redis,如redis无数据,则读ssdb;读ssdb成功,再写主redis。

l  优点:只改proxy,redis无须改动。

l  缺点:proxy实现较复杂,redis和ssdb的数据一致性不好保证。因为ssdb基于leveldb/rocksdb实现,在读操作且redis中无数据且ssdb内存中无数据时,可能极大影响性能。

方案四 提供ssdb,业务选择接入redis或ssdb

l  实现描述:redis和ssdb独立两套系统,类似之前腾讯提供CMEM和TSSD两套系统。业务开发根据业务特点决定使用哪一套系统。client、proxy可以复用,等同可以选择使用redis存储引擎或leveldb/rocksdb存储引擎。

l  优点:无须开发,只需引入ssdb系统即可。

l  缺点:业务开发可能没办法一开始确定使用哪一套系统。需要维护和运维两套系统。

方案五 提供ssdb,业务初始接入redis,可选择平滑迁入ssdb

l  实现描述:类似方案四,但可选择从redis平滑迁入ssdb。

l  优点:只需开发proxy支持迁入 ssdb系统即可。

l  缺点:需要维护和运维两套系统。

三、通用问题

l  读操作且redis中无数据的性能问题

不管是直接基于leveldb/rocksdb做数据落地,还是使用ssdb,都会碰到读操作且redis中无数据的性能问题,因为此时需要先读取redis,redis中读不到再一个level一个level去读取磁盘文件,这种情况的性能可想而知不会太好。

l  Redis的淘汰

redis区分冷热数据都是设定redis的maxmemory,然后进行lru淘汰使内存中只保留热数据,而Redis的lru淘汰只是从随机选的一些key选出最符合lru规则的一个key进行淘汰,即只是一种近似淘汰,所以不能很好地区分冷热数据。因此有可能出现被lru淘汰的key实际并不是冷数据,这样下次读取时会因为redis中已无数据而去磁盘读,出现一些性能问题。

l  写操作先写内存还是先写磁盘?

先写内存,此时如果系统崩溃,内存中的数据还没有来得及Dump到磁盘,会丢失数据。先写磁盘,再写内存,则即使系统崩溃,不会造成数据的丢失,但可能导致磁盘和内存数据的不一致,为了避免这种不一致,又得先删除内存中的key,再写磁盘,再写内存,影响性能。总的来说,对于以内存为主的KV数据库,优先选择先写内存。

l  SSD应用风险

为了提高读写磁盘的性能,需要使用SSD。而SSD本身存在一些问题——

•      毛刺问题:同时读写SSD盘时,读SSD盘有可能会耗时数秒。被挂住的几率为万分之一;

•      坏盘问题:SSD坏盘几率比普通sas硬盘要高;

•      坏块问题:SSD盘中可能存在某个块可以写入,但是读不出来,此时这个块的数据将会丢失。

四、总结和建议

总的来说,基于redis做冷热分离从技术上是可行的,从业务实用角度看却不一定。因为首先redis不能很好区分冷热数据,然后很难避免读取落地冷数据时的性能问题,因此肯定不如纯内存的redis性能好,而用户对KV数据库性能的期望是没有最好,只有更好。随着内存越来越大、越来越便宜,更多的数据可以直接放到redis内存,会进一步导致冷热分离成为一个无人使用的鸡肋功能。

最理想的冷热分离是redis能够满足如下三个条件:

l  lru淘汰做到淘汰的是最冷数据;

l  只在lru淘汰时落地冷数据;

l  能快速从磁盘读取冷数据并写回到内存。

这样就能在maxmemory足够时完全是纯内存KV数据库模式,不受冷数据落地的丁点影响;而在maxmemory满时进入冷热数据分离模式,又能在设大maxmemory时恢复纯内存KV数据库模式。当然要达到这个目标非常难。

从实际考虑,当前有业务确实想要冷热分离的话,建议方案四,即提供两套KV系统——以内存为主的redis系统和以持久化为主的ssdb系统,根据业务特点选择使用。考虑现有已使用redis的业务需要迁到ssdb的话,则优先选择方案五。

五、附录

附各C/C++持久化KV数据库简介和分析:

l  Leveldb

LevelDb是google开源的能够处理十亿级别规模KV型数据持久性存储的C++程序库。LevleDb在存储数据时,是根据记录的key值有序存储。LevelDb的写操作要大大快于读操作,而顺序读写操作则大大快于随机读写操作。

level一个写操作仅涉及一次磁盘文件追加写和内存SkipList插入操作,因此leveldb的写操作非常高效。

由于 LevelDB 在某一层查找不存在的数据时, 会继续在下一层进行查找, 所以对于不存在的数据的查找会速度非常慢. 所以, 需要结合 Bloom Filter, 利用 Bloom Filter 能快速地判定”不存在”的特点。

l  Rocksdb

Facebook 维护的一个活跃的 LevelDB 的分支。RocksDB 在 LevelDB 上做了很多的改进,比如多线程 Compactor、分层自定义压缩、多 MemTable 等。另外 RocksDB 对外暴露了很多配置项,可以根据不同业务的形态进行调优。

l  Lmdb

LMDB 选择在内存映像文件 (mmap) 实现 B+Tree,而且同时使用了 Copy-On-Write 实现了 MVCC 实现并发事务无锁读的能力,对于高并发读的场景比较友好;同时因为使用的是 mmap 所以拥有跨进程读取的能力。

l  Ssdb

基于leveldb/rocksdb存储引擎实现,加入网络支持,兼容redis协议和redis数据类型(不支持set集合),支持主从复制和负载均衡。SSDB/LevelDB 在进行数据库整理(Compaction)操作时, 磁盘io高,持续的时间一般随着数据变大而变长, 一般只持续数秒。不能指定执行compaction的时间。有些redis命令不支持,有些支持的redis命令可能不完全和redis一致。

l  Mangodb

分布式文档数据库。MongoDB的最大卖点是不需构建非主键索引也能执行很多查询。

l  Fatcache

SSD上实现的memcached,内存中保存索引数据,机器重启索引数据会丢失。假如只需要支持string类型数据落地,可使用代替ssdb。

l  Tair

淘宝开源的分布式KV数据库。抽象存储层的架构设计使Tair很容易接入新的存储引擎,当前支持的存储引擎有非持久化的MDB(自主研发的类memcache)/RDB(抽离Redis的存储部分),持久化的LDB(接入LevelDB)。

l  TTC

非严格意义上的KV数据库。支持无数据源和持久数据源两种工作模式。无数据源模式就是一个简单的基于共享内存的cache服务。持久数据源后接mysql,写操作先写db,再写内存;读操作先读内存,内存中不存在再去读db,读db成功再添加到内存。所以TTC本质上是一个带缓存功能的mysql数据库,可以想见其读写性能肯定不如纯内存数据库,也没有leveldb高效写的特点,注定是一个平庸的产品,再加上使用繁琐,早已被淘汰。

l  CMEM

分布式KV内存数据库,支持主从同步和平滑迁移,数据可落地,高性能。仅做KV缓存还不错,但支持数据类型和命令不如redis丰富。

关于redis的冷热数据分离相关推荐

  1. Shopee ClickHouse 冷热数据分离存储架构与实践

    本文首发于微信公众号"Shopee技术团队". 摘要 Shopee ClickHouse 是一款基于开源数据库 ClickHouse 做二次开发.架构演进的高可用分布式分析型数据库 ...

  2. mysql 冷热数据分离_elasticsearch冷热数据读写分离

    Elasticsearch5.5冷热数据读写分离 前言 冷数据索引:查询频率低,基本无写入,一般为当天或最近2天以前的数据索引 热数据索引:查询频率高,写入压力大,一般为当天数据索引 当前系统日志每日 ...

  3. 云上如何做冷热数据分离

    目录(?)[-] 前言 如何区分冷热数据 冷数据的特点 冷数据的处理 场景一极低频度的查询 冷数据备份 使用冷数据 场景二需要经常查询 方案一冷热RDS 方案二冷数据转存RDS PostgreSQL版 ...

  4. 文件服务器冷热数据划分,游戏服务器冷热数据分离方案

    冷热数据分离 当前场景: gamserver启动时,会将所有数据加载到内存中,提高读取数据的性能.但是有很多数据很可能是不常用甚至再也用不到的数据,将这些数据加载到内存中需要占用更多的内存,极大的浪费 ...

  5. Redis+MySQL冷热数据交换

    场景:某网站需要对其项目做一个投票系统,投票项目上线后一小时之内预计有100万用户进行投票,希望用户投票完就能看到实时的投票情况 这个场景可以使用redis+mysql冷热数据交换来解决. 何为冷热数 ...

  6. MySQL基于冷热数据分离优化的LRU刷盘策略

    MySQL基于冷热数据分离优化的LRU刷盘策略 前言 对于计算机刷盘这个概念相信大家都非常熟悉了,刷盘策略,其实在操作系统层面来说的话就是页面置换算法. 不知道各位朋友们还记得页面置换算法有哪些吗? ...

  7. (六)大白话MySQL是如何基于冷热数据分离的方案,来优化LRU算法?

    (一)大白话MySQL执行SQL的流程 (二)大白话InnoDB存储引擎的架构设计 (三)大白话MySQL Binlog是什么? (四)MySQL的Buffer Pool内存结构 (五)MySQL的B ...

  8. ELK ILM 策略实现冷热数据分离 持续更新

    前言:当ELK平台运行的时间越来越长,对服务器磁盘占用空间就会越来越大,传统的清理index索引数据是脚本+计划任务,虽然能够解决定时清理数据的需求,当索引越来越多,每次都要去修改脚本并不方面.ELK ...

  9. 【elasticsearch】——用ILM策略自动完成冷热数据分离

    一.前言 从Elastic Stack 迎来 6.6 版本后,就增加了ILM生命周期管理的功能.下面我们从以下几个方面来分析: 为什么索引会有生命?什么是索引生命周期? ILM 是如何划分索引生命周期 ...

最新文章

  1. 爬虫必备工具,掌握它就解决了一半的问题
  2. 通过BCS对象模型使用筛选器
  3. 简述linux各个组成部分的定义及功能,Mariadb的架构及相关概念
  4. SSM框架搭建(四) springmvc和mybatis的配置
  5. [html] 使用div+css进行布局有什么好处?
  6. html怎么转换成asp.net,Asp.net中将Word文件转换成HTML的方法
  7. 解决8080端口被占用问题
  8. wamp3.1.0下载地址
  9. 阿里巴巴优酷视频增强和超分辨率挑战赛-持续更新
  10. 4741G BIOS修复工具,黑刷bios有需要的收藏
  11. tecplot教程发布
  12. Nginx+php+mysql超时问题总结
  13. SQLyog免费下载地址
  14. 【SV中local::的用法】
  15. 冲刺阶段 - PMP易错概念(持续更新中)
  16. 【Leetcode】883. 三维形体投影面积
  17. 牛顿迭代法例题 matlab,牛顿迭代法-matlab程序(解线性方程组)
  18. Exchange Server 2010部署(一)部署Windows Server 2008 R2域控制器
  19. Unity3D使用腾讯广点通广告
  20. 解读多重启动引导文件——BOOT.INI

热门文章

  1. Ckeditor and ckfinder 配置实现截图上传图片到远程服务器
  2. 如何解决浏览器兼容性问题
  3. 阿里巴巴发布2019十大科技趋势!AI人工智能5G网络改变世界!
  4. Contributor License Agreements : 贡献者许可证协议 介绍
  5. Fillchar 引起的内存泄漏[转]
  6. 事务的acid属性是指_事务的ACID特性
  7. 【精】LintCode领扣算法问题答案:1896. 捡胡萝卜
  8. 访问一个网页的全过程
  9. 郑州中创|人才缺口超70万,多所高校新设区块链专业!
  10. 2014秋C++ 狗逮耗子之“开口说英语”