V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dusu
V2EX  ›  程序员

百万级 Hash,十亿个元素,分布式存储和索引选什么适合?

  •  
  •   dusu · 2020-02-04 20:34:35 +08:00 · 5248 次点击
    这是一个创建于 1514 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景

    各位大佬好,目前小弟手上有百万级的 Hash,约十亿个元素,格式如下:

    
    00000001
      |-key=a, val=2 字符:[1-20]-crc32 字符:整数 1:整数 2
      |-key=b, val=2 字符:[1-20]-crc32 字符:整数 1:整数 2
      ...
      |-key=z, val=2 字符:[1-20]-crc32 字符:整数 1:整数 2
      
    
    00000002
      |-key=aa, val=2 字符:[1-20]-crc32 字符:整数 1:整数 2
      |-key=bb, val=2 字符:[1-20]-crc32 字符:整数 1:整数 2
      ...
      |-key=zz, val=2 字符:[1-20]-crc32 字符:整数 1:整数 2
      
    ...
    
    

    value 格式:

    一个元素代表一个文件:
    
    2 字符:代表所在的机器
    
    [1-20]-crc32:代表目标所在文件
    
    整数 1:代表目标在文件的起始位置
    
    整数 2:代表文件长度
    
    ---例子---
    
    ab:9-cbdg3323:1200:500
    
    

    每个 Hash 的 key 大概在 100-5000 个。

    目前场景读大于写(读约 500/s,写约 200/s ),方案用的是 ssdb,

    ssdb 单线程 compact 的时候对服务影响太大,经常 loadavg 过载

    加上另外,leveldb 层面似乎更适合读大于写的场景(还有部署机器也不一定是 SSD 硬盘)。

    对比

    对比过市面上类似产品:Pika\Ledis\redix(主要对比了不同存储引擎),似乎效果相差不大。

    为什么不选 Redis?

    成本问题,目前 ssdb 已经快 100G 了,

    再加上要求分布式的话,如果能把这 十亿个元素 x5 倍 存在可观的 Redis 中,也可以考虑。

    SO. 求大佬推荐一下适合的产品(或技术方案)。

    要求:

    1. 支持「分布式」,扩容无忧
    2. 可支持高效在 hash 中「批量」检查元素 key 是否存在
    3. 高效的读大于写的场景,读 QPS 能达到目前的 5x
    4. 最好有现成的 redis/http 协议可开箱用
    5. 全家桶性质的产品慎推,不想引入太多运维成本

    备用方案:

    按 id 水平拆表存 mysql,将元素里的数据拆开来存储、索引.

    再加前置缓存...

    26 条回复    2020-05-14 11:04:23 +08:00
    vus520
        1
    vus520  
       2020-02-04 21:15:35 +08:00   ❤️ 1
    如果你的 key 读写不多,可以考虑 db 或者 ES。
    如果都是缓存级别的热数据,那估计 pika 是最好的,现在 SSD 不贵。
    fuis
        2
    fuis  
       2020-02-04 21:28:27 +08:00
    tidb
    dusu
        3
    dusu  
    OP
       2020-02-04 21:54:11 +08:00
    @vus520
    感谢,pika 其实挺好的,但是到 v3 后已经去掉 double master 支持了,
    要自行引入 codis,不然还得带 docker,运维成本并不低
    之前用 pika 当文件存储服务,存了 1.5T 文件后,
    访问量不高,但 I/O 直接吃满,性能上不去,就不敢用了...

    @fuis
    感谢,TIDB 门槛有点高,个人开发者吃不消.
    vus520
        4
    vus520  
       2020-02-04 22:21:04 +08:00   ❤️ 1
    那就 mongo 或者 ES 了
    ppyybb
        5
    ppyybb  
       2020-02-05 00:15:41 +08:00 via iPhone
    写入是指更新还是增加一个 key ? hash 数量会变化吗? latency 要求是啥
    ppyybb
        6
    ppyybb  
       2020-02-05 01:01:49 +08:00 via iPhone
    你这个限制比较多,又要省钱....要不自己搭建一个 mongo 集群,要不自己搭建 ssdb 集群(运维成本,改动小点),要不试试阿里云混合存储 redis ?
    btnokami
        7
    btnokami  
       2020-02-05 03:13:05 +08:00
    现在是 single instance 吗?搭一个 cluster 然后对 key 做 partition 应该能 scale 起来吧,或者用 Master slave model,只有 write to master 然后 read from slave 应该可以解决吧
    laminux29
        8
    laminux29  
       2020-02-05 05:15:39 +08:00   ❤️ 1
    1.海量数据,又要关键操作性能高,这种情况下,读与写本来就是个矛盾,要不读快写满,要不写快读满,你要两者都高,这怎么可能。

    2.你对开源(免费)产品,既要求性能高,又要求功能多,还要求运维成本低,这怎么可能。

    3.在一堆海量数据里,确定一条数据的唯一性,这本来就是世界难题,原因是在硬件与运维有限的前提下,这操作完全是在挑战计算机设备的性能极端,这事在理论上根本没办法搞定,就连谷歌最后都只能选择砸钱堆服务器堆运维,才有了较好的性能。你又没服务器,又没人给你运维数据性能,这事怎么可能解决得了?

    建议:
    1.你应该选择你最关注的因素,比如读速度快,然后牺牲一下写数据,按这个模式,来做业务逻辑。


    2.现在任何一款主流的分布式数据库,都做不到帮你把冷热数据均摊好,保证每台物理设备的性能平均。因为这个操作要涉及到经常的大规模的数据迁移,这个过程本身就会大幅度降低系统性能。因此,还不如你自己设计一个冷热数据记录器,再根据业务繁忙度,在闲时就像停服一样,重新分布冷热数据。这操作其实就是运维工作,你不去做这个工作,没办法把冷热数据高质量地均摊在不同物理设备上。
    raynor2011
        9
    raynor2011  
       2020-02-05 07:25:55 +08:00 via Android
    Hbase?
    xautll
        10
    xautll  
       2020-02-05 08:57:23 +08:00
    clickhouse 可以参考一下
    sampeng
        11
    sampeng  
       2020-02-05 09:06:31 +08:00 via iPhone
    redis 完全够用…才百万级和 10 亿个元素…你也太小看 redis 了
    defunct9
        12
    defunct9  
       2020-02-05 10:44:03 +08:00 via iPhone
    楼主最后用什么?
    cabing
        13
    cabing  
       2020-02-05 10:48:28 +08:00
    @dusu

    算下成本。你的存储时 100G 吗?

    如果觉得 redis 成本高的话,

    单机的 io 又比较大,为啥不自己写个简单的 proxy 呢?

    底层挂哪个存储都行,ssdb 或者 pika 或者直接用 rocksdb 做个存储也行。
    dusu
        14
    dusu  
    OP
       2020-02-05 13:07:52 +08:00 via iPhone
    @ppyybb 感谢,目前用的就是 ssdb 集群。
    dusu
        15
    dusu  
    OP
       2020-02-05 13:10:51 +08:00 via iPhone
    @btnokami 目前是集群 回头试试 key 分片。
    dusu
        16
    dusu  
    OP
       2020-02-05 13:12:24 +08:00 via iPhone
    @xautll 似乎 clickhouse 适合于离线分析 ,不适合高并发下 kv 查询。
    wingyiu
        17
    wingyiu  
       2020-02-05 13:13:14 +08:00
    redis 分片方案呗
    dusu
        18
    dusu  
    OP
       2020-02-05 13:15:19 +08:00 via iPhone
    @laminux29 大佬说的是,问题描述确实有些矛盾,其实也是想请教一下在这个场景下,大家会用的一些低成本高收益的方案。
    dusu
        19
    dusu  
    OP
       2020-02-05 13:18:06 +08:00 via iPhone
    @cabing 自己做 proxy 其实也尝试过 单机问题不大。但是涉及到「分布式」这块一致性和稳定性比较难彻底解决。遂放弃。
    cabing
        20
    cabing  
       2020-02-05 13:23:38 +08:00
    @dusu


    分布式的 meta,使用 consul 或者 etcd 存下 meta 信息。

    比较简单方案:做个一致性 hash,然后每个 node 都自己做个简单的拷贝方案,分布式存储存下 meta,这个最简单啊

    需要改造,获取数据时做个 proxy 改造
    luozic
        21
    luozic  
       2020-02-05 13:30:27 +08:00 via iPhone
    是在云里面还是物理机器? 物理机器可以去看看 dpdk 这种方案,不过想要低成本的条件的话,最好根据具体的需求特征定制一下 proxy 层,存储层基本现在开源的 rocksdb 系的基本可以直接用。 通用的肯定不是特定场景下的成本最低方案。
    justfly
        22
    justfly  
       2020-02-05 13:40:11 +08:00
    直接尝试 redis cluster 吧。

    我算了一下你的 value,大概 30 个字节,10 亿级别占用大概不到 30G 内存空间,留 5 倍的扩展空间和 value 外额外空间,redis 集群使用 10 个以内的节点够用了。
    ppyybb
        23
    ppyybb  
       2020-02-05 18:48:29 +08:00 via iPhone
    @dusu 原来是集群那你扩大分片不就行了,怎么会有 100g 呢?你说的集群是主从?
    wangyzj
        24
    wangyzj  
       2020-02-05 20:36:35 +08:00
    redis 啊
    又不是不够用
    再就得看业务场景和其它功能了
    aliipay
        25
    aliipay  
       2020-02-06 12:14:43 +08:00
    val 搞什么 string,直接用 byte 定义
    机器名:2Byte 最高支持 65536 台,如果不超过 128 个节点可以设为 1B,高 1 位保留扩展性
    文件:crcr32 只要 4Byte
    文件起始: 不知道具体范围,假设 4GB 内, 就是 4Byte. 如果存在小数值偏多,可以考虑 utf8 编码
    文件长度:同上
    所以总长度在 14B 左右,目测能少掉一半量
    wzw
        26
    wzw  
       2020-05-14 11:04:23 +08:00
    @dusu #14 根据你的了解, ssdb 和 pika 有啥区别呀, 最直观的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3330 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 13:35 · PVG 21:35 · LAX 06:35 · JFK 09:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.