架构视角-文件的通用存储原理

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 Tair(兼容Redis),内存型 2GB
简介: 架构师是互联网行业高薪又紧俏的资源。成为架构师最基本的是设计能力。设计与设计的区别主要体现在两方面:1,深度:要解决哪些问题?这个问题背后的根本问题是什么?还有什么问题没有发现?对应的能力是发现和解决问题的能力。2,体系:要解决的问题的属于哪一类的问题?这类问题能否进一步抽象,让系统解决更大的问题?对应的抽象归纳和体系化思维的能力。

架构师是互联网行业高薪又紧俏的资源。成为架构师最基本的是设计能力。设计与设计的区别主要体现在两方面:


1,深度:要解决哪些问题?这个问题背后的根本问题是什么?还有什么问题没有发现?对应的能力是发现和解决问题的能力。


2,体系:要解决的问题的属于哪一类的问题?这类问题能否进一步抽象,让系统解决更大的问题?对应的抽象归纳和体系化思维的能力。


而做架构的基本功就是研究成熟成功的系统,并总结归纳为一种设计方法添加到自己的设计库中。今天我们来看看文件存储机制的通用实现及原理-谈Kafka、Redis、基于Lucene的搜索引擎等中间件和数据库的文件存储机制。如果你有九年义务教育以上学历,并且觉得看不懂这篇文章,请给我留言~~


顺便插一句,不知道大家有没有奇怪静儿最近都没有写高可用方面的文章。事情是这样的,对于高可用的很多设计、架构,静儿都在进行专利申请中,为了避免对公司造成影响和损失,暂时处于多想不说的阶段。


   一个商业化中间件的性能好坏,其文件存储机制设计是衡量一个消息队列服务技术水平和最关键指标之一。下面先介绍一下各个中间件的存储机制。看不懂可直接跳到最后。

各个中间件的存储机制

 

1Kafka  

 

Kafka是最初由Linkedin公司开发,是一个分布式、分区的、多副本的、多订阅者,基于zookeeper协议的分布式日志系统(也可以当做MQ系统),常见可以用于web/nginx日志、访问日志,消息服务等等,Linkedin于2010年贡献给了Apache基金会并成为顶级开源项目。


设计特点


Kafka把topic中一个partition(大块)大文件分成多个小文件段,通过多个小文件段,就容易定期清除或删除已经消费完的文件,减少磁盘占用。


通过索引信息可以快速定位message和确定response的最大大小。


通过index(索引)元数据全部映射到memory(内存),可以避免segment file(文件片段)的IO磁盘操作。


通过索引文件稀疏存储,可以大幅降低index文件元数据占用空间大小。


   一张图解释一下刚才说的特点:


12132328-d56e827212dfa735.jpg


  从上面的图中可以看到,生产者和消费者并没有直接的交互。这就达到了生产者消费者模式的第一个好处:解耦。作为消费者,可以自定义消费线程数和消费者数量。这就达到了生产者消费者模式的第二个好处:限流。这也是大家使用MQ一般想要达到的目的。


2Redis  

 

   谈redis首先要纠正一个误区:缓存比mysql快。为了说明这个问题,下面是静儿自己动手得到的数据。


结论:使用了缓存后响应时间不稳定

image.gif

网络异常取消重新上传


结论:mysql的响应时间非常稳定

image.gif

网络异常取消重新上传


从cat监控中可以看到缓存的get时间确实较长。


12132328-8374deb910221d58.jpg


顺便跑题一下,静儿测试中还发现在jvm正常执行业务逻辑,不太复杂无外部调用,一般是1到2毫秒。但是如果抛出了异常,这段代码执行时间要变成100ms+。所以一般代码中禁止用抛出非必要异常来代替正常逻辑。


12132328-9f7fc5ef0be58176.jpg


之所以给大家打这个预防针,是因为下面要给出Redis的描述了。


Redis本质上是一个key-value类型的内存数据库,整个数据库加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过10万次读写操作,是已经性能最快的key-value DB。


Redis存储机制分成两种Snapshot和AOF。无论是哪种机制,Redis都是将数据存储在内存中。


AOF工作原理:是将数据先存在内存,但是在存储的时候会使用fsync(无阻塞进程的)来完成对本次写操作的日志记录。AOF最关键的配置就是关于调用fsync追加日志文件的频率,有两种预设频率。always:每次记录进来都添加。everysecond每秒添加一次。


存储模式性能和安全比较:


1.性能


snapshot性能是要明显高于AOP方式的,原因有两点:


1>采用二进制方式存储,数据文件小,加载快速。


