比如 知乎文章,简书,豆瓣,掘金,等有大篇幅文章的网站,文章的内容,可能几千字,甚至好几万字,如何存储呢

1.用mysql 的 TEXT类型,mysql 的 Text最大可以4GB怎么都够了,但是那么大放在一行中不知是不是影响读写速度

2.直接用 mogodb 存,Bson里就放1个key,value却几百k或上兆,总觉得也不好

3.持久性KV资料库,如果是既支持单机又方便扩展,各位可以推荐一下哪个比较好用的吗?

4.OSS对象存储,OSS是不是就必须存成文件了?IO是不是对比KV会很慢,如果频繁读又频繁写,更不适合了吧

热点的话还是要存资料库吧,不热的可以落盘成文件?如果总结场景的话

A: 频繁读 不频繁写:新闻,咨讯,知识付费文章,公众号文章,论坛帖子

B: 频繁读 也频繁写:笔记,协作文档

大厂都是如何做的,对比一下不同方案


基于kv存储吧


以下所有条目都来源于互联网文章的二次加工,如有雷同,概不承认

没做过相关工作,纯理论分析一波,欢迎讨论:

条目一:如果是创业初期,直接用最熟悉的资料库就好

比如MySQL。

这样的做是有好处的,就是糙快猛。创业初期,最重要的是把项目做出来并上线。业务能不能活下来还不一定呢,想太多高性能、高可靠、易运维的事都没有太大的意义。

简单可靠才是最需要关注的。

条目二:不建议使用MySQL的TEXT类型

像blob和text这样的栏位,名义上是为存储很大的数据而设计的类型。但这正因为如此,这跟关系资料库使用table的设计理念是冲突的。table中的每一列数据都是定长的,比如varchar(32)。但blob和text的上限太长了,MySQL不可能将它们存储在table中,因而会使用专门的外部存储区域进行存储,数据行内存储指针。这样做的其中一个结果是会导到多一次磁碟IO,性能开销比较严重。

条目三:新闻类文本直接静态化扔Nginx或OSS就好

频繁读不频繁写的新闻资讯类文本,在保存的时候,直接写成静态的html,访问的时候直接从nginx返回。这样做,不仅可以节省伺服器资源,还可以利用CDN加速,把文件放到离用户最近的CDN伺服器上,既便宜又快。

OSS是另一个可选的方案。OSS的优势是对图片和视频存储做了大师针对性优化,比如缩放图片和视频转码。另外,几乎所有的OSS云服务都自带CDN加速服务。

熟悉程度和价格可能仍然是很重要的选择因素。

条目四:笔记类产品MongoDB可能是个不错的选择

简述MongoDB的特点如下:

  1. 偶尔丢数据:在开发者水平相当的情况下,MongoDB更容易鼓励开发者做出不恰当的设计从而导致数据丢失。如果你的数据特别重要(金融、交易),那么关系型资料库可能是个更好的选择。对笔记类产品吧,可能没那么疼,忍一忍就过去了。
  2. 无schema:不需要预定义的schema,以文档(json, bson)形式保存数据,同一个集合(对应关系资料库的表)中的不同文档可以使用不同的结构,并支持随时向扩展任意栏位。这个特点导致MongoDB特别适合存储商品参数这类名目繁多又不尽相同的参数。在在游戏、电商、社交、直播、物流等领域都能看到MongoDB的身影。

    当然,随之而来的问题就是如果代码结构不够清晰,很可能导致没有任何人知道资料库中存储的数据是什么格式。对接手他人代码的人员,如果不能确定文档中有哪些栏位 ,则可能导致相当危险的结果。如果你的数据模式比较固定的话,一个变通的方案是通过protobuf这种序列化协议引入外部模式。

    这对笔记类产品谈不上好或者坏,毕竟笔记的主要内容是大段不需要解析的文本。
  3. 单文档查询速度快:MongoDB使用BTree结构(对比MySQL使用B+Tree),针对单文档的查询做了大量节约IO的优化,因此查询速度很快,当然吃内存也是毫不含糊。 修订:MongoDB使用的也是B+Tree,原来的理解有误。
  4. 多表联查功能弱:笔记产品不太需要。
  5. 事务功能弱:4.0以上的版本已经支持基于Replica Set的事务,但在此之前只支持单文档的原子操作。对笔记来产品来说,弱化事务的使用可以提高数据写入效率。
  6. 提供全文索引,这个对笔记类搜索有用(但中文支持弱不少 = = )。
  7. 原生支持sharding(分片),升级资料库容量时分片间的数据可以自动迁移,这对海量数据的扩容简直不要太nice。

条目五:其它资料库产品

  1. MySQL,关系资料库,强在事务和关联查询
  2. Redis/Memcache,内存资料库,主要用作缓存,不适用于长文本处理
  3. ElasticSearch,全文搜索,虽然楼主没提,但在笔记类产品的确有这种需求。但仔细想一下,个人笔记量是否真的需要上ES才能满足需要呢?


这个问题,我经历过,我面对的情况比你所说的还要复杂些,现在看来解决得还算不错,有大量客户使用,验证是可行的。总体思路是,要兼顾使用频度与性能代价,对于长内容,无论是长文本,还是图片、文件等,要从设计上考虑用户使用情况与后台运行负载,再决定如何存储。

具体来说,对于需要高频度读取并展现的,放入资料库;否则,不存入资料库,而是放入磁碟,资料库里只存放其文件路径,需要展现时依据路径读取并展现,即可。但有个例外,对于内容可能很大,会对资料库造成重大性能瓶颈的栏位,坚决放入磁碟,不要提供高频度读取展现的支持,不能因为这一件小事而影响全局。

结合实际来说吧,会更清楚些。当时是在开发华创信息管理平台,一款信息管理的平台软体,允许用户可按需建表、设栏位,以便让普通用户快速搭建各种管理系统。栏位的数据类型支持长文本、附件等长栏位,长文本的最大长度32K中文字,附件可以是图片、word、excel、.zip等各种文件。

这种平台软体,既然允许用户自由设置,那么问题就来了,因为一个表可能会设置多个长栏位,所以我前面说,比你说的情况还要复杂些。比如,利用平台搭建一个售后服务管理系统,他可能设置一个客户报修表,并设置以下栏位:故障现象描述、故障现场照片、解决措施描述、维修后照片...等等,其中,描述栏位可能较长,数据类型一般用长文本,照片是文件,数据类型只能用附件。

该怎么决策呢。对于长文本,我们允许在用户界面上直接显示,一页数据就包含100行,假如每行包含2个长文本,一页就要读取200个长文本,因此,其读取展现频度是较高的,只能放入资料库。而对于图片等附件型栏位,由于附件可能较大,假如每个限制5M,算正常吧,但你架不住记录数可能巨多啊,直接放入资料库会让资料库的大小急剧膨胀,后果不堪设想。因此,附件型栏位的文件型数据必须放入磁碟,在用户界面上不支持批量展现,而是点击它才显示。这样,就从设计上兼顾了用户使用方便性与后台运行负载,效果不错。


看html的具体内容和篇幅。

是我的话,不考虑mogo


这个需要看你自己的能力,技术投入,后续扩展,性能要求等因素考虑。

如果从易用性上,mysql简单易用,门槛低,后续维护方便,但是他对于text,blob等格式在性能上效果不佳,主要还是因为它并不擅长文档等海量存储场景。

如果追求性能,可以考虑使用redis,基于内存性能高但是功能比mysql欠缺写。

基于文档存储,也可以选择mongodb,先天支持海量存储。


推荐阅读:
相关文章