V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wuhao1
V2EX  ›  数据库

问下站内大神们 成千上万的小说-存储方案

  •  1
     
  •   wuhao1 · 2024-09-26 17:54:27 +08:00 · 7217 次点击
    这是一个创建于 391 天前的主题,其中的信息可能已经有所发展或是发生改变。

    1.数据库存储
    2.磁盘存储
    3.oss 存储
    4. ?
    结合 速度和成本 最好的会是那种方案呢?
    个人倾向于磁盘 速度快成本低

    团队倾向于 oss

    87 条回复    2025-03-02 16:42:10 +08:00
    Kinnice
        1
    Kinnice  
       2024-09-26 18:02:28 +08:00
    有分布式要求吗? 没有就磁盘,有就对象存储
    数据库只在你需要大量全文检索的时候再说
    dynastysea
        2
    dynastysea  
       2024-09-26 18:03:45 +08:00
    你团队是对的,磁盘你怎么管理元数据?
    MoYi123
        3
    MoYi123  
       2024-09-26 18:11:15 +08:00
    怎么可能直接存磁盘啊, 打算自己造几年轮子啊.
    shadowyue
        4
    shadowyue  
       2024-09-26 18:14:00 +08:00
    当然是现成的 OSS ,你估计下各种方案最终落地需要的时间
    13240284671
        5
    13240284671  
       2024-09-26 18:20:03 +08:00
    不都是存数据库吗?一本小说 20M,存 oss 咋打开?
    wuhao1
        6
    wuhao1  
    OP
       2024-09-26 18:29:24 +08:00
    oss 对于密集操作,很不友好,网络 IO 开销太大了

    @Kinnice 暂时没有分布式要求
    @dynastysea 磁盘只要存 章节内容就行了, 章节的元数据存数据库

    @MoYi123 用磁盘主要是 方便 和 性能的考虑
    @shadowyue oss 其实成本应该比磁盘贵

    @13240284671 书少确实存数据库, 但是海量的书存数据库就不合适宜了, 主要是数据库的存储太贵了
    Pitttttt
        7
    Pitttttt  
       2024-09-26 22:27:00 +08:00
    什么需求需要存数据库呢?数据库存元数据(名字大小目录之类的),本地盘存实际文本会不会好些
    rui6ye
        8
    rui6ye  
       2024-09-26 23:35:17 +08:00   ❤️ 1
    好巧 我的小说文章网(只是一个工具的部分功能)也正在收录,刚发布完。资源来源 pdd 的几十块的 U 盘,大部分格式是 pdf 的,其他是 txt 等,偷个懒我直接传诚通网盘了,直接下载。要兼容这么多格式,工作量太繁琐。
    3 天时间一口气发布了 4w 多篇文章。
    https://li2345.com/read
    dode
        9
    dode  
       2024-09-27 09:20:28 +08:00
    暂时没有分布式要求,单机网络开销多大? 现在网络已经存在性能瓶颈了吗?
    abersheeran
        10
    abersheeran  
       2024-09-27 09:52:19 +08:00
    我还真做过,我的做法是一本小说压缩后分章节存入 sqlite 。这里有几个原因,第一是可以让细碎的章节文件合并起来,还有是查 sqlite 要比直接从文件系统读取更快,以及当用户阅读一本书的时候,应该是连续的,要把后续章节提前拉到本地做缓存,而不是只把当前章节拉到本地做缓存。当时我抓了压缩后接近一个 T 的小说数据。
    abersheeran
        11
    abersheeran  
       2024-09-27 09:54:49 +08:00
    sqlite 文件放在 OSS 上进行保存。本地做一个缓存机制,100GB 硬盘可以缓存几万本书,对于小站点来说完全够了。普通的 CC 攻击打不死。
    sincw
        12
    sincw  
       2024-09-27 10:17:28 +08:00
    小说网站感觉基本 99%的小说都是在吃灰状态。oss+本地热缓。oss 主要节约时间来着
    elboble
        13
    elboble  
       2024-09-27 11:31:16 +08:00
    磁盘存文件,meta 存 mongo ,字段包括书名作者概要及文件路径等等。关键 meta 元素的提取怎么来。

    如果全文检索只能都进数据库了吧。

    没用过 oss ,认知范围内只会这样。
    baijiahei
        14
    baijiahei  
       2024-09-27 11:53:43 +08:00
    成熟方案
    参考杰奇小说
    元数据 mysql 小说 txt 扔硬盘
    生成纯静态 html
    热文件扔 ssd 什么压力都没有
    wuhao1
        15
    wuhao1  
    OP
       2024-09-27 13:46:09 +08:00
    oss 确实不失是一个好方法,但是在集中密集操作就暴露缺点了,如果我要读完整的一本书的内容, 网络开销太大了

    还有就是如果是免费小说那么静态化再加上 CDN 毫无压力, 可是如果是收费呢?

    总结: 把磁盘和 oss 的优点集中起来, 既存 oss 又存磁盘, 有没有就好很多 ……^_^

    不存数据库的话全文检索又是一个问题。
    815979670
        16
    815979670  
       2024-09-27 13:57:43 +08:00
    如果没有全文检索需求的话可以压缩存储,web 场景下 cpu 资源很多都是被浪费了(常年在 20%以下),可以通过压缩利用起来
    815979670
        17
    815979670  
       2024-09-27 15:43:55 +08:00
    @abersheeran 能详细说说怎么存的吗,一本小说一个 sqlite 文件 还是 1T 数据全是同一个 sqlite 文件 或者时按照其他规则拆分的? 压缩算法用的时 zip 吗? 我之前有尝试用 zip 算法压缩文本 然后存入 sqlite 体积只有原来的四分之一
    ytmsdy
        18
    ytmsdy  
       2024-09-27 20:34:01 +08:00
    如果预算够,直接上 oss ,如果做磁盘存储的话,备份是一个很大的问题。小说文件都是小文本,小文件备份效率非常低。
    oss 除了费钱以外,其他都挺好的。oss+cdn ,基本上不用这么管。
    wuhao1
        19
    wuhao1  
    OP
       2024-09-29 09:16:13 +08:00
    @ytmsdy OSS 应对密集操作不友好,网络 IO 太高
    wxf666
        20
    wxf666  
       2024-10-01 04:31:17 +08:00
    @815979670 #17 全是一个 SQLite 文件,应该也没啥不妥吧。。

    我在隔壁帖,测试了单表 1.3 亿 100 GB 数据,六七年前轻薄本上,还能上万随机读/写事务并发。。


    压缩存储,感觉用 zstd 较好?压缩率接近 lzma ,但解压速度快 7 倍。。

    可以测试一下,每 N 个章节一起压缩后总大小 S0 ,与整本小说压缩后大小 S1 ,的关系。

    选 N 尽量小(只读取一章时,不用浪费太多力气解压更多章节),S0 又尽可能逼近 S1 的( N 太小,会浪费很多空间,反复存储词典啥的?导致 S0 远大于 S1 。。)


    或者试试,行级别的 zstd 压缩插件( https://github.com/phiresky/sqlite-zstd ),或者页级别的( https://github.com/mlin/sqlite_zstd_vfs ),或者官方 $4000 的( https://sqlite.org/purchase/zipvfs


    对了,中文内容的话,换成 UTF-16 存储,能直接省 1/3 空间。。
    wxf666
        21
    wxf666  
       2024-10-01 05:02:53 +08:00
    @wuhao1 相比磁盘存储,为嘛不选 SQLite 数据库呢?感觉优点还行呀:


    1. 单表 1.3 亿 100 GB 大小时,六七年前轻薄本上,仍能上万随机读/写事务并发。且只占用 16 MB 内存。[源码在隔壁帖]( /t/1075881#reply65 )


    2. 官方宣称,相比文件系统,10 KB 文件存数据库里,能快 35%,节省 20% 空间。[文章]( https://sqlite.org/fasterthanfs.html )

    你按章节来存的话,假设每章 5000 汉字,UTF-16 存,恰好 10 KB 。


    3. 支持全文索引,甚至拼音/首字母/多音字。可无限搜索事务同时进行。

    微信宣称,手机端百万百字聊天记录,搜三字词,只需 0.0029 秒。10 秒全文索引完毕。[文章]( https://mp.weixin.qq.com/s/Ph0jykLr5CMF-xFgoJw5UQ )


    4. 备份迁移时,没有天量小文件烦恼。

    两周后,SQLite 会发布一个,[远程增量同步工具]( https://sqlite.org/draft/rsync.html )。
    wxf666
        22
    wxf666  
       2024-10-02 15:27:51 +08:00   ❤️ 1
    @abersheeran #10
    @815979670 #17

    我用近 14000 章的《带着农场混异界》,试了一下 zstd 的预训练词典,感觉很适合分章节压缩存储,

    因为 UTF-8 时,整本压缩率 20%,分章节总压缩率也才 22% ~ 28%,还能快速随机选取章节。

    如果独立压缩章节,总压缩率飙到 38%。



    1. 压缩后,UTF-16 没有明显优势。所以采取 UTF-8 就好。

    UTF-8 时 137.4 MB
    - gzip 压缩 43.5 MB ( 31.7%)
    - zstd 压缩 28.7 MB ( 20.9%)
    - lzma 压缩 26.8 MB ( 19.5%)

    UTF-16 时 96.9 MB ,
    - gzip 压缩 39.0 MB (少 10.5%,相比 UTF-8 压缩后)
    - zstd 压缩 27.6 MB (少 3.9%)
    - lzma 压缩 25.2 MB (少 6.2%)


    2. 分章节后,所有压缩算法表现都很差。可选择多章节压缩,或分离词典。

    - gzip 后共 55.6 MB ( 40.5%)
    - zstd 后共 51.8 MB ( 37.7%)
    - lzma 后共 52.4 MB ( 38.2 %)


    3. 只有 zstd 支持预训练词典,且不同词典大小,分章节总压缩率也不同。

    - 32 KB 词典(压缩后 12.6 KB ),压缩后+词典 39.6 MB ( 28.8%)
    - 64 KB 词典(压缩后 24.7 KB ),压缩后+词典 37.8 MB ( 27.5%)
    - 110 KB 词典(压缩后 41.9 KB ),压缩后+词典 36.6 MB ( 26.7%)← 默认词典大小
    - 128 KB 词典(压缩后 48.7 KB ),压缩后+词典 36.3 MB ( 26.4%)
    - 256 KB 词典(压缩后 97.8 KB ),压缩后+词典 35.0 MB ( 25.5%)
    - 512 KB 词典(压缩后 197.2 KB ),压缩后+词典 34.1 MB ( 24.8%)
    - 1024 KB 词典(压缩后 315.3 KB ),压缩后+词典 33.0 MB ( 24%)
    - 2048 KB 词典(压缩后 611.2 KB ),压缩后+词典 32.1 MB ( 23.3%)
    - 4096 KB 词典(压缩后 1164.8 KB ),压缩后+词典 31.2 MB ( 22.7%)
    - 8192 KB 词典(压缩后 2328.5 KB ),压缩后+词典 32.4 MB ( 23.6%)


    4. 个人认为,不同场景的选择。

    - 如果本地收藏,追求极致压缩,每次查看,接受解压全本,应该选 UTF-16 + lzma ,压缩率 18%

    - 如果本地收藏,但要求快速任意跳转章节,选 UTF-8 + zstd + 大词典,压缩率 23%

    - 如果对外提供服务,选 UTF-8 + zstd + 小词典,压缩率 27%


    第三点考虑如下:

    - 若服务器本地解压,再传给用户,每次选取章节后,再取对应词典压力较小,缓存词典所需内存也少

    - 若要求客户端先拿词典,再本地解压呈现章节。面对只看几章就弃书的用户,沉没成本较低( 20 ~ 40 KB )
    815979670
        23
    815979670  
       2024-10-02 17:06:13 +08:00
    @wxf666 问一下 压缩后的数据存 text 类型还是 blob 类型?
    wxf666
        24
    wxf666  
       2024-10-02 20:00:59 +08:00
    @815979670 #23

    BLOB ,存的是 zstd 压缩后的二进制数据。


    噢,如果要全文搜索,存压缩后数据也没关系的。SQLite 的 FTS 支持无内容表,只要你添加/删除时,提供了压缩前的章节内容,就行。

    但搜索结果只有 `章节 ID`,还需要回 `章节表` 取数据解压。但搜索服务,一般都会分页呈现结果,所以不会一下子解压几万个章节出来。。

    一下子解压几万个章节。。可能也没事?过亿数据,都能四五万随机读并发,命令行里 zstd 用词典,单线程解压那 14000 章节文件,也才 0.9 秒。。还是六七年前的轻薄本了。。
    infinet
        25
    infinet  
       2024-10-02 22:40:14 +08:00
    @wxf666 14000 章! 键盘都磨平了吧
    815979670
        26
    815979670  
       2024-10-03 02:57:06 +08:00 via Android
    @wxf666 谢谢 回复非常有参考价值,我计划用 sqlite 存日志,配合压缩使用 目前未压缩数据一个月有 400G 左右,压缩后体积应该能小压缩到 35% ~30% 左右

    第一次了解到外置压缩字典的用法,对于高度重复,量又大的日志文件应该很有用(任务单次日志输出 3MB ),之前我还在担心每行独立压缩,压缩率可能不高的问题
    cyoking
        27
    cyoking  
       2024-10-03 10:27:13 +08:00
    @rui6ye 你这个不会被被人追究版权吗
    wxf666
        28
    wxf666  
       2024-10-03 14:17:31 +08:00
    @infinet #25

    要是不换键盘,估计都能磨成粉了吧。。

    其实网上冲着《字数较多网文》随便搜的,

    看了下,这小说连载十来年了,应该换好几套键盘了吧。。



    @815979670 #26

    我还没试过日志存数据库诶。。

    日志可以调整成,边压缩,边流式存到硬盘上吗?

    要搜索的话,zstdgrep 就能搜了。。


    如果你确实想试试数据库存日志,也推荐你 DuckDB 对比下,

    这货是列式数据库,默认就带压缩。同一列相同类型,压缩效果应该也更好些。。

    而且功能、计算速度也比 SQLite 丰富/快很多。

    就是不知道读写速度,比得上 SQLite 不。。
    815979670
        29
    815979670  
       2024-10-04 00:11:21 +08:00
    DuckDB 挺早就注意到了,出于两个考虑没有考虑使用:
    1. 项目的开发使用的是 Go 语言,主流的 Go-duckdb 库 ( https://github.com/marcboeker/go-duckdb) 依赖 CGO (无法跨平台编译 这个对我很重要),有一个不依赖 CGO 的 ( https://github.com/scottlepp/go-duck) 但目前只有 8 个 Star 不太敢用在项目中。

    2. SQLite 发展时间很长,经过了时间的检验,并且官方也提到了对损坏的数据库文件也尽可能的提供了读取的支持,无论从性能、兼容性 、生态 等多方面考虑,它仍然很能打 并且在我这个场景中够用。而 DuckDB 我自己做一些新技术探索时也尝试过 性能确实可以( 2000w 行 csv ,就纯 csv 没索引那种,汇总数据特别快 只用了 0.2 毫秒),但毕竟是一个新东西,可能 一两年后的项目中会考虑使用吧(让子弹飞一会)。

    日志存储倒不是流式存储,项目中会有一个专门写日志的组件,不管哪里的日志都丢给 这个组件,先缓存起来,再按照一定的规则批量写入 SQLite 落盘(我之前测试过 SQLite 批量写入性能 https://www.dbkuaizi.com/archives/154.html 15w 数据耗时 5.13 s ),所以写入不存在问题。
    815979670
        30
    815979670  
       2024-10-04 00:12:20 +08:00
    @wxf666 忘了 @了 看 29 楼
    815979670
        31
    815979670  
       2024-10-04 00:14:04 +08:00
    29 楼更正一个错误 DuckDB 汇总数据是 200ms 0.2 秒
    mayli
        32
    mayli  
       2024-10-04 06:07:10 +08:00
    @wuhao1 oss 压缩存放,外加服务器本地缓存下。
    mayli
        33
    mayli  
       2024-10-04 06:15:21 +08:00
    上万的小说 -> 也就 10K
    平均每本 10MB
    oss = 100 GB
    完全没有压力.
    tushan
        34
    tushan  
       2024-10-04 15:43:54 +08:00
    建议使用 oss 储存,对于冷门小说还可以走存档的套餐,成本更低,
    wxf666
        35
    wxf666  
       2024-10-05 23:20:39 +08:00
    @mayli #33
    @tushan #34

    是整本存 OSS 吗?在线阅读,也要下整本吗。。

    对于只看几章,就弃书的用户来说,投入是不是有点高了。。



    @815979670 #29

    算了,DuckDB 标题也写了,人家自认是 OLAP 类型数据库,应该不适合高并发读写。。

    但用来分析你那 400GB 历史日志,应该非常合适。。
    mayli
        36
    mayli  
       2024-10-06 01:12:38 +08:00
    @wxf666 你要是有快速跳转需求,可以按照章节切分缓存。
    如果懒得切,也可以用 nginx byte-Range Caching
    这种缓存分片。

    https://blog.nginx.org/blog/smart-efficient-byte-range-caching-nginx
    815979670
        37
    815979670  
       2024-10-06 15:32:56 +08:00
    @wxf666 其实也没有分析一说,就是一些普通的运行日志,只有出现故障后根据时间戳检索,在展示的时候解压显示就行
    wxf666
        38
    wxf666  
       2024-10-06 16:54:11 +08:00
    @815979670 #37

    总感觉,要依赖外部程序解压缩,才能查看原文,有点麻烦。。

    正常原文存储,每天凌晨归档至 DuckDB ,可行吗?

    如果怕 DuckDB 还不够稳定,可能丢数据,那就再 lzma 压缩一份,文件系统上归档?



    @mayli #36

    切分后,怎么存放、提供访问呢?

    1. 直接按范围下载原文,并 gzip 传输,是不可行的。因为如 22 楼所说,独立每章 gzip --best 压缩,整书只能压到 40%。( zstd 配合小字典压缩,都能有 25%)

    2. 按章切分 + 字典压缩 + 存 OSS 提供访问的话,好像有个请求费比较贵。。服务器的话,存储和流量又比较贵。。
    mayli
        39
    mayli  
       2024-10-06 17:58:42 +08:00   ❤️ 1
    @wxf666 其实 40% 和 25% 差距并不大,如果你是 OSS 的话,这部分没多少钱。
    你这些数据不算多,即是说 1w 本小说
    每本 10MB, 10MB * 10K = 100G
    每本 100MB, 100MB * 10K = 1000G (我不信有压缩后 100M 的小说…)

    假设极限情况 1T 成本用
    https://www.hetzner.com/storage/storage-box/ -> € 3.20 max/mo.
    https://wasabi.com/pricing -> $6.99 TB/month
    https://r2-calculator.cloudflare.com/ -> $38.25 / mo

    有这个时间去抠 15%的压缩率,时间成本都已经能一年服务器费用了。

    对于一般的电子书站,分章节是合理的,毕竟大部分网页阅读都是分章节的,s3 这种对于单文件多文件也没有太大价钱区别。
    wxf666
        40
    wxf666  
       2024-10-06 19:05:36 +08:00   ❤️ 2
    @mayli #39

    简单算了下,大部分时候,还是 OSS + zstd 划算?再加上 CDN ,能进一步减少流量部分的花费?

    除非只存了 100 ~ 200 GB ,且每月点击数过亿,此时用服务器较为划算?



    1. 我查了下啊哩云的价格(不太熟悉,有错的还请指出):

    OSS:
    - 存储:0.12 元 / GB / 月
    - 流量:0.50 元 / GB
    - 请求:0.01 元 / 万次(每月 <= 2000W 次时免费)

    服务器:
    - 存储:0.50 元 / GB / 月
    - 流量:0.80 元 / GB


    2. 如 22 楼所说,14000 章小说,词典 + 分章节压缩 36.6 MB ,平均每章 2.68 KB 。加上网络传输 TCP/IP 头部、握手、响应头部等杂七杂八开销,算 3KB 好了。

    如果是 gzip 压缩传输,平均每章 4.02 KB ,加上乱七八糟两三百字节,算 4.3 KB 好了。


    3. 则每月费用为( P 为每章平均网络包大小,C 为每月点击次数(万次),S 为每月存储大小( GB )):

    - 服务器:( P x C / 2^20 ) x 0.8 + 0.5 x S

    - OSS:( P x C / 2^20 ) x 0.5 + 0.12 x S + max(C - 2000, 0) x 0.01


    4. 画图后,是这样:


    - X 轴:C 值( 0 - 6.7 亿次)
    - Y 轴:S 值( 0 - 1000 GB )
    - Z 轴:每月费用( 0 - 3000 元)
    - 红色:服务器 + gzip
    - 黄色:OSS + gzip
    - 蓝色:OSS + zstd
    - 绿色:服务器 + zstd
    815979670
        41
    815979670  
       2024-10-06 20:05:42 +08:00
    @wxf666 没必要 存储的日志从设计上考虑,只允许通过这个程序读取,所以只要能实现 压缩存储、按时间检索展示就行
    niubee1
        42
    niubee1  
       2024-10-06 20:49:37 +08:00
    @wxf666 上千万部小说,按照常年下 txt 小说的经验来说,完本的 txt 文件均值在 5M 左右,按照 1500 万本计算,纯文本的体积就有 73 TB ,如果按照 50%的完本率乘个系数来算的话,预估至少 50TB 。但是实际上活跃的小说只有其中一部分,可以将大多数的内容放到 OSS 的低频存储里去,用一个电梯算法来做冷热数据的替换。这样成本会低一些
    wxf666
        43
    wxf666  
       2024-10-06 21:03:36 +08:00
    @niubee1 #42 如果是整本存储,那肯定是 UTF-16 + lzma 压缩最舒服了,从 22 楼看,能压到 18%(即 9 ~ 13 TB )

    但这不适合在线阅读,因为没法任意章节跳转。。而且看几章就弃书,也要下全本的话,成本太高了。。

    对于在线阅读,你们会怎么提供服务呢?
    niubee1
        44
    niubee1  
       2024-10-06 21:50:18 +08:00
    @wxf666 一般来说还是分章节用小文件存储,oss 什么的,压缩什么的无所谓的,因为事实上大部分小说阅读网站也不提供小说内部全文检索,搜索主要针对的元数据,那就是数据库的故事了。分章节存还有一个好处是可方便冷热分区存,以便节省费用,根据自己的经验,很大部分小说的后 1/3 章节甚至 1/2 的章节,大多数人都会弃书,所以绝大部分内容都可以放到低频存储里去,只要电梯算法设计合理,可以节省很多成本
    wxf666
        45
    wxf666  
       2024-10-06 22:59:25 +08:00
    @niubee1 #44

    这个小文件,是请求服务器获得吗?还是走 OSS + CDN 呢?还是。。?

    啊?压缩的话,能节省 75% 的存储需求呀?放 OSS 里,就是每年节省 37.5 TB ,算下来就是 5.5W 元了呀。。

    额。。这咋和全文搜索,联系上了。。

    是诶,还能通过区分冷热数据,进一步省钱。。但冷数据好像不足 64KB ,也按 64KB 算,应该要多个章节合起来存了。。
    dzdh
        46
    dzdh  
       2024-10-06 23:40:46 +08:00
    直接无脑 cloudflare r2
    niubee1
        47
    niubee1  
       2024-10-07 10:07:30 +08:00
    @dzdh 楼主没说是不是收费,要不要加密,不加密可以,加密的话 cloudflare r2 就不适合了
    winglight2016
        48
    winglight2016  
       2024-10-07 12:03:01 +08:00
    lz 这需求都说不清楚怎么还负责存储方案了?存储方案首先看的是读写需求,只要满足这两块,剩下的考虑才是成本,用最便宜的存储就可以。

    小说网站一般都是按章节浏览,所有按全本文件存储的方式都不合适,除非是专门做全本下载的。

    最后,成千上万本小说,这个数据量太小了,根本不值得讨论性能、速度这些问题。
    wuhao1
        49
    wuhao1  
    OP
       2024-10-07 13:39:23 +08:00
    @niubee1 收费,免费都有, 所以就按收费来 , 免费的收费为 0 ,加密这个之前搞过不过算法也在 js 里 可以破解, 后面索性不加密了,哈哈
    @winglight2016 是的 按章节 收费,也有按本收费 的,看大神回复的 很多都是 按整本 (适合免费小说的 方案 ,付费的确实 不适合。
    oss 看起来确实不失为一个好的方案, 但应用下来, 在应对 密集操作 就是灾难, 网络 io 太大,请求一整本书的时候会很慢, 不得已需要将书存到缓存来缓解这种缺点
    niubee1
        50
    niubee1  
       2024-10-07 14:22:30 +08:00
    @wuhao1 一直很好奇你一直在说 IO 密集操作,但是就我所知,小说这类文件存到 OSS 上后就只需要读就行了,还有啥密集的 IO 操作?
    wxf666
        51
    wxf666  
       2024-10-07 21:23:09 +08:00
    @winglight2016 #48

    楼主有说,存章节内容。如果每本书 5000 章,那就是考虑怎么存 5000W 小文件了。。



    @wuhao1 #49

    我回复了很多,全是按章节来考虑的,甚至连成本都算了,并画动态图进行比较。

    我也很好奇,你说的《网络 IO 太大》是啥意思呢?

    是说,缓存整本书,需要发起几千个网络请求吗?

    你每次并发 100 下载,一分钟内都能下完了吧。。

    或者,你按 10 章 / 文件来保存,只需要几百个请求就行了呀?



    @niubee1 #50

    同好奇他说的《 IO 密集》是啥意思。。几千小文件,下到内存里,解压合并不就好了吗。。
    dzdh
        52
    dzdh  
       2024-10-08 08:21:29 +08:00
    @niubee1 #47 rclone 挂载到本地 自己加密 关键是大量 IO 操作请求次数都收费的
    abersheeran
        53
    abersheeran  
       2024-10-08 09:30:08 +08:00
    @815979670 #17 一本小说一个 sqlite ,方便缓存热点小说,全部小说的基本信息有一个独立的数据库。
    815979670
        54
    815979670  
       2024-10-08 09:49:47 +08:00
    @abersheeran 那确实挺合适,小说更新和不会再修改 并发读取又是 sqlite 的强项
    abersheeran
        55
    abersheeran  
       2024-10-08 09:55:46 +08:00
    如果你是打算自己做个笔趣阁之类的盗版小说网站,我倒是有一个不道德的点子。你把网络小说拆章节存到 telegraph 上。
    wuhao1
        56
    wuhao1  
    OP
       2024-10-08 10:31:05 +08:00
    @wxf666
    @niubee1
    是这样的 , 比如 为了某种需求 , 需要对整本书 做一些操作, 比如 拆章 , 将之前 3000 字一章的 拆成 1500 字(甚至更少)左右 1 章 , 那么就需要先将整本书读完, 然后在做操作, 如果是存 oss 那么读整本书的等待时间, 就很煎熬了。
    biubiuF
        57
    biubiuF  
       2024-10-08 10:49:57 +08:00
    先预处理文本,然后按热度做阶梯式存储
    wuhao1
        58
    wuhao1  
    OP
       2024-10-08 12:03:49 +08:00
    @biubiuF 目前是 第一次读整本书的时候存 redis 缓存, 后面的访问都是访问 redis ,但是 第一次也还是很慢
    mayli
        59
    mayli  
       2024-10-08 12:17:53 +08:00
    @abersheeran 有没有基于 telegraph 的 key-value 存储, 就不能指定 key ,但是至少可以存个 key-index
    davehandong
        60
    davehandong  
       2024-10-08 12:56:57 +08:00
    我觉得还是得看这些文件存储以后具体会有什么样的操作吧,根据实际的情况去选择。
    如果是一个“小说”的“系统”,我觉得不会是某一种存储方案。
    文件的基本信息需要放到关系型数据库里,文件本身其实我是倾向于放到对象存储里面,根据文件总量、单个文件大小、并发量还有能够接受的延迟,去选择具体的对象存储。
    单纯从使用上说我从 S3, MinIO, Ceph 这三个里面去选,因为 api 基本兼容,后面不管换啥,代码都不需要修改。
    ala2008
        61
    ala2008  
       2024-10-08 16:00:27 +08:00
    不应该存目录,然后去检索吗
    niubee1
        62
    niubee1  
       2024-10-09 09:39:54 +08:00
    @wuhao1 如果是你说的这样子的需求的话,如果要简化你的程序开发的话,上 TiDB 这类分布式数据库来存,会简单很多,而且你的内容有付费内容,这样的内容在 OSS 上加密的话效率太低,存数据库的话,就不用在数据库加密,有人访问的时候临时加密输出就行了。或者自己搞实体机组分布式文件系统譬如 ZFS ,或者上 Ceph 。但是运维成本就很高。
    ShuA1
        63
    ShuA1  
       2024-10-09 10:05:40 +08:00
    上数据库利于后期的 SEO 优化, 及后期的迭代更新。 文件会麻烦很多。
    直接 pgsql 吧,all In one
    niubee1
        64
    niubee1  
       2024-10-09 10:05:41 +08:00
    @wuhao1 感觉你的需求描述来说不像是 X 趣阁 这类盗版站,那就很有意思了,国内还有新站?啥项目?好好奇
    wxf666
        65
    wxf666  
       2024-10-09 10:33:52 +08:00
    @abersheeran #53

    为啥不全部小说,放一个 SQLite 里呢?热点小说 / 章节,也会被系统缓存那几个页面的呀?

    比如说,你就算在机械硬盘上放数据库,反复 SELECT * FROM data WHERE id = 1 ,也能几万 QPS 呀?(机械硬盘 4K 随机读写,才几百噢)
    wxf666
        66
    wxf666  
       2024-10-09 10:38:53 +08:00
    @wuhao1 #56

    边看边拆可以吗?为啥要一下子拆完呢。。是为了能快速跳转,拆后的章节?

    那服务器预先计算每章字数、每行字数?客户端就可以迅速决定,拆分后新章节包含哪些行,分布在哪些章节文件了呀。。


    @wuhao1 #58

    为啥不整书压缩( 100 MB -> 18 MB ),放 OSS 呢?是怕 OSS 被刷流量吗?

    如果是付费书,可以压缩时加密码呀。。要解压,需从服务器拿密码啥的。。

    但话说,不是付费用户,你不给 URL ,应该也行了吧。。
    wxf666
        67
    wxf666  
       2024-10-09 10:46:41 +08:00
    @niubee1 #62

    1. 访问服务器时,为啥还要加密输出呢?是怕用户简单抓包,就分析出响应结构吗?还是。。?

    2. OSS 上存加密压缩包,付费用户访问接口拿密码,可行吗?

    3. 为嘛不选 SQLite 呢?隔壁帖子测试,单表 1.3 亿 100 GB 数据,还能有 4.7W QPS 呀?(六七年前轻薄本 + 低端 SATA 固态)



    @ShuA1 #63

    为嘛不选 SQLite 呢?隔壁帖子测试,单表 1.3 亿 100 GB 数据,还能有 4.7W QPS 呀?(六七年前轻薄本 + 低端 SATA 固态)
    mayli
        68
    mayli  
       2024-10-09 12:04:44 +08:00
    @wxf666 因为没必要,你这个简化的模型就是一个 key:(小说,章节) -> value:内容
    的存储,没有关系,没有 join ,不需要 acid 。
    直接 oss/s3/文件完事,你可以测试下 oss/文件系统,完全满足。
    sqlite 100GB 数据库维护起来挺费劲的。
    wuhao1
        69
    wuhao1  
    OP
       2024-10-09 14:36:30 +08:00
    @wxf666 目前的方案就是 采用 oss 存储章节内容, 遇到密集操作整本书的时候巨慢,单章的读写没什么问题,目的就是要生成一本新的书,所以边看边拆不现实,再说边看边拆,不好控制需要不断记录拆的位置然后要截断的位置,不如全本全局的拆。我们目前并没有压缩内容,读取内容更方便。


    @niubee1 就是普通的 付费小说 平台,类似与阅文,点众这样的

    其实可以搞成 oss 和磁盘共存 (某一项用做备份,需要密集操作 调磁盘,效率高,一般的章节读写 oss 磁盘都可以。
    ShuA1
        70
    ShuA1  
       2024-10-09 14:58:46 +08:00
    @wxf666 SQLite 只有单并发, 而且后期扩展也麻烦。pg 可以 all in one , 一个数据库解决应用和小说存储的问题。
    815979670
        71
    815979670  
       2024-10-09 16:09:25 +08:00
    @ShuA1 SQLite 可以并发查询 而且性能很高,只是不能并发写,对于小说这种 只在后台更新,前端用户并发阅读的 特别合适,甚至很多项目都用 SQLite 做缓存
    niubee1
        72
    niubee1  
       2024-10-09 16:29:28 +08:00
    @wuhao1 你算一下你们内容的的总量是多少, 如果是 TB 级别的内容的话,SQLite 单机肯定撑不住,那就要群集方案,那都要分布式群集了,那还不如用现成的成熟方案,不然你还打算自己 DIY 一个 SQLite 作为 backend 的群集出来?没有必要吧。
    加密的话,因为我经常爬小说,所以,习惯使然

    另,付费小说平台在国内还有得赚么?还是是在国外搞?
    ShuA1
        73
    ShuA1  
       2024-10-09 16:39:16 +08:00
    @815979670 小说也并不是单并发写入,需要考虑:
    1. 多蜘蛛写入
    2. 单蜘蛛的情况, 后台其他操作写入/注册会员写入
    815979670
        74
    815979670  
       2024-10-09 17:11:50 +08:00
    1. 多个蜘蛛写入 SQLite 如果小说是以 每本小说都是一个 SQLite 的维度存储时,这不是问题。
    如果存储多本小说 或者 同一个 SQLite 文件有多个线程写入,可以通过 批量写入的方式实现, 我前年测试 SQLite 写入性能 15w 数据耗时 5.13 s ,完全可以满足需求

    2. SQLite 只是小说内容部分的存储方案,项目中 会员信息或者其他操作 还是 mysql/pgsql
    wxf666
        75
    wxf666  
       2024-10-09 17:40:38 +08:00
    @mayli #68 我在 40 楼也认为,放 OSS 更合适。

    但确实又有其他人说,要上 TiDB 、PostgreSQL 、甚至存硬盘 等,

    所以就想问问,SQLite 会碰到啥困难,满足不了啥需求。。

    毕竟这货资源占用真的小,性能也真的很强,挺诱人的。。

    (除了多线程并行写事务。但并发写还不错,一亿数据还能上万并发写)


    > 《 sqlite 100GB 数据库维护起来挺费劲的》

    具体是什么场景费劲呢?备份迁移吗?还是。。?
    zwenooo
        76
    zwenooo  
       2024-10-09 18:16:25 +08:00
    @wuhao1 冷热存储呗,长期没用的就放 oss ,热门小说就放磁盘,放缓存 设置一个 ttl 。
    wxf666
        77
    wxf666  
       2024-10-09 18:43:13 +08:00
    @ShuA1 #70

    你们爬小说,每秒会爬多少章节,写入多少行数据库呢?

    PostgreSQL 一亿数据时,能支持多少并发写呢?资源占用如何?

    隔壁贴测试 SQLite ,1.3 亿 100 GB 数据时,仍能 1W 随机写事务 / 秒,占用 16 MB 内存。

    但并行写确实是 1 。可我觉得,还是有办法扬长避短:

    1. 专门一个线程,处理写事务,每秒能写上万行。其他爬虫线程,爬好数据后,传给该线程的队列。
    2. 每个爬虫线程,每爬 1000 章 / 一本书,申请互斥锁,平均花 0.1 秒写入数据后,继续爬。
    3. SQLite 官方有个开发了 9 年的 begin-concurrent 分支[^1],允许多个写事务同时操作不同 4K 页。(类似 Redis 多事务操作不同键)

    官方宣称[^2],AMD 5950X + WAL2 日志 + 同步关闭 + 100W 行 256 MB 数据时,有:

    - 三线程,7.2W TPS (每事务一写)
    - 八线程,5.4W TPS (每事务一写十读)

    但一直没合并到主分支。如果愿意吃螃蟹,可以试试。

    [^1]: [SQLite: Begin Concurrent]( https://sqlite.org/cgi/src/doc/begin-concurrent/doc/begin_concurrent.md)
    [^2]: [hctree: Thread Test (sqlite.org)]( https://sqlite.org/hctree/doc/hctree/doc/hctree/threadtest.wiki)
    wxf666
        78
    wxf666  
       2024-10-09 20:54:11 +08:00
    @wuhao1 #69

    《遇到密集操作整本书的时候巨慢》是网络请求几千个章节慢吗?

    @ShuA1 估计会每秒爬几千章,要不你问问他咋做的?


    我[以前]( /t/884743#reply12 )用 Python 爬笔趣阁,凌晨 3 ~ 5 点时,每秒能爬 700 章左右。。

    包括:单线程协程爬取 + 解析抽取 + 转成 UTF-16 + 全本数据合并 + 多线程 lzma 压缩 + 写入到 TF 卡(在骁龙 636 的手机上 + WIFI 测试的)
    wxf666
        79
    wxf666  
       2024-10-09 21:17:01 +08:00
    @niubee1 #72

    请教一下,《 TB 级别的内容的话,SQLite 单机肯定撑不住》是啥意思呢?

    1TB 时,QPS 会掉到几百几十的意思吗?

    1.3 亿 100 GB 时,没感到有啥性能瓶颈呀。。

    (六七年前轻薄本 + 低端 SATA 固态,还能 4.7W 的 QPS )

    ---

    可惜我手头只有 256 GB 的固态,测试不了。。但我感觉应该没问题?

    数据库调整成 8KB / 页,扇出是 612 ( 4K 时 306 ),叶子节点上能存 3 章小说(每章 2.66 KB ,字典压缩后),

    那 4 层 B+ 树能存 612 ^ 3 x 3 = 6.88 亿章,总共 1.70 TB 。。

    缓存前三层枝干节点,系统需要 (612^0 + 612^1 + 612^2) x 8 / 2^20 = 2.86 GB 内存,

    往后每随机读取一章,就和 1.3 亿 100 GB 类似了。也可参考固态 8K 随机读取测试。。
    wxf666
        80
    wxf666  
       2024-10-09 21:19:34 +08:00
    @wzwmeme #76

    服务器硬盘和流量,都比 OSS 贵得多诶。。

    应该长期没用,放低频 OSS 。热门放 OSS + CDN 。。
    Bridan
        81
    Bridan  
       363 天前
    @815979670 sqlite 的驱动也是 cgo 啊
    wuhao1
        82
    wuhao1  
    OP
       363 天前
    @wxf666 硬盘的话 , 基本只有存储,一般和应用在同一台 ecs 直接读取,没有流量,即使需要共享给其他服务器 可以走内网
    zzmark06
        83
    zzmark06  
       358 天前
    oss ,唯一选择。
    云上的存储单价,你拉出来列个表。
    例如你说的,存到磁盘,吞吐量有多少?吞吐量能到多少?
    oss 密集操作网络 IO 开销大,但你考虑过磁盘能吃多少 IOPS 吗,云上的话这个比 OSS 成本要高。
    对于这类业务,OSS + CDN 是最优选择,服务器只管授信,流量走 CDN 自然分层,存储有对象存储便宜大碗。

    若存储量到 pb 级,可以私有云自建,进一步降低成本。
    自建 CDN 源站,存储自建分布式存储,比如 seaweedfs ,小说分块 + 压缩后,都是小文件,不适合 hdfs
    zzmark06
        84
    zzmark06  
       358 天前
    @wxf666 sqlite 这属于单节点玩具 db ,对于并发性 web 服务,是跟不上用的。
    并发访问,就成了两种情况,1. 串行排队,2. 程序内实现类似于 db 的 buffer cache

    至于 duckdb ,这东西底层是列结构存储,读取需要解压,不适合并发访问,也不适合频繁写入。
    duckdb ,和 sqlite 一样也是进程级,对于并发性 web 服务,也是一样的毛病。

    #39 做的成本估算,有些细节可以调整。
    OSS 和服务器的流量成本均应采纳 CDN 价格,不过按经验上看,CDN 回源也要再算,比较麻烦,流量成本占比低时没啥必要。

    最优方案还是 OSS + CDN 存放 zstd 压缩后的文件。zstd 压缩使用小样本预训练词典,词典随客户端下发。
    至于传输,zstd 压缩后,不要再计算 gzip 之类的量。

    还有,算流量别算那么精确,oss 对于小文件有对齐,2kb 塞进去也会按 4k 计算(标准存储),而且访问 OSS 是 http 协议,头部塞了一大堆东西,几 kb 的文件算不准的。

    至于整本存储,lzma 依然不是优化方案,还是首选 zstd ,新代的压缩算法几乎是全方面碾压老代。
    这东西参数很多,把 level 开高压缩比不错,解压速度也可以。


    当然,若是私有云自建,这方面有个优秀的方案,HBase + HDFS 。


    #77 提到,sqlite 100g 1.3 亿数据,1w 随机写事务,这种测试没用,这数值是 WAL 的数值,而且是无事务写。

    顺便再补个,我们做大规模爬虫类任务,是 crawl 爬后存文件丢进 DFS ,再有独立中间件提取再入库。至于入什么库就看情况了,多数是 kafka 。
    再有服务消费 kafka 进行分拣、清洗、预先处理,按业务分类入业务库。
    所以,什么并发写之类的都不存在。


    #77 还有一个,支持多少并发写,占用资源问题。
    对于 db ,mysql 也好 pg 也好,并发写并不是大批量导入的最优解,大规模数据导入是靠 batch ,而不是并行。
    以我们的经验,mysql 导入 100w 行,字段 50 ,行均大小 5k 左右,单并发写速到 1w/s 不难。


    至于题主,大概率是个新入行没做过项目的年轻人,脑子里想的都是不切实际的笑话,甚至还想搞 redis 缓存,也不知道缓给谁看的
    815979670
        85
    815979670  
       234 天前
    @Bridan Go SQLite 库有好几个,有 CGO 的 也有无 CGO 的,前者性能更好,后者交叉编译更友好。
    依赖 CGO: https://github.com/mattn/go-sqlite3
    不依赖 CGO: https://gitlab.com/cznic/sqlite
    不依赖 CGO 使用 Gorm: https://github.com/glebarez/sqlite

    无 CGO 的性能会差一点,但也不会太差,个人感觉是可接受的,毕竟 SQLite 没人 会用在压力特别高的场景中
    Bridan
        86
    Bridan  
       234 天前
    @815979670 我看过不依赖 cgo 的,他们是用 go 把 sqlite 重新实现了一遍。
    Bridan
        87
    Bridan  
       234 天前
    @815979670 go-duck 不依赖 cgo ,但是它依赖 duckdb 的 cli ,cli 在效率和开销上是不如驱动的
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   Solana   ·   4458 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 35ms · UTC 10:05 · PVG 18:05 · LAX 03:05 · JFK 06:05
    ♥ Do have faith in what you're doing.