IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    [原]ssd-cache 不错的kv系统总结

    zhoubl668发表于 2015-04-27 18:59:31
    love 0

    Table of Contents

    • 1 需求
      • 1.1 why
      • 1.2 具体需求
    • 2 index
    • 3 ssd 特性
      • 3.1 成本
      • 3.2 接口
      • 3.3 比较典型的ssd参数
      • 3.4 小结
    • 4 现有系统调研
      • 4.1 基于redis修改
        • 4.1.1 redis-vm
        • 4.1.2 redis-storage
        • 4.1.3 小结
      • 4.2 单机存储引擎
        • 4.2.1 LevelDB
        • 4.2.2 RocksDB(facebook)
        • 4.2.3 Berkley DB
        • 4.2.4 nessDB(国人开发)
        • 4.2.5 小结
      • 4.3 备选项目
        • 4.3.1 ssdb
        • 4.3.2 fatcache
        • 4.3.3 ardb
        • 4.3.4 ledisdb
        • 4.3.5 其它
        • 4.3.6 小结
      • 4.4 成熟分布式存储系统
        • 4.4.1 淘宝tair
        • 4.4.2 aerospike
        • 4.4.3 #facebook Apollo
        • 4.4.4 #facebook-McDipper
        • 4.4.5 #腾讯CKV海量分布式存储系统
        • 4.4.6 小结
      • 4.5 其它思路
    • 5 小结
      • 5.1 关于目前的很多系统

    1 需求

    1.1 why

    用redis内存实在太贵了, 假设要存1T数据双副本:

    • 内存: 1000*2 / 64 = 32台机器.
    • 2T盘机器: 2-4台

    1.2 具体需求

    1. 数据存放在ssd.
    2. 性能要求: 6台机器的集群10w/s, (单机2w/s)
    3. 有expire功能.
    4. 使用redis协议 (twemproxy, client-lib可以复用)
    5. 数据类型仅支持kv, 以后可以考虑支持hash.

    其它:

    • 事务或script支持.
    • 主从, failover
    • 集群.
    • redis-mgr 部署支持

    2 index

    主要涉及下面几个方面:

    1. ssd特性.
    2. 存储引擎, 如LevelDB, RocksDB, BDB等.
    3. 现有系统的调研和benchmark, 主要关注SSDB和fatcache.

    本文是这个调研系列的目录和结论, 相关调研:

    • coding-for-ssd笔记
    • LevelDB 调研 TODO
    • SSDB代码阅读
    • SSDB benchmark
    • fatcache 代码阅读

    3 ssd 特性

    3.1 成本

    --国外国内2T成本
    ssd$0.6/GB京东价格(400元/128G=3.1元/GB)6000
    hdd:$0.12/GB京东价格(400元/1T=0.4元/GB)800
    • 实际上, 我们买服务器的时候, 价格会更便宜些, 不过还是这个数量级.
    • 考虑到一台1U服务器价格 在3-5w, 使用2T ssd带来的成本上升: 5200/30000 = 18%左右, 并不算太贵, 加之后续电费等消耗, 可以认为使用ssd带来的成本上升小于15%
    • 当然, 我们不能用ssd来存文件之类的大/冷的数据, 这是明显的浪费.

    3.2 接口

    目前ssd主要2种接口:

    • sata

    • pci-e, 性能更高.
      • 典型产品如:
        • Fusion-io ioScale Gen2 (w: 4w, r:5w)
        • Fusion-io ioMemory (w: 32w, r:19w)
        • 华为ES3000 (w: 10w, r:15w)
        • MemblazeQ520 (w:7w, r:3w)

    sata 带宽6Gbps, pci-e 常见带宽 3.2G*8 = 24Gbps.

    3.3 比较典型的ssd参数

    ProductIntel SSD 320Intel SSD 530ioMemory PX600
    ComponentsMLCMLCMLC
    Launch Date20112013
    Sequential Read270 MB/s540 MB/s2700 MB/s
    Sequential Write220 MB/s490 MB/s1500MB/s
    Random Read (8GB Span)39,500 IOPS48,000 IOPS196,000 IOPS
    Random Write (8GB Span)23,000 IOPS80,000 IOPS320,000 IOPS
    Latency - Read75 us80 us92 us
    Latency - Write90 us80 us15 us
    interfaceSATA 6.0 Gb/sSATA 6.0 Gb/sPCI-Express 2.0 x8

    数据来源:

    • Intel-SSD-320: http://ark.intel.com/products/56569/Intel-SSD-320-Series-600GB-2_5in-SATA-3Gbs-25nm-ML
    • Intel-SSD-530: http://ark.intel.com/products/75336/Intel-SSD-530-Series-480GB-2_5in-SATA-6Gbs-20nm-MLC
    • Fusion-io: http://www.fusionio.com/data-sheets/iomemory-px600-atomic-series/

    notes:

    • 这里选的 Fusion-io ioMemory系列, 写可以达到32w/s, 写延迟只有15us, 很明显写操作都是先写buffer.

    • 对三块Intel-SSD-530 做raid0后, 用fio进行了测试, 数据和标称数据差不多:
      • random-write: 5.5w/s
      • random-read: 7.3w/s

    3.4 小结

    • 随机读性能好

    • 随机写性能较差
      • 写放大: 写一个字节也会导致整个page的read-modify-write

      • 应该尽量避免small-write

      • 很多ssd会通过 hybrid log-block mapping 来做写merge. 从而减轻写放大,
        • 这相当于把Log-Structure的一些算法在ssd控制器这一层实现了, 从而实现较高的随机写性能.
        • 但是即便有了 hybrid log-block mapping, 也应该尽量避免small-write(因为需要多次操作映射关系表)
      • ssd在大量写压力下, 性能可能恶化到8000iops.
        • 因为很多update, GC可能跟不上, 如果每次写操作需要做一次erase整个block, 就悲剧了.
        • 正常情况下, GC利用后台的时间, 可以完成erase工作.
    • 顺序读写和hdd在同一量级.

    • 寿命有限

    ssd可以通过下面这些方式调优:

    • 调整page/block的大小, 较小的擦除块可以得到较高的wqps.
    • gc策略: 可以通过不同的算法优化, 这是ssd控制器FTL的核心技术.
    • Flash Translation Layer (FTL) 上做 hybrid log-block mapping 优化随机写.
    • 使用 TRIM 命令, 会有少量优化.

    详细参考: coding-for-ssd笔记

    4 现有系统调研

    针对我们的需求, 调研了一些现有的系统, 主要分三类:

    • 基于redis的修改如redis-vm.
    • 单机引擎如Berkley DB, LevelDB.
    • 一些和我们需求接近的现有系统, 如ssdb, fatcache等.
    • 成熟产品, 如淘宝tair, aerospike 等.

    4.1 基于redis修改

    4.1.1 redis-vm

    • http://antirez.com/news/52
    • http://blog.nosqlfan.com/html/1047.html

    redis在2.2-2.4曾经做过vm功能, 来将内存扩展到磁盘, 但是不久就被废弃了, 原因主要是造成性能不稳定.

    存在的问题:

    • slow restart: 重启太慢
    • slow saving: 保存数据太慢
    • slow replication: 上面两条导致 replication 太慢
    • complex code: 代码过于复杂
    • 2.4 之后就已经从redis代码中移除了.

    作者的观点:

    • have Redis do what it does best - very quickly serve data from RAM.
    • 估计当时的测试, 使用的磁盘都是hdd, 那当然性能糟糕, 如果换成ssd应该会好些.

    4.1.2 redis-storage

    • 把leveldb嵌入到redis.

    • 完成度较高, 新增了一些rl_开头的命令:

      rl系列命令:(同时操作redis和leveldb系列命令)
      =======string数据操作======
      rl_get key            (从redis或leveldb取值, 优先顺序:redis > leveldb)
      rl_getset key         (返回同rl_get, 当leveldb有值,redis无值时,会回写到redis)
      ...
      
    • 读: 先从redis读取, 如果redis没有,则到leveldb读取。

    • 写: 先写到leveldb中,写成功了,再写到redis中

    • 问题:
      • 这个项目的目的是把redis的内存扩大2-5倍, 把redis作为leveldb的cache+store. 两份storage很诡异.

      • 作者设计的时候, 应该是考虑到兼容redis, 客户端尽量不需要改动, 冷key会自动淘汰,
        • 但是实际上提供了两套命令, 客户端需要根据情况, 指定只写redis/只写leveldb还是双写. 就很麻烦.
      • 没有expire支持, leveldb过大后, 怎么办?

      • 完全没有考虑到主从的设计.

    参考:

    • https://github.com/qiye/redis-storage
    • http://www.guangla.com/post/2014-03-17/40061277735 (shenzhe)

    4.1.3 小结

    基于redis的改进, 主要有这么几种:

    1. 增加新命令
    2. 在key被淘汰时写磁盘
    3. key一直在内存, 把某些value放磁盘(redis-vm的实现方案)

    如果基于redis来实现, 存在下面一些问题:

    1. 主从同步很可能被破坏(现有全量同步机制需要重新改写)
    2. 重启时加载数据的机制.
    3. 不能支持全部命令, 容易造成混淆.
    4. 不能被主流所接受

    如果不基于redis代码来做:

    1. 主从同步需要重做
    2. sentinel机制需要重做.

    4.2 单机存储引擎

    4.2.1 LevelDB

    LevelDB是BigTable的单机存储, LSM-Tree 思想, 写操作都转化为顺序写.

    特点:

    • KV引擎

    • 支持SCAN(iteration)

    • Snappy压缩

    • 随机读写能达到 10w/s 的性能
      • 这里性能是小数据量下, 还不刷盘的情况
      • 实际写能到10w, 读取决于存储介质.
    • 支持Bloom Filter, 能在一定程度上优化读性能.

    4.2.2 RocksDB(facebook)

    • 基于LevelDB改进
    • 更好的利用多核等
    • 代码包比LevelDB复杂.

    4.2.3 Berkley DB

    • 历史悠久的嵌入式数据库

    • 支持事务, 细粒度锁.

    • 支持多种算法
      • B+树
      • Hash
      • Heap(更节约空间)
      • Recno
      • Queue(定长record)
    • 对一些老的UNIX数据库, 如dbm, ndbm接口兼容.

    http://docs.oracle.com/cd/E17076_02/html/programmer_reference/am_conf.html

    4.2.4 nessDB(国人开发)

    • 支持事务 特点

    • 自己实现存储引擎, 不是基于LevelDB
      • 3.0 提供 Buffered-Tree index (Toku的FT-Tree)
      • 作者是TokuDB的贡献者.
    • 2011-2014持续开发, 目测代码质量很高.

    • 本身是一个库.

    • 还提供一个服务端,支持Redis的 PING, SET, MSET, GET, MGET, DEL, EXISTS, INFO, SHUTDOWN 命令,
      • 现在已经专注于实现引擎, 不提供server功能了.
    • 整个引擎基于LSM-Tree思想开发,对随机写非常友好。为提高随机读,nessDB使用了Level LRU和Bloom Filter策略。

    • 引擎是自己开发的, 还需要时间验证.

    4.2.5 小结

    • 较老的存储引擎都基于B+树或Hash实现, 写性能差.
    • 较新的存储引擎基于LSM-Tree, Log Structed Hash, FT-Tree之类新的数据结构, 针对写进行优化, 写性能能得到很大改善
    • 读操作主要取决于底层磁盘能提供的 随机读IOPS , 通过Bloom Filter等能有一定的优化.

    4.3 备选项目

    4.3.1 ssdb

    • ssdb 是一个基于leveldb的kv存储, 提供兼容redis的协议

    • 支持String, Hash, Zset, Queue几种数据结构.

    • 支持Expire和主从同步

    • ssd上写性能稳定在3.8wqps, 不会随着写数据增多而变差, 和hdd差不多,

    • 读性能稳定在5000qps, 不能充分发挥硬件性能, 这主要是由于读操作是单线程顺序执行.

    • 主要问题:
      • 读性能问题(多线程可达到15000)
      • 所有expire的key记录在内存
      • 兼容问题(expire/ttl/del都有问题, scan类设计上和redis不同)

    详细参考:

    • SSDB代码阅读笔记
    • SSDB benchmark

    4.3.2 fatcache

    • Memcache on SSD

    • Log-Structure Hash结构.

    • 不能持久化(元数据不落盘, 重启后数据丢失)

    • 性能不错, Initial performance results with fatcache 100K sets/sec, 40K gets/sec on a single SSD

    • 读不命中时效率高(所有key记录在内存中)

    • 写裸盘. 需要root.

    • 主要问题:
      • 不持久化

      • key都放在内存, 如果10亿条的话, 每条key 32字节, 就需要32G. 此时存的数据(100字节/kv) 大约100G.
        • 所以这适合value较大的情况, 比如1K, 这样32G内存就能管理1T数据.

    详细参考: fatcache代码阅读笔记

    4.3.3 ardb

    https://github.com/yinqiwen/ardb

    • Full redis-protocol compatible
    • Most redis commands supported, and a few new commands
    • Replication compatible with Redis 2.6/2.8
    • Auto failover support by redis-sentinel
    • 存储引擎支持 LevelDB/LMDB/RocksDB
    • 空间索引.
    • 代码量5w, 很难想象是一个人的作品. (HUST)

    看上去很不错, c++实现.

    4.3.4 ledisdb

    • go 实现(金山 siddontang)
    • https://github.com/siddontang/ledisdb
    • 支持多种引擎: LevelDB, goleveldb, LMDB, RocksDB, BoltDB.
    • 支持expiration
    • 比GoRedis完善
    • 写的很细心
    • lua
    • redis 协议 +rest协议

    设计:

    • http://siddontang.com/2014/05/10/ledisdb-introduction/
    • http://siddontang.com/2014/05/30/ledisdb-design-1/
    • http://siddontang.com/2014/06/14/ledisdb-design-2/

    4.3.5 其它

    • memcachedb
      • https://gitorious.org/mdb/memcachedb/source/9f2e5415e4d9017889caf61c100a9b8652825319
    • redis-leveldb
      • 不是基于redis的代码,
      • https://github.com/KDr2/redis-leveldb
      • redis-protocol compatible
      • libev, cpp实现.
      • 2000行代码, 简单实现的玩具, 代码中各种printf直接输出到终端. 代码质量差
      • 没有expire, 主从同步,
    • seqdb
      • 提供sql接口的kv.
    • GoRedis
      • go实现, (陌陌)
      • 存储引擎使用RocksDB, redis接口.
      • 不支持expire
      • slaveof-proxy为两个redis建立自定义的主从同步,包含限速、断线重试等。
    • rdisk 是一个hackathon项目, 提供兼容redis的协议.
      • libuv做服务
      • rangel 解析
      • tokyocabinet 作为存储引擎(作为.so嵌入)
      • https://github.com/Moodstocks/redisk
      • 是一个不错的开始
    • lycadb
      • An experiment with InnoDB storage for a Redis-like key/value store
    • redis-land-go
      • https://github.com/xjdrew/redis-land-go
      • 旁路监听,把redis数据存盘到leveldb

    4.3.6 小结

    • 有很多尝试做兼容redis的磁盘存储的项目,
    • 在设计实现上都存在或多或少的问题.

    4.4 成熟分布式存储系统

    4.4.1 淘宝tair

    • 淘宝开发的分布式 key/value 存储系统

    • 模块
      • config-server (master+slave)
      • data server (存储节点)
      • 客户端保存路由表, 有local cache
      • 一致性hash+数据迁移
    • 存储引擎
      • mdb: 缓存, 支持kv,
      • rdb: redis内存结构, kv, list, set, zset.
      • ldb: 基于leveldb.
    • 需要专用的 client lib.

    • 支持多副本, 多版本.

    • 规模(2011):
      • 共有20多个集群,400多台的服务器,其中300多台是cache的,每台提供22G的内存。其他的是持久化的Tair集群。
      • 存放了数百亿条记录,每秒百万级别的请求数。

    http://code.taobao.org/p/tair/wiki/intro/

    4.4.2 aerospike

    • 商业产品, 开源.

    • 三层:
      • client 感知数据存在哪里
      • Distribution Layer
      • Data Storage Layer: 单机引擎.
    • API形式: 不是简单的key/value, 每个key需要指定 (namespace, set, key), 应该是为了控制锁粒度.

    • Indexes are always stored in RAM.

    • 数据类型: map, list, integer, string, blob.

    • 可配 expire

    • 支持lua.

    • 支持Secondary indexes, 不是简单kv, 更像mongo

    • 支持Hot Analytics (distributed aggregations or indexed map-reduce)

    https://github.com/aerospike/aerospike-server

    4.4.3 #facebook Apollo

    http://www.infoq.com/news/2014/06/facebook-apollo

    • Paxos-like NoSQL database
    • C++
    • 低延迟, 特别是Flash and in-memory
    • 不是简单kv, 支持数据结构: maps, queues, trees
    • 分布式, 有shard概念, 每个shard内基于RocksDB.
    • Apollo isn't currently being used in production at Facebook
    • The company is also looking at using Apollo as a reliable queuing system
    • 是分布式的ssdb
    • 还没开源.

    4.4.4 #facebook-McDipper

    https://www.facebook.com/notes/facebook-engineering/mcdipper-a-key-value-cache-for-flash-storage/10151347090423920

    Compared with memory, flash provides up to 20 times the capacity per server and still supports tens of thousands of operations per second,

    • 大约12年5月上线.
    • cache替换策略: LRU或者FIFO
    • you can enable bloom filters to avoid unnecessary reads
    • 主要用于图片服务器的缓存(cdn上) 后端是HayStack.
    • We serve over 150 Gb/s from McDipper forward caches in our CDN.
    • 是一个cdn用的cache存储. memcache协议.
    • 不开源.

    4.4.5 #腾讯CKV海量分布式存储系统

    (闭源, 这里参考一个ppt)

    http://www.csdn.net/article/2014-03-11/2818723

    高性能、低延时、持久化、分布式KV存储服务, 日请求数: 超过万亿次 (那得看多少套集群)

    与Memcached和Redis等开源NoSQL相比,CKV具有以下优点.

    • 内存+SSD, 99%命中率(取决于应用)

    • 可以扩展到1PB

    • 单表 千万qps

    • 单台Cache服务器千兆网络环境支持50万/秒的访问,万兆网络环境支持超过100万/秒的访问

    • 双机热备,主备切换对业务透明. redis一样.

    • 扩容: 需要停写
      • 扩容过程如下:Master将禁止shard2数据写访问命令发送给Access
    • 规模: 近万台服务器
      • 万台, 每天万亿请求, 那就是说1亿/台, 每台只相当于1000qps.

    4.4.6 小结

    • 这里的几个系统, 都是类似GFS的架构, config-server + data server + 智能client
    • 支持动态数据迁移和路由更新.
    • 它们都有各自的接口, 相对来说比较复杂.

    4.5 其它思路

    • HBase/Cassendra/MySQL on ssd?
      • 可以利用现有hbase等系统良好的扩展性, 性能上也能有所保证
      • 接口不兼容.
      • 过于复杂.

    5 小结

    • 为了避免随机写, 现在很多存储引擎都是Write-optimized的, 基于LSM的思想来开发, 比如:
      • fatcache/Riak: Log-Structure Hash table
      • RethinkDB: Log-Structure B-tree
      • LevelDB, Cassendra, HBase: Log-Structure merge tree.
    • LevelDB 平均每次读大约需要1.3-1.5次IO, Log-Structure Hash 只需要1次, 但是不能scan.

    • ssdb/ardb/nessDB/ledisdb 都是国人做的, 很赞, 值得持续关注.

    • 可以否决基于redis做的改造.

    • 基于LevelDB或者RocksDB封装提供redis协议比较简单, 难点主要是expire/replication/failover的实现.

    5.1 关于目前的很多系统

    无论对redis改造或者是重新实现, 在数据结构/expire/主从同步上, 都延用了redis的做法, 比如:

    • 支持富数据结构

    • expire信息放在内存

    • 主从断掉全量同步.

    • 依然有rdb, 整个库占了1T磁盘, rdb出来也占1T => 这些设计可能没考虑1T这个数据量级, 只考虑100G这个量级.
      • 比如ardb依然使用rdb做同步.
    • 甚至有的还会把磁盘操作计入aof, 再加上aof_rewrite,

    由于数据规模变大(60G=>600G的级别) 这些设计就存在问题.

    代码特点expirerepl其它
    2redis-storage redis+特定命令无无专注于使内存成为磁盘的cache
    3ssdb 单独key存储
    3ardb5wcpp, 复杂, 地理索引
    • 存储:
    • 同步: ?
    • 切换: ?
    兼容性好, 沿用redis, 依然支持rdb
    3ledisdb(go) 金山2w 单独key存储, 定期elim
    • 存储: 自定义binlog,fid+offset
    • 同步: 从拉,全量+增量
    • 切换: 全量同步
    2GoRedis2w






    转字:http://idning.github.io/ssd-cache.html



沪ICP备19023445号-2号
友情链接