1 实习
1.1 讲解一下curd启动器
1.2 数据同步的过程是怎么实现的,同步过程中的数据一致性怎么保证的
答:同步过程中会记录断点,表示每一批同步成功时的位置,如果对端出现问题,则下一次同步会继续从这个断点后开始同步。
1.3 当对端出现故障时,线程会抛异常然后被捕获并且记录,那么这个库的同步不就相当于终止了吗,而且这个异常线程也会消失,你怎么让他同步完整的表(重要)
答:一般对于同步过程中出现异常的,我们都会进行记录,并且记录异常原因,稍后会通过人工会根据捕获的异常修复漏洞,然后点击按钮进行一次基于库或者表级别的同步,这个过程也是基于上次的断点同步的
1.4 线程怎么感知到已经同步完一张表了呢
答:通过比较源端表和目的端表的记录行数,就可以确定最终是否同步完成
1.5 你是需要从公司的数据库拉一批数据到内存中,然后再同步到对端的数据库,你是怎么知道这一批执行成功的呢,有什么通知机制吗?
答:我使用的是jdbc原生接口,每一次拉取到一批数据的时候,就会执行一次executeBatch方法,然后会在进行commit操作,这个接口本身有返回值,如果能继续同步下一批,就说明同步成功,如果失败会抛异常,也会被捕获
2 mysql
2.1 设计mysql表结构的时候,需要考虑到哪些点
答:
(2)按需建立多种索引
(4)对于分布式环境,尽量做到一个服务对应一个独立的库,做一个流量的隔离
设计数据库表时需要考虑的因素相当多,这些因素会影响数据的组织、检索、更新、维护以及整体的性能和扩展性。以下是一些在设计表时应考虑的主要因素:
- 物理存储:
- 冗余和反规范化:
当设计表时,建议首先深入了解业务需求,以确保数据模型能够满足业务的长期和短期需求。
2.2 覆盖索引
2.3 场景题:在上亿条记录的表中使用limit做分页查询时会碰到什么问题,怎么解决(重点)
答:刚开始我说即使上亿条记录,mysql的B+树最多5层也能搞定吧,其实这个磁盘IO应该能扛得住吧,但是面试官说他们公司的极限是3次磁盘IO
2.3.1 在拥有上亿条记录的表中使用 LIMIT
进行分页查询时,可能会遇到以下问题:
2.3.2 如何解决这些问题?
通过考虑上述方法并根据具体的应用和需求选择合适的方法,可以有效地解决在大数据集上使用 LIMIT
进行分页查询的问题。
2.3.3 对于大表,使用 LIMIT 进行深度分页可能会消耗大量的内存,因为数据库需要缓存大量的行来处理这样的查询。举个例子
深度分页的例子: 假设你有一个包含1亿条记录的大表。你想从这张表中获取第9999901到第10000000条的记录。当你执行以下查询时:
sqlCopy codeSELECT * FROM your_big_table ORDER BY some_column LIMIT 9999900, 100;
实际上,MySQL会扫描前9999900条记录,丢弃它们,然后返回接下来的100条记录。这意味着数据库实际上要处理近1000万行记录,只为了返回100行结果,这自然会消耗大量的时间和内存。
2.3.4 与其使用 `LIMIT m,n`,不如记录上一页的最后一个记录的ID或其他标识,然后查询“大于此ID”的下一页记录。这种方法被称为游标或seek方法。 给个java的demo,使用游标时,sql语句怎么写呢?
当我们使用游标或seek方法进行分页时,我们不再使用传统的 OFFSET
和 LIMIT
。取而代之的是,我们根据上一页的最后一个记录的标识(通常是一个递增的ID)来查询下一页的数据。
以下是一个简单的Java示例,使用JDBC和MySQL数据库:
String url = "jdbc:mysql://localhost:3306/your_database";
String user = "username";
String password = "password";
2. 执行分页查询:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class SeekPaginationDemo {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/your_database";
String user = "username";
String password = "password";
int pageSize = 10; // 每页的记录数
int lastId = 0; // 上一页的最后一个记录的ID
try (Connection connection = DriverManager.getConnection(url, user, password)) {
String sql = "SELECT * FROM your_table WHERE id > ? ORDER BY id ASC LIMIT ?";
try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
preparedStatement.setInt(1, lastId);
preparedStatement.setInt(2, pageSize);
try (ResultSet resultSet = preparedStatement.executeQuery()) {
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
// ... 其他列 ...
System.out.println("ID: " + id + ", Name: " + name);
// 更新lastId为当前记录的ID
lastId = id;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
这个示例展示了如何基于上一页的最后一个记录的ID来获取下一页的数据。当你需要获取下一页面时,只需再次运行上述代码,并使用更新后的 lastId
。
2.3.5 游标是一种可滚动的结果集,可以在不返回所有数据的情况下进行分页查询。使用游标分页可以避免对整个表进行扫描,从而提高查询效率。MySQL支持使用游标进行分页查询,但需要注意内存消耗和网络传输的问题。 使用游标分页可以避免对整个表进行扫描,为什么?
使用游标分页(又称为”seek method“或基于keyset的分页)时,你是基于上一页的某个值(通常是主键或唯一键)来查询下一页的数据,而不是基于固定的偏移量。由于数据库可以利用索引(例如,B树)来快速定位到指定的起始值,所以不需要逻辑地扫描那些之前的记录。
举一个简单的例子:
假设你有一个ID为1到1000的表。你想要获取从第501条到第510条的数据。
-
使用传统的
LIMIT
和OFFSET
方式:SELECT * FROM table LIMIT 500, 10
。在这种情况下,数据库虽然只返回了10条记录,但在逻辑上它仍然要处理前500条记录,尽管这些记录最终并没有被返回。 -
使用游标方式:如果你知道上一页的最后一个ID是500,你可以这样查询:
SELECT * FROM table WHERE id > 500 ORDER BY id LIMIT 10
。这时,数据库可以利用ID的索引直接跳到ID为500的位置并开始查询,避免了处理那些之前的记录。
因此,当你使用游标分页时,可以更高效地从索引中查找和检索数据,而不必扫描那些之前的、不必要的记录。这对于大型数据集尤为有用,因为使用传统的LIMIT
和OFFSET
可能会导致随着页码增大而逐渐变慢。
2.3.6 使用游标方式:如果你知道上一页的最后一个ID是500,你可以这样查询:SELECT * FROM table WHERE id > 500 ORDER BY id LIMIT 10。这时,数据库可以利用ID的索引直接跳到ID为500的位置并开始查询,避免了处理那些之前的记录。 1 这样的话是不是说,可以先利用id的主键索引,以logn的复杂度查找出目标记录,然后再在目标记录中按照limit10进行筛选,如果是单纯的使用limit字段,就不会走索引,会从第一条记录开始扫描到第500条,对吗
-
当你使用条件
WHERE id > 500
并且id
列有索引(通常作为主键或唯一键),数据库会利用这个索引在B-Tree结构中以O(logn)的复杂度快速定位到ID为500的记录位置。 -
一旦找到起始位置,数据库可以从那里开始检索并按照
ORDER BY
和LIMIT
进行排序和限制记录数。这个过程相对较快,因为它避免了逻辑上扫描那些不相关的记录。 -
对于传统的
LIMIT
和OFFSET
方法,如果没有其他的WHERE
条件,那么数据库实际上要逻辑地扫描到指定的偏移位置。例如,LIMIT 500, 10
实际上需要数据库逻辑地处理前500条记录,然后返回接下来的10条。这在大数据集上会导致性能问题,因为随着页数的增加,需要扫描的记录数也在增加。
因此,使用基于游标或keyset的分页方法通常在大数据集上更加高效。
2.3.7 SELECT * FROM table order by id LIMIT 500, 10 这种也是会扫描前500吗?
是的,当你使用SELECT * FROM table ORDER BY id LIMIT 500, 10
这样的查询,它首先会根据ORDER BY
条件对数据进行排序(如果使用了索引,如主键索引,那么排序操作会更快),然后跳过前500条记录,最后返回接下来的10条记录。
在这种情况下,虽然排序操作可能很快(尤其是当排序字段有索引时),但跳过前500条记录是需要时间的,特别是当这个数字(在这里是500)变得很大时,这种分页方式的性能开销会增加。这就是为什么当数据集非常大时,使用OFFSET
方式的分页可能会导致性能问题,而基于游标或keyset的分页方法在这种场景下会更优越。
2.3.8 SQL游标(Cursor in SQL)和 游标方式分页(Keyset or Cursor-based Pagination)的区别
在你提供的知乎链接中描述的游标与我之前提到的”游标”概念存在明显的区别。下面,我将为你详细解释这两者之间的主要区别:
-
SQL游标(Cursor in SQL):
总之,两者的主要区别是:SQL游标是数据库中的一个高级结构,用于逐行处理查询结果;而游标方式分页是一个高效的数据检索策略,特别是在大数据集上。
2.4 评估一张表的存储空间,一般是怎么计算的,包括内存和磁盘,假设金山的用户量为2亿,每一个人半年产生一次订单,然后需要多少个这样的数据库去存储呢?
答:
我的计算过程:
2.4.1 计算字段数
以订单表为例,首先得包含这么几个字段,以下是大概15个字段,
order_id:订单的唯一标识符。通常是一个自增的整数或者一个UUID。
customer_id:与下订单的客户关联的唯一标识符。
order_date:订单创建的日期和时间。
shipping_address:送货地址。
billing_address:账单地址。
total_amount:订单的总金额。
tax_amount:应付的税额。
shipping_cost:运输费用。
order_status:订单的状态,例如'待处理'、'已发货'、'已完成'、'已取消'等。
payment_method:支付方式,如'信用卡'、'PayPal'、'货到付款'等。
payment_status:支付状态,如'未支付'、'已支付'、'部分支付'等。
shipping_method:送货方式,如'标准'、'快递'、'自提'等。
expected_delivery_date:预期的送货日期。
actual_delivery_date:实际的送货日期。
notes:关于订单的任何其他说明或注释。
created_at 和 updated_at:记录创建和最后更新的时间戳。
2.4.2 计算一条记录占用的空间
为了估算订单表的一条记录大概会占用多少字节,我们需要考虑每个字段的数据类型和所占的字节。以下是一个简化的估算,基于您前面提到的订单表字段:
- order_id: 假设为INT,占用4字节。
- customer_id: 假设为INT,占用4字节。
- order_date: 假设为DATETIME,占用8字节。
- shipping_address: 假设为VARCHAR(255),占用的实际字节数取决于实际内容,但最大为255字节。
- billing_address: 同上,最大255字节。
- total_amount: 假设为DECIMAL(10,2),占用14字节。
- tax_amount: 假设为DECIMAL(10,2),占用14字节。
- shipping_cost: 假设为DECIMAL(10,2),占用14字节。
- order_status: 假设为VARCHAR(50),最大50字节。
- payment_method: 假设为VARCHAR(50),最大50字节。
- payment_status: 假设为VARCHAR(50),最大50字节。
- shipping_method: 假设为VARCHAR(50),最大50字节。
- expected_delivery_date: 假设为DATE,占用3字节。
- actual_delivery_date: 假设为DATE,占用3字节。
- notes: 假设为TEXT,实际占用的字节取决于内容,但假设平均长度为100字节。
- created_at: 假设为DATETIME,占用8字节。
- updated_at: 假设为DATETIME,占用8字节。
假设每个VARCHAR字段平均使用其长度的一半,那么总的字节数为:
只考虑字段:4 + 4 + 8 + 127.5 + 127.5 + 14 + 14 + 14 + 25 + 25 + 25 + 25 + 3 + 3 + 100 + 8 + 8 = 624字节
考虑到荣誉以及索引、锁记录等的开销:624+
这个估算是基于上述字段的数据类型和假设,实际的值可能会有所不同。除了字段的存储,还需要考虑其他的开销,如记录的元数据、索引、行的开销等。所以,真实环境中,一条记录可能会占用稍微多一点的空间。
2.4.3 除了字段的存储,还需要考虑其他的开销,如记录的元数据、索引、行的开销等,大概也估算一下
除了字段本身的存储空间,一条数据库记录的实际存储空间通常会受到以下几个方面的影响:
-
行开销:每行数据都会有一些额外的字节作为开销,这与特定的数据库系统有关。例如,在MySQL的InnoDB存储引擎中,每行有一些固定的开销。
-
索引:如果表中的某个字段被索引,那么索引本身也会消耗存储空间。索引的大小取决于索引的类型、被索引字段的大小、数据的独特性等。每种索引(如B-tree,哈希,R-tree等)都有自己的空间要求。
是否为NULL,那么对于上述的17个字段,这将是2.125字节。
4. 索引:索引的大小非常依赖于数据和所使用的索引类型。作为一个简化的估计,假设我们为order_id
和customer_id
创建了两个B-tree索引。B-tree索引的大小主要取决于键的大小、树的深度和填充因子。假设每个索引条目占用20字节(键的大小+指针),对于100,000条记录的表,索引大小约为2MB。如果我们按记录计算,那么每条记录为这两个索引贡献了约20字节。
将上述所有因素加起来:
合计:657.125字节
这只是一个大致估算,实际存储需求可能会有所不同,取决于数据、数据库管理系统的具体实现、索引的具体结构和其他因素。
2.4.4 总量计算:一年产生的订单数 * 一条记录占用的空间大小
金山两亿用户,一年产生的订单量可以达到4亿,那么需要的总的磁盘空间为
4 * 10^9 *650B*1.2 = 4*780* 10^9 =3120G=3.12T
gpt4给的评估方法:
评估一张表的存储空间不是一个绝对精确的计算,因为还涉及到很多因素,如数据库管理系统的内部实现、行溢出、索引的空间等。但以下是一个基本的方法来估算一张表的存储需求:
这只是一个基本的估算方法。如果你需要更精确的估算,可能需要考虑使用特定于数据库的工具或命令。例如,在MySQL中,你可以使用SHOW TABLE STATUS
命令来查看表的实际大小。
2.4.5 磁盘使用数量
2.5 秒杀系统中订单的唯一性怎么解决
秒杀场景中订单的唯一性是非常重要的,为了避免同一商品被重复秒杀,通常采用以下策略来确保唯一性:
2.6 设计一个高并发的分布式id生成器(场景设计题)
设计一个高并发的分布式ID生成器需要确保ID的唯一性、连续性(可选)和高效性。以下是几种常用的方法:
-
UUID:
-
结合多种策略:
总之,选择哪种ID生成策略取决于具体的应用场景和需求,如是否需要ID连续、是否需要全局唯一、生成的ID长度等。
3 消息队列
3.1 为什么使用kafka而不是rabbitMQ呢
答:
(1)性能瓶颈
4 redis
4.1 redis做分布式锁怎么实现的
答:
4.2 redission分布式锁具体是怎么实现的
5 rpc框架
5.1 你实现rpc的思路是怎么样的,怎么做任务拆减(其实就是在问rpc框架的组成部分)
实现一个RPC框架通常是一个复杂的工作,需要考虑网络通信、序列化/反序列化、服务发现、负载均衡等多个方面。以下是一个基本的实现思路和任务拆解方法:
任务拆解:
5.2 假设我要现在写了一个服务,要对接你的这个rpc框架,得注意些什么呢
当你要将你的服务接入到一个RPC框架时,通常需要注意以下几点:
最后,建议详细阅读RPC框架的官方文档和最佳实践,以确保服务的稳定性和高效性。
5.3 你推荐用哪一种序列化协议
单一语言系统内使用kryo,最快,跨语言系统,比如硬件系统和java系统交互,使用protocol buffer
5.4 讲讲protobuff的向前和向后兼容性
调用方收到了新的数据结构版本时,会忽略新增的字段,实现向前兼容
当调用方收到了旧版本数据结构的响应时,新增的字段会使用默认值填充,从而不会报错
6 反问
6.1 讲讲你们部门的业务
答:我们不涉及到具体的客户端文档格式,我们部门主要的业务是云文档的上传,下载和共享编写,最复杂的是文档的规模,现在已经到达2000亿级别,刚刚跟你聊到的数据库的高可用,分库分表等技术都涉及到数据规模庞大的优化问题
6.2 您这个部门的人数
答:围绕云文档的人数大概有100号人,在线预览,缩略图,文件系统之类的
6.3 是用go吗
答:百分之95的人都是用go
6.4 表现如何
6.5 base有限制吗
答:一般是先去武汉做一个集中几个月的培训,然后会按照意愿分配
原文地址:https://blog.csdn.net/yxg520s/article/details/134751870
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_26368.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!