2>存储的时候是按照配置中的save策略来存储,每次都是聚合很多数据批量存储,写入的效率高。AOF一般都是工作在实时或准实时模式下。相对存储频率高,效率低。


2.数据安全


AOF数据安全性高于Snapshot,原因:


snapshot存储是基于累积批量的思想,累积的数据越多写入效率越高,但是如果长时间数据不写入RDB(redis的数据库),redis遇到了崩溃,没写入的数据就无法恢复。


   Redis中有rewrite功能,AOF的存储是按照记录日志的方式去工作的,成千上万的数据插入必然导致日志文件的扩大,Redis这个时候会根据配置合理触发rewrite操作。这个操作是将最终保留值记录到日志文件中,从而缩小日志文件的大小。这个类似于lucene的optimize操作。

 

3Mysql/MariaDB  

 

Mysql与目前流行的nosql数据库最大的不同是规定了严格的数据类型。数据类型因为在创建表时在内存中严格划定了地址空间,所以能限定字段的数据存储长度。


   数据类型限定范围的方式有两种:1是严格限定空间,划分了多少空间就只能存储多少数据,超出的数据将被切断;2是使用额外的字节的bit位来标记某个数据,存储了就进行标记,不存储就不标记。下面介绍3种类型的存储方式。


1.整形的存储


它严格限定空间,每个已划分的字节上的bit位上的0和1直接可以计算出数值,所以它的范围是根据bit位的数量值来计算的。一个字节有8个bit位,一个bit位可以构成2的8次方=256个数值。同理2字节共2的16次方=65526个数值。也就是说,在0-255之间的数字都只占用1个字节,256-65535之间的数字占用2个字节。


2.char的存储


char类型是常被成为定长字符串类型,它严格限定空间长度,但它限定的是字符数不是字节数。它有“短了就使用空格补足”的能力。


3.varchar常被称为“变长字符串类型”。它存储数据时使用额外的字节的bit位来标记某个字节是否存储了数据。每存储1个字节占用一个bit位进行标记。一个额外的字节可以标记256个字节,2个额外的字节可以标记65536个字节。MySQL/mariadb限制了最大能存储65536个字节。这表示,如果是单字节的字符,它最多能存储65536个字符,如果是多字节字符,如UTF8的每个字节占用3个字节,它最多能存储65536/3=21845个字符。

 

4基于Lucene的搜索引擎  

 

提到基于Lucene的搜索引擎,大家可能更熟悉ElasticSearch(ES)。静儿有段时间专门负责公司的搜索,没有现在这么忙,本应该是非常难得和宝贵的机会。有大把的时间研究源码,可惜当时整个心都不在工作上。当时用的还是solr4.X.X(solr是基于Lucene的搜索引擎系统,lucene和solr版本同步更新,目前最新是7.6.0),当时solr每月发布一个新版本。版本有很多bug,我当时是在源码上做了很多修复补丁的。但是当时各种意识都很薄弱。如果当初给apache提patch,有些应该是能通过的。这就能形成了一个良好的反馈循环,可能现在的状况截然不同。


   想起dubbo有段时间已经不更新版本,后来捐给了apache,给这个项目又重新注入了生机。其中的一个教训就是大家一定要有很强的开源意识。这种意识还包括在自己做功能方案和开发实现的时候要有业界调研和对标的意识。


静儿的梦想是实现自己的搜索引擎中间件,所以目前从事的是和这个原理有很深渊源的工作:容器调度。什么?看不出来联系?那这个以后再慢慢聊。


Lucene的数据都存在一个目录下,一个目录构成了一个索引。Lucene经多年演进优化,现在的一个索引文件可以分为4个部分:词典、倒排表、正向文件、列式存储。一张表解释lucene的存储原理:


12132328-885792a2632a3dcd.jpg


通用原理


   1.高频读取操作放于内存。


2.文件分段减少磁盘IO操作。


3.磁盘存储防止数据丢失。


4.更好的结构化可以提升存储和读取效率。


以上です。不解释。


总结


     之前和同事聊天,同事说他们架构师基于原来的版本设计了一个非常完美的2.0方案。但是这个方案并不解决现有的任何问题。这也是静儿想做架构并且可以很轻松的找到一个架构师职位,但一直都是在项目组内自己动手写代码的原因:一个旁观者想了解内部的痛点很困难。


