在线商城网站备案,给公司做一个网站,土特产网站的制作,wordpress多个用户发表文章前言
Netty 是一款基于 Java 的网络编程框架#xff0c;能为应用程序管理复杂的网络编程、多线程处理以及并发。Netty 隐藏了样板和底层代码#xff0c;让业务逻辑保持分离#xff0c;更加易于复用。使用 Netty 可以得到一个易于使用的 API#xff0c;让开发人员可以专注自…前言
Netty 是一款基于 Java 的网络编程框架能为应用程序管理复杂的网络编程、多线程处理以及并发。Netty 隐藏了样板和底层代码让业务逻辑保持分离更加易于复用。使用 Netty 可以得到一个易于使用的 API让开发人员可以专注自己的应用程序的独特之处。介绍了 Netty 框架并展示了如何将它引入到 Java 网络应 用程序中通过对本书的学习读者能学到如何编写高度可伸缩的应用程序而无需关心底层 API。本书将通过许多动手的例子教读者以异步的方式进行思考并帮助读者掌握构建大规模网络应用程序的最佳实践。
结构化数据、非结构化数据与半结构化数据
文章的开始聊一下结构化数据、非结构化数据与半结构化数据因为数据特点的不同将在技术上直接影响存储引擎的选型。
首先是结构化数据根据定义结构化数据指的是由二维表结构来逻辑表达和实现的数据严格遵循数据格式与长度规范也称作为行数据特点为数据以行为单位一行数据表示一个实体的信息每一行数据的属性是相同的。例如 因此关系型数据库完美契合结构化数据的特点关系型数据库也是关系型数据最主要的存储与管理引擎。
非结构化数据指的是数据结构不规则或不完整没有任何预定义的数据模型不方便用二维逻辑表来表现的数据例如办公文档Word、文本、图片、HTML、各类报表、视频音频等。
介于结构化与非结构化数据之间的数据就是半结构化数据了它是结构化数据的一种形式虽然不符合二维逻辑这种数据模型结构但是包含相关标记用来分割语义元素以及对记录和字段进行分层。常见的半结构化数据有XML和JSON例如
personname张三/nameage18/agephone12345/phone
/person这种结构也被成为自描述的结构。
以关系型数据库的方式做存储的架构演进
首先我们看一下使用关系型数据库的方式企业一个系统发展的几个阶段的架构演进由于本文写的是Sql与NoSql因此只以存储方式作为切入点不会涉及类似MQ、ZK这些中间件内容 阶段一企业刚发展的阶段最简单一个应用服务器配一个关系型数据库每次读写数据库。
阶段二无论是使用MySQL还是Oracle还是别的关系型数据库数据库通常不会先成为性能瓶颈通常随着企业规模的扩大一台应用服务器扛不住上游过来的流量且一台应用服务器会产生单点故障的问题因此加应用服务器并且在流量入口使用Nginx做一层负载均衡保证把流量均匀打到应用服务器上。
阶段三随着企业规模的继续扩大此时由于读写都在同一个数据库上数据库性能出现一定的瓶颈此时简单地做一层读写分离每次写主库读备库主备库之间通过binlog同步数据就能很大程度上解决这个阶段的数据库性能问题
阶段四企业发展越来越好了业务越来越大了做了读写分离数据库压力还是越来越大这时候怎么办呢一台数据库扛不住那我们就分几台吧做分库分表对表做垂直拆分对库做水平拆分。以扩数据库为例扩出两台数据库以一定的单号例如交易单号以一定的规则例如取模交易单号对2取模为0的丢到数据库1去交易单号对2取模为1的丢到数据库2去通过这样的方式将写数据库的流量均分到两台数据库上。一般分库分表会使用Shard的方式通过一个中间件便于连接管理、数据监控且客户端无需感知数据库ip
关系型数据库的优点
上面的方式看似可以解决问题实际上确实也能解决很多问题正常对关系型数据库做一下读写分离 分库分表支撑个1W的读写QPS还是问题不大的。但是受限于关系型数据库本身这套架构方案依然有着明显的不足下面对利用关系型数据库方式做存储的方案的优点先进行一下分析后一部分再分析一下缺点对某个技术的优缺点的充分理解是技术选型的前提。
易理解
因为行 列的二维表逻辑是非常贴近逻辑世界的一个概念关系模型相对网状、层次等其他模型更加容易被理解
操作方便
通用的SQL语言使得操作关系型数据库非常方便支持join等复杂查询
数据一致性
支持ACID特性可以维护数据之间的一致性这是使用数据库非常重要的一个理由之一例如同银行转账张三转给李四100元钱张三扣100元李四加100元而且必须同时成功或者同时失败否则就会造成用户的资损
数据稳定
数据持久化到磁盘没有丢失数据风险支持海量数据存储
服务稳定
最常用的关系型数据库产品MySql、Oracle服务器性能卓越服务稳定通常很少出现宕机异常
关系型数据库的缺点
紧接着的我们看一下关系型数据库的缺点也是比较明显的。
高并发下IO压力大
数据按行存储即使只针对其中某一列进行运算也会将整行数据从存储设备中读入内存导致IO较高
为维护索引付出的代价大
为了提供丰富的查询能力通常热点表都会有多个二级索引一旦有了二级索引数据的新增必然伴随着所有二级索引的新增数据的更新也必然伴随着所有二级索引的更新这不可避免地降低了关系型数据库的读写能力且索引越多读写能力越差。有机会的话可以看一下自己公司的数据库除了数据文件不可避免地占空间外索引占的空间其实也并不少
为维护数据一致性付出的代价大
数据一致性是关系型数据库的核心但是同样为了维护数据一致性的代价也是非常大的。我们都知道SQL标准为事务定义了不同的隔离级别从低到高依次是读未提交、读已提交、可重复度、串行化事务隔离级别月底可能出现的并发异常越多但是通常而言能提供的并发能力越强。那么为了保证事务一致性数据库就需要提供并发控制与故障恢复两种技术前者用于减少并发异常后者可以在系统异常的时候保证事务与数据库状态不会被破坏。对于并发控制其核心思想就是加锁无论是乐观锁还是悲观锁只要提供的隔离级别越高那么读写性能必然越差
水平扩展后带来的种种问题难处理
前文提过随着企业规模扩大一种方式是对数据库做分库做了分库之后数据迁移1个库的数据按照一定规则打到2个库中、跨库join订单数据里有用户数据两条数据不在同一个库中、分布式事务处理都是需要考虑的问题尤其是分布式事务处理业界当前都没有特别好的解决方案
表结构扩展不方便
由于数据库存储的是结构化数据因此表结构schema是固定的扩展不方便如果需要修改表结构需要执行DDLdata definition language语句修改修改期间会导致锁表部分服务不可用
全文搜索功能弱
例如like “%中国真伟大%”只能搜索到2019年中国真伟大爱祖国无法搜索到中国真是太伟大了这样的文本即不具备分词能力且like查询在%中国真伟大这样的搜索条件下无法命中索引将会导致查询效率大大降低
写了这么多我的理解核心还是前三点它反映出的一个问题是关系型数据库在高并发下的能力是有瓶颈的尤其是写入/更新频繁的情况下出现瓶颈的结果就是数据库CPU高、Sql执行慢、客户端报数据库连接池不够等错误因此例如万人秒杀这种场景我们绝对不可能通过数据库直接去扣减库存。
可能有朋友说数据库在高并发下的能力有瓶颈我公司有钱加CPU、换固态硬盘、继续买服务器加数据库做分库不就好了问题是这是一种性价比非常低的方式花1000万达到的效果换其他方式可能100万就达到了不考虑人员、服务器投入产出比的Leader就是个不合格的Leader且关系型数据库的方式受限于它本身的特点可能花了钱都未必能达到想要的效果。至于什么是花100万就能达到花1000万效果的方式呢可以继续往下看这就是我们要说的NoSql。
结合NoSql的方式做存储的架构演进
像上文分析的数据库作为一种关系型数据的存储引擎存储的是关系型数据它有优点同时也有明显的缺点因此通常在企业规模不断扩大的情况下不会一味指望通过增强数据库的能力来解决数据存储问题而是会引入其他存储也就是我们说的NoSql。
NoSql的全称为Not Only SQL泛指非关系型数据库是对关系型数据库的一种补充特别注意补充这两个字这意味着NoSql与关系型数据库并不是对立关系二者各有优劣取长补短在合适的场景下选择合适的存储引擎才是正确的做法。
比较简单的NoSql就是缓存 针对那些读远多于写的数据引入一层缓存每次读从缓存中读取缓存中读取不到再去数据库中取取完之后再写入到缓存对数据做好失效机制通常就没有大问题了。通常来说缓存是性能优化的第一选择也是见效最明显的方案。
但是缓存通常都是KV型存储且容量有限基于内存无法解决所有问题于是再进一步的优化我们继续引入其他NoSql 数据库、缓存与其他NoSql并行工作充分发挥每种NoSql的特点。当然NoSql在性能方面大大优于关系挺数据库的同时往往也伴随着一些特性的缺失比较常见的就是事务功能的缺失。
下面看一下常用的NoSql及他们的代表产品并对每种NoSql的优缺点和适用场景做一下分析便于熟悉每种NoSql的特点方便技术选型。
KV型NoSql代表----Redis
KV型NoSql顾名思义就是以键值对形式存储的非关系型数据库是最简单、最容易理解也是大家最熟悉的一种NoSql因此比较快地带过。Redis、MemCache是其中的代表Redis又是KV型NoSql中应用最广泛的NoSqlKV型数据库以Redis为例最大的优点我总结下来就两点
数据基于内存读写效率高KV型数据时间复杂度为O(1)查询速度快
因此KV型NoSql最大的优点就是高性能利用Redis自带的BenchMark做基准测试TPS可达到10万的级别性能非常强劲。同样的Redis也有所有KV型NoSql都有的比较明显的缺点
只能根据K查V无法根据V查K查询方式单一只有KV的方式不支持条件查询多条件查询唯一的做法就是数据冗余但这会极大的浪费存储空间内存是有限的无法支持海量数据存储同样的由于KV型NoSql的存储是基于内存的会有丢失数据的风险
综上所述KV型NoSql最合适的场景就是缓存的场景
读远多于写读取能力强没有持久化的需求可以容忍数据丢失反正丢了再查询一把写入就是了
例如根据用户id查询用户信息每次根据用户id去缓存中查询一把查到数据直接返回查不到去关系型数据库里面根据id查询一把数据写到缓存中去。
搜索型NoSql代表----ElasticSearch
传统关系型数据库主要通过索引来达到快速查询的目的但是在全文搜索的场景下索引是无能为力的like查询一来无法满足所有模糊匹配需求二来使用限制太大且使用不当容易造成慢查询搜索型NoSql的诞生正是为了解决关系型数据库全文搜索能力较弱的问题ElasticSearch是搜索型NoSql的代表产品。
全文搜索的原理是倒排索引我们看一下什么是倒排索引。要说倒排索引我们先看下什么是正排索引传统的正排索引是文档–关键字的映射例如Tom is my friend这句话会将其切分为Tom、“is”、“my”、friend四个单词在搜索的时候对文档进行扫描符合条件的查出来。这种方式原理非常简单但是由于其检索效率太低基本没什么实用价值。
倒排索引则完全相反它是关键字–文档的映射我用张表格展示一下就比较清楚了 意思是我现在这里有Tom is Tom、“Tom is my friend”、“Thank you, Betty”、“Tom is Betty’s husband四句话搜索引擎会根据一定的切分规则将这句话切成N个关键字并以关键字的维度维护关键字在每个文本中的出现次数。这样下次搜索Tom的时候由于Tom这个词语在Tom is Tom”、“Tom is my friend”、Tom is Betty’s husband三句话中都有出现因此这三条记录都会被检索出来且由于Tom is Tom这句话中Tom出现了2次因此这条记录对Tom这个单词的匹配度最高最先展示。这就是搜索引擎倒排索引的基本原理假设某个关键字在某个文档中出现那么倒排索引中有两部分内容
文档ID在该文档中出现的位置情况
可以举一反三我们搜索Betty Tom这两个词语也是一样搜索引擎将Betty Tom切分为Tom、Betty两个单词根据开发者指定的满足率比如满足率50%那么只要记录中出现了两个单词之一的记录都会被检索出来再按照匹配度进行展示。
搜索型NoSql以ElasticSearch为例它的优点为
支持分词场景、全文搜索这是区别于关系型数据库最大特点支持条件查询支持聚合操作类似关系型数据库的Group By但是功能更加强大适合做数据分析数据写文件无丢失风险在集群环境下可以方便横向扩展可承载PB级别的数据高可用自动发现新的或者失败的节点重组和重新平衡数据确保数据是安全和可访问的
同样ElasticSearch也有比较明显的缺点 性能全靠内存来顶也是使用的时候最需要注意的点非常吃硬件资源、吃内存大数据量下64G SSD基本是标配算得上是数据库中的爱马仕了。为什么要专门提一下内存呢因为内存这个东西是很值钱的相同的配置多一倍内存一个月差不多就要多花几百块钱至于ElasticSearch内存用在什么地方大概有如下这些 Indexing Buffer----ElasticSearch基于LuenceLucene的倒排索引是先在内存里生成然后定期以Segment File的方式刷磁盘的每个Segment File实际就是一个完整的倒排索引 Segment Memory----倒排索引前面说过是基于关键字的Lucene在4.0后会将所有关键字以FST这种数据结构的方式将所有关键字在启动的时候全量加载到内存加快查询速度官方建议至少留系统一半内存给Lucene 各类缓存----Filter Cache、Field Cache、Indexing Cache等用于提升查询分析性能例如Filter Cache用于缓存使用过的Filter的结果集 Cluter State Buffer----ElasticSearch被设计为每个Node都可以响应用户请求因此每个Node的内存中都包含有一份集群状态的拷贝一个规模很大的集群这个状态信息可能会非常大 读写之间有延迟写入的数据差不多1s样子会被读取到这也正常写入的时候自动加入这么多索引肯定影响性能 数据结构灵活性不高ElasticSearch这个东西字段一旦建立就没法修改类型了假如建立的数据表某个字段没有加全文索引想加上那么只能把整个表删了再重建
因此搜索型NoSql最适用的场景就是有条件搜索尤其是全文搜索的场景作为关系型数据库的一种替代方案。
另外搜索型数据库还有一种特别重要的应用场景。我们可以想一旦对数据库做了分库分表后原来可以在单表中做的聚合操作、统计操作是否统统失效例如我把订单表分16个库1024张表那么订单数据就散落在1024张表中我想要统计昨天浙江省单笔成交金额最高的订单是哪笔如何做我想要把昨天的所有订单按照时间排序分页展示如何做这就是文档型NoSql的另一大作用了我们可以把分表之后的数据统一打在文档型NoSql中利用文档型NoSql的搜索与聚合能力完成对全量数据的查询。
至于为什么把它放在KV型NoSql后面作为第二个写呢因为通常搜索型NoSql也会作为一层前置缓存来对关系型数据库进行保护。
列式NoSql代表----HBase
列式NoSql大数据时代最具代表性的技术之一了以HBase为代表。
列式NoSql是基于列式存储的那么什么是列式存储呢列式NoSql和关系型数据库一样都有主键的概念区别在于关系型数据库是按照行组织的数据 看到每行有name、phone、address三个字段这是行式存储的方式且可以观察id 2的这条数据即使phone字段没有它也是占空间的。
列式存储完全是另一种方式它是按每一列进行组织的数据 这么做有什么好处呢大致有以下几点
查询时只有指定的列会被读取不会读取所有列存储上节约空间Null值不会被存储一列中有时候会有很多重复数据尤其是枚举数据性别、状态等这类数据可压缩行式数据库压缩率通常在3:15:1之间列式数据库的压缩率一般在8:130:1左右列数据被组织到一起一次磁盘IO可以将一列数据一次性读取到内存中
第二点说到了数据压缩什么意思呢以比较常见的字典表压缩方式举例 自己看图理解一下应该就懂了。
接着继续讲讲优缺点列式NoSql以HBase为代表的优点为
海量数据无限存储PB级别数据随便存底层基于HDFSHadoop文件系统数据持久化读写性能好只要没有滥用造成数据热点读写基本随便玩横向扩展在关系型数据库及非关系型数据库中都是最方便的之一只需要添加新机器就可以实现数据容量的线性增长且可用在廉价服务器上节省成本本身没有单点故障可用性高可存储结构化或者半结构化的数据列数理论上无限HBase本身只对列族数量有要求建议1~3个
说了这么多HBase的优点又到了说HBase缺点的时候了
HBase是Hadoop生态的一部分因此它本身是一款比较重的产品依赖很多Hadoop组件数据规模不大没必要用运维还是有点复杂的KV式不支持条件查询或者说条件查询非常非常弱吧HBase在Scan扫描一批数据的情况下还是提供了前缀匹配这种API的条件查询除非定义多个RowKey做数据冗余不支持分页查询因为统计不了数据总数
因此HBase比较适用于那种KV型的且未来无法预估数据增长量的场景另外HBase使用还是需要一定的经验主要体现在RowKey的设计上。
文档型NoSql代表----MongoDB
坦白讲根据我的工作经历文档型NoSql我只有比较浅的使用经验因此这部分只能结合之前的使用与网上的文章大致给大家介绍一下。
什么是文档型NoSql呢文档型NoSql指的是将半结构化数据存储为文档的一种NoSql文档型NoSql通常以JSON或者XML格式存储数据因此文档型NoSql是没有Schema的由于没有Schema的特性我们可以随意地存储与读取数据因此文档型NoSql的出现是解决关系型数据库表结构扩展不方便的问题的。
MongoDB是文档型NoSql的代表产品同时也是所有NoSql产品中的明星产品之一因此这里以MongoDB为例。按我的理解作为文档型NoSqlMongoDB是一款完全和关系型数据库对标的产品就我们从存储上来看 看到关系型数据库是按部就班地每个字段一列存在MongDB里面就是一个JSON字符串存储。关系型数据可以为name、phone建立索引MongoDB使用createIndex命令一样可以为列建立索引建立索引之后可以大大提升查询效率。其他方面而言就大的基本概念二者之间基本也是类似的 因此对于MongDB我们只要理解成一个Free-Schema的关系型数据库就完事了它的优缺点比较一目了然优点
没有预定义的字段扩展字段容易相较于关系型数据库读写性能优越命中二级索引的查询不会比关系型数据库慢对于非索引字段的查询则是全面胜出
缺点在于
不支持事务操作虽然Mongodb4.0之后宣称支持事务但是效果待观测多表之间的关联查询不支持虽然有嵌入文档的方式join查询还是需要多次操作空间占用较大这个是MongDB的设计问题空间预分配机制 删除数据后空间不释放只有用db.repairDatabase()去修复才能释放目前没发现MongoDB有关系型数据库例如MySql的Navicat这种成熟的运维工具
总而言之MongDB的使用场景很大程度上可以对标关系型数据库但是比较适合处理那些没有join、没有强一致性要求且表Schema会常变化的数据。
总结数据库与NoSql及各种NoSql间的对比
最后一部分做一个总结本文归根到底是两个话题
何时选用关系型数据库何时选用非关系型数据库选用非关系型数据库使用哪种非关系型数据库
首先是第一个话题关系型数据库与非关系型数据库的选择在我理解里面无非就是两点考虑 第一点不多解释应该都理解非关系型数据库都是通过牺牲了ACID特性来获取更高的性能的假设两张表之间有比较强的一致性需求那么这类数据是不适合放在非关系型数据库中的。
第二点核心数据不走非关系型数据库例如用户表、订单表但是这有一个前提就是这一类核心数据会有多种查询模式例如用户表有ABCD四个字段可能根据AB查可能根据AC查可能根据D查假设核心数据但是就是个KV形式比如用户的聊天记录那么HBase一存就完事了。
这几年的工作经验来看非核心数据尤其是日志、流水一类中间数据千万不要写在关系型数据库中这一类数据通常有两个特点
写远高于读写入量巨大
一旦使用关系型数据库作为存储引擎将大大降低关系型数据库的能力正常读写QPS不高的核心服务会受这一类数据读写的拖累。
接着是第二个问题如果我们使用非关系型数据库作为存储引擎那么如何选型其实上面的文章基本都写了这里只是做一个总结所有的缺点都不会体现事务这个点因为这是所有NoSql相比关系型数据库共有的一个问题 但是这里特别说明选型一定要结合实际情况而不是照本宣科比如
企业发展之初明明一个关系型数据库就能搞定且支撑一年的架构搞一套大而全的技术方案出来有一些数据条件查询多更适合使用ElasticSearch做存储降低关系型数据库压力但是公司成本有限这种情况下这类数据可以尝试继续使用关系型数据库做存储有一类数据格式简单就是个KV类型且增长量大但是公司没有HBase这方面的人才运维上可能会有一定难度出于实际情况考虑可先用关系型数据库顶一阵子
所以如果不考虑实际情况虽然合适有些存储引擎更加合适但是强行使用反而适得其反总而言之适合自己的才是最好的。
面试准备复习资料分享 为了应付面试也刷了很多的面试题与资料现在就分享给有需要的读者朋友资料我只截取出来一部分哦有需要的可以来找我获取哈 获取方式点击蓝色字体即可免费获取 人才运维上可能会有一定难度出于实际情况考虑可先用关系型数据库顶一阵子
所以如果不考虑实际情况虽然合适有些存储引擎更加合适但是强行使用反而适得其反总而言之适合自己的才是最好的。
面试准备复习资料分享 为了应付面试也刷了很多的面试题与资料现在就分享给有需要的读者朋友资料我只截取出来一部分哦有需要的可以来找我获取哈 获取方式点击蓝色字体即可免费获取
[外链图片转存中…(img-BJGWRTAs-1624082963652)]