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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 架构师是互联网行业高薪又紧俏的资源。成为架构师最基本的是设计能力。设计与设计的区别主要体现在两方面: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方案。但是这个方案并不解决现有的任何问题。这也是静儿想做架构并且可以很轻松的找到一个架构师职位,但一直都是在项目组内自己动手写代码的原因:一个旁观者想了解内部的痛点很困难。


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


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

相关文章
|
6天前
|
设计模式 安全 Java
【分布式技术专题】「Tomcat技术专题」 探索Tomcat技术架构设计模式的奥秘(Server和Service组件原理分析)
【分布式技术专题】「Tomcat技术专题」 探索Tomcat技术架构设计模式的奥秘(Server和Service组件原理分析)
41 0
|
6天前
|
Cloud Native Linux 网络虚拟化
深入理解Linux veth虚拟网络设备:原理、应用与在容器化架构中的重要性
在Linux网络虚拟化领域,虚拟以太网设备(veth)扮演着至关重要的角色🌐。veth是一种特殊类型的网络设备,它在Linux内核中以成对的形式存在,允许两个网络命名空间之间的通信🔗。这篇文章将从多个维度深入分析veth的概念、作用、重要性,以及在容器和云原生环境中的应用📚。
深入理解Linux veth虚拟网络设备:原理、应用与在容器化架构中的重要性
|
6天前
|
API 持续交付 开发者
构建高效微服务架构:后端开发的新视角
【5月更文挑战第8天】 随着现代软件开发的演变,微服务架构已经成为了企业追求敏捷、可扩展和灵活部署的重要解决方案。本文将深入探讨如何构建一个高效的微服务架构,包括关键的设计原则、技术栈选择以及持续集成与部署的最佳实践。我们还将讨论微服务带来的挑战,如数据一致性、服务发现和网络延迟,并提出相应的解决策略。通过本文,后端开发者将获得构建和维护微服务系统所需的深度知识,并了解如何在不断变化的技术环境中保持系统的健壮性和可维护性。
44 8
|
1天前
|
存储 弹性计算 Cloud Native
AutoMQ:如何基于阿里云计算与存储产品实现云原生架构升级
AutoMQ:如何基于阿里云计算与存储产品实现云原生架构升级
|
1天前
|
存储 关系型数据库 分布式数据库
【PolarDB开源】深入PolarDB内核:探究存储计算分离架构的设计哲学
【5月更文挑战第20天】PolarDB是阿里巴巴的云原生分布式数据库,以其存储计算分离架构为核心,解决了传统数据库的扩展性和资源灵活性问题。该架构将数据存储和计算处理分开,实现高性能(通过RDMA加速数据传输)、高可用性(多副本冗余保证数据可靠性)和灵活扩展(计算资源独立扩展)。通过动态添加计算节点以应对业务流量变化,PolarDB展示了其在云时代应对复杂业务场景的能力。随着开源项目的进展,PolarDB将持续推动数据库技术发展。
28 6
|
6天前
|
运维 监控 安全
WLAN的组网架构和工作原理
WLAN的组网架构和工作原理
9 0
|
6天前
|
消息中间件 Java 持续交付
构建高效微服务架构:后端开发的新视角
【5月更文挑战第15天】在现代软件开发的浪潮中,微服务架构已成为推动技术创新和服务灵活性的关键因素。本文将探讨如何构建一个高效的微服务架构,包括关键的设计原则、技术栈选择以及持续集成与部署的最佳实践。通过分析微服务的优势和挑战,我们将为后端开发人员提供一个全面的指导,帮助他们在构建可扩展、容错且易于维护的系统时做出明智的决策。
|
6天前
|
负载均衡 JavaScript Java
构建高效微服务架构:后端开发的新视角
【5月更文挑战第13天】在现代软件开发中,微服务架构已经成为一种流行趋势。它通过将应用程序拆分为一组小型、独立的服务来提高可扩展性、弹性和可维护性。本文将探讨如何构建一个高效的微服务架构,包括选择合适的技术栈、设计良好的服务接口、确保数据一致性以及实现有效的服务发现和负载均衡。
|
6天前
|
存储 移动开发 前端开发
【Uniapp 专栏】Uniapp 架构设计与原理探究
【5月更文挑战第12天】Uniapp是一款用于跨平台移动应用开发的框架,以其高效性和灵活性脱颖而出。它基于HTML、CSS和Vue.js构建视图层,JavaScript处理逻辑层,管理数据层,实现统一编码并支持原生插件扩展。通过抽象平台特性,开发者能专注于业务逻辑,提高开发效率。尽管存在兼容性和复杂性挑战,但深入理解其架构设计与原理将助力开发者创建高质量的跨平台应用。随着技术进步,Uniapp将继续在移动开发领域扮演重要角色。
【Uniapp 专栏】Uniapp 架构设计与原理探究
|
6天前
|
负载均衡 NoSQL 关系型数据库
深入浅出Redis(六):Redis的主从架构与主从复制原理
深入浅出Redis(六):Redis的主从架构与主从复制原理