前段时间大家纷纷剖析拼多多优惠券事件背后的技术问题。不可否认,技术是有点菜。但是拼多多目前整体看是成功的。成功在哪里呢?它成功的解决了商家(其他平台门槛高,入住不了)和消费者(以更低的价格买到商品)的痛点。所以这点状况并未伤及元气。


   在做设计的时候,我会首先问自己一个问题:现在哪里最痛?架构讲究深度和体系。深度解决的是痛点根本性的问题。体系解决的是未来的痛点问题。不以解决问题为目的设计的系统都是“成功之母”。

相关文章
|
3月前
|
存储 缓存 前端开发
Django 后端架构开发:存储层调优策略解析
Django 后端架构开发:存储层调优策略解析
53 2
|
3月前
|
存储 NoSQL 关系型数据库
MPP架构数据仓库使用问题之Visibility bitmap表被删除的文件信息是如何记录的
MPP架构数据仓库使用问题之Visibility bitmap表被删除的文件信息是如何记录的
|
3天前
|
SQL Java 数据库连接
Mybatis架构原理和机制,图文详解版,超详细!
MyBatis 是 Java 生态中非常著名的一款 ORM 框架,在一线互联网大厂中应用广泛,Mybatis已经成为了一个必会框架。本文详细解析了MyBatis的架构原理与机制,帮助读者全面提升对MyBatis的理解和应用能力。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
Mybatis架构原理和机制,图文详解版,超详细!
|
17天前
|
开发者 容器
Flutter&鸿蒙next 布局架构原理详解
本文详细介绍了 Flutter 中的主要布局方式,包括 Row、Column、Stack、Container、ListView 和 GridView 等布局组件的架构原理及使用场景。通过了解这些布局 Widget 的基本概念、关键属性和布局原理,开发者可以更高效地构建复杂的用户界面。此外,文章还提供了布局优化技巧,帮助提升应用性能。
78 4
|
17天前
|
存储 Dart 前端开发
flutter鸿蒙版本mvvm架构思想原理
在Flutter中实现MVVM架构,旨在将UI与业务逻辑分离,提升代码可维护性和可读性。本文介绍了MVVM的整体架构,包括Model、View和ViewModel的职责,以及各文件的详细实现。通过`main.dart`、`CounterViewModel.dart`、`MyHomePage.dart`和`Model.dart`的具体代码,展示了如何使用Provider进行状态管理,实现数据绑定和响应式设计。MVVM架构的分离关注点、数据绑定和可维护性特点,使得开发更加高效和整洁。
146 3
|
23天前
|
监控 网络协议 安全
DNS服务器故障不容小觑,从应急视角谈DNS架构
DNS服务器故障不容小觑,从应急视角谈DNS架构
45 4
|
29天前
|
设计模式 测试技术 持续交付
架构视角下的NHibernate:设计模式与企业级应用考量
【10月更文挑战第13天】随着软件开发向更复杂、更大规模的应用转变,数据访问层的设计变得尤为重要。NHibernate作为一个成熟的对象关系映射(ORM)框架,为企业级.NET应用程序提供了强大的支持。本文旨在为有一定经验的开发者提供一个全面的指南,介绍如何在架构层面有效地使用NHibernate,并结合领域驱动设计(DDD)原则来构建既强大又易于维护的数据层。
37 2
|
29天前
|
容器
Flutter&鸿蒙next 布局架构原理详解
Flutter&鸿蒙next 布局架构原理详解
|
30天前
|
存储 监控 分布式数据库
百亿级存储架构: ElasticSearch+HBase 海量存储架构与实现
本文介绍了百亿级数据存储架构的设计与实现,重点探讨了ElasticSearch和HBase的结合使用。通过ElasticSearch实现快速检索,HBase实现海量数据存储,解决了大规模数据的高效存储与查询问题。文章详细讲解了数据统一接入、元数据管理、数据一致性及平台监控等关键模块的设计思路和技术细节,帮助读者理解和掌握构建高性能数据存储系统的方法。
百亿级存储架构: ElasticSearch+HBase 海量存储架构与实现
|
1月前
|
前端开发 Java 应用服务中间件
21张图解析Tomcat运行原理与架构全貌
【10月更文挑战第2天】本文通过21张图详细解析了Tomcat的运行原理与架构。Tomcat作为Java Web开发中最流行的Web服务器之一,其架构设计精妙。文章首先介绍了Tomcat的基本组件:Connector(连接器)负责网络通信,Container(容器)处理业务逻辑。连接器内部包括EndPoint、Processor和Adapter等组件,分别处理通信、协议解析和请求封装。容器采用多级结构(Engine、Host、Context、Wrapper),并通过Mapper组件进行请求路由。文章还探讨了Tomcat的生命周期管理、启动与停止机制,并通过源码分析展示了请求处理流程。