一、数据库索引种类很多-什么是稀疏索引和密集索引
回答
(一)密集索引
在密集索引中,数据库中的每个键值都有⼀个索引记录,可以加快搜索速度,但需要更多空间来存储索引记录本身,索引记录包含键值和指向磁盘上实际记录的指针。
(二)稀疏索引
在稀疏索引中,不会为每个关键字创建索引记录,⽽是为数据记录⽂件的每个存储块设⼀个键-指针对,存储块意味着块内存储单元连续
(三)案例
1、Mysql的MyISAM引擎⾥⾯, 使⽤均为稀疏索引;
2、Mysql的Innodb引擎⾥⾯,如果有主键,则主键为密集索引
3、Kafka⾥⾯的索引⽂件也是采⽤稀疏索引进⾏构造消息索引
4、ClickHouse的合并树MergeTree引擎是稀疏索引,默认index_granularity设置8192,新版本的提供了⾃适应粒度⼤⼩的特性
(四)总结
1、ClickHouse⼀级索引就是【稀疏索引】,可以⼤幅减少索引占⽤的空间
(1)默认的索引⼒度8192,假如1亿⾏数据只需要存储12208⾏索引,占⽤空间⼩,clickhouse中⼀级索引的数据是常驻内存的,取⽤速度极快
(2)稀疏索引所占空间⼩,并且插⼊和删除时所需维护的开销也⼩,缺点是速度⽐密集索引慢⼀点
2、密集索引空间占⽤多,⽐稀疏索引更快的定位⼀条记录,缺点就是会占⽤较多的空间
3、不变思想:时间换空间、空间换时间
二、Kafka之间副本数据同步是怎样的?⼀致性怎么保证,数据怎样保证不丢失呢
回答
(一)kafka的副本(replica)
1、topic可以设置有N个副本, 副本数最好要⼩于broker的数量
2、每个分区有1个leader和0到多个follower,我们把多个replica分为Learder replica和follower replica
(二)⽣产者发送数据流程
1、保证producer 发送到指定的 topic, topic 的每个 partition收到producer 发送的数据后
2、需要向 producer 发送 ack 确认收到,如果producer 收到ack, 就会进⾏下⼀轮的发送否则重新发送数据
(三)副本数据同步机制
1、当producer在向partition中写数据时,根据ack机制,默认ack=1,只会向leader中写⼊数据
2、然后leader中的数据会复制到其他的replica中,follower会周期性的从leader中pull数据,
3、对于数据的读写操作都在leader replica中,follower副本只是当leader副本挂了后才重新选取leader,follower并不向外提供服务,假如还没同步完成,leader副本就宕机了,怎么办?
(四)当producer向leader发送数据时,可以通过request.required.acks参数来设置数据可靠性的级别
1、副本数据同步策略 , ack有3个可选值,分别是0, 1,all。
①ack=0
producer发送⼀次就不再发送了,不管是否发送成功
发送出去的消息还在半路,或者还没写⼊磁盘,Partition Leader所在Broker就直接挂了,客户端认为消息发送成功了,此时就会导致这条消息就丢失
②ack=1(默认)
只要Partition Leader接收到消息⽽且写⼊【本地磁盘】,就认为成功了,不管他其他的Follower有没有同步过去这条消息了
问题:万⼀Partition Leader刚刚接收到消息,Follower还没来得及同步过去,结果Leader所在的broker宕机了
③ack= all(即-1)
producer只有收到分区内所有副本的成功写⼊全部落盘的通知才认为推送消息成功
备注:leader会维持⼀个与其保持同步的replica集合,该集合就是ISR,leader副本也在isr⾥⾯
问题⼀:如果在follower同步完成后,broker发送ack之前,leader发⽣故障,那么会造成数据重复
数据发送到leader后 ,部分ISR的副本同步,leader此时挂掉。⽐如follower1和follower2都有可能变成新的leader, producer端会得到返回异常,producer端会重新发送数据,数据可能会重复
问题⼆:acks=all 就可以代表数据⼀定不会丢失了吗
Partition只有⼀个副本,也就是⼀个Leader,任何Follower都没有
接收完消息后宕机,也会导致数据丢失,acks=all,必须跟ISR列表⾥⾄少有2个以上的副本配合使⽤
在设置request.required.acks=-1的同时,也要min.insync.replicas这个参数设定 ISR中的最⼩副本数是多少,默认值为1,改为 >=2,如果ISR中的副本数少于min.insync.replicas配置的数量时,客户端会返回异常
三、说下Mysql数据库垂直、⽔平分表,垂直分库、⽔平分库的区别
回答
(一)垂直分表介绍
1、也就是“⼤表拆⼩表”,基于列字段进⾏的
2、拆分原则⼀般是表中的字段较多,将不常⽤的或者数据较⼤,⻓度较⻓的拆分到“扩展表 如text类型字段
3、访问频次低、字段⼤的商品描述信息单独存放在⼀张表中,访问频次较⾼的商品基本信息单独放在⼀张表中
4、垂直拆分原则
(1)把不常⽤的字段单独放在⼀张表;
(2)把text,blob等⼤字段拆分出来放在附表中;
(3)业务经常组合查询的列放在⼀张表中
(二)垂直分库讲解
1、垂直分库针对的是⼀个系统中的不同业务进⾏拆分, 数据库的连接资源⽐较宝贵且单机处理能⼒也有限
2、没拆分之前全部都是落到单⼀的库上的,单库处理能⼒成为瓶颈,还有磁盘空间,内存,tps等限制
3、拆分之后,避免不同库竞争同⼀个物理机的CPU、内存、⽹络IO、磁盘,所以在⾼并发场景下,垂直分库⼀定程度上能够突破IO、连接数及单机硬件资源的瓶颈
4、垂直分库可以更好解决业务层⾯的耦合,业务清晰,且⽅便管理和维护
5、⼀般从单体项⽬升级改造为微服务项⽬,就是垂直分库
(三)⽔平分表
1、把⼀个表的数据分到⼀个数据库的多张表中,每个表只有这个表的部分数据
2、核⼼是把⼀个⼤表,分割N个⼩表,每个表的结构是⼀样的,数据不⼀样,全部表的数据合起来就是全部数据
3、针对数据量巨⼤的单张表(⽐如订单表),按照某种规则(RANGE,HASH取模等),切分到多张表⾥⾯去
4、但是这些表还是在同⼀个库中,所以单数据库操作还是有IO瓶颈,主要是解决单表数据量过⼤的问题
5、减少锁表时间,没分表前,如果是DDL(create/alter/add等)语句,当需要添加⼀列的时候mysql会锁表,期间所有的读写操作只能等待
(四)⽔平分库
1、把同个表的数据按照⼀定规则分到不同的数据库中,数据库在不同的服务器上
2、⽔平分库是把不同表拆到不同数据库中,它是对数据⾏的拆分,不影响表结构
3、每个库的结构都⼀样,但每个库的数据都不⼀样,没有交集,所有库的并集就是全量数据
4、⽔平分库的粒度,⽐⽔平分表更⼤