哈喽~,大家好,我是千羽。
下面分享我认识的一位大佬华中科技大学985硕,美团一面,全是基础,可惜挂了。
美团一面(fail)
1、数据库的四种隔离级别
数据库的四种隔离级别如下:
- 读未提交(Read Uncommitted):这是最低级别的隔离,一个事务可以读取到另一个事务未提交的数据,可能会出现脏读、不可重复读和幻读等问题。
- 读已提交(Read Committed):一个事务只能读取到另一个事务已经提交的数据,避免了脏读问题,但仍可能出现不可重复读和幻读问题。
- 可重复读(Repeatable Read):一个事务在执行期间读取到的数据始终保持一致,不受其他事务的影响,避免了不可重复读问题,但仍可能出现幻读问题。
- 串行化(Serializable):这是最高级别的隔离,所有事务必须按顺序依次执行,避免了所有并发问题,但也牺牲了系统的并发性能。
2、MySql属于何种隔离级别
MySQL的默认隔离级别是可重复读(Repeatable Read)。
可重复读解决了脏读和不可重复读的问题,但是可能会出现幻读的问题。在这个隔离级别下,同一个事务内的多次读取结果是一致的,不同事务之间的读取结果互不干扰。
3、Redis和MySql不一致如何解决
- 使用Canal等中间件:Canal是阿里巴巴开源的一款基于数据库增量日志解析的数据同步工具,可以实现MySQL与Redis的数据实时同步。使用Canal可以降低代码耦合度,提高数据一致性。
- 分布式锁:在更新数据时,使用分布式锁保证同一时间只有一个操作在进行,从而避免数据不一致的问题。常见的分布式锁实现有Redlock、Zookeeper等。
- 数据校验:在数据写入和读取时进行数据校验,如使用CRC校验码等,以确保数据的完整性和一致性。
- 数据库与缓存双写策略:在更新数据时,同时写入数据库和缓存,确保两者数据一致。但这种方法可能增加系统复杂性和网络开销。
- 缓存失效机制:利用Redis的失效机制,设置缓存失效时间。当缓存失效时,从数据库中读取数据并重新设置缓存。这种方法可以减小对正常业务的影响,但需要接受一定的数据延迟。适用于读多写少的互联网环境。
- 定时任务更新:通过定时任务按照一定时间间隔更新Redis缓存。这种方法可以保证数据的定期同步,但不保证实时一致性,需要为每个任务编写调度代码。适用于对数据实时性要求不高的场景。
4、MySql主从分布不一致如何解决
MySQL主从分布不一致可以通过以下方法解决:
- 使用中间件:中间件可以有效地将主库和从库连接起来,实现数据的实时同步。常用的MySQL中间件包括Mycat、ProxySQL等。
- 调整MySQL参数:通过调整MySQL参数,如
sync_binlog
、read_only
等,可以增强数据的一致性和可靠性。 - 备份与恢复策略:制定合理的备份与恢复策略,确保在发生故障或数据不一致时,能够快速恢复数据到正常状态。
- 忽略错误,同步数据:适用于主从库数据相差不大,或者要求数据可以不完全统一的情况,数据要求不严格的情况。可以设置全局变量
sql_slave_skip_counter
跳过一步错误,之后再用mysql> show slave status/G
查看主从同步状态是否正常。 - 重新同步数据:如果主从分布差异较大,或者数据要求必须一致,可以重新同步数据。首先停止从库的服务,然后找到差异的数据进行修正或者删除,再重新进行主从配置,启动从库服务。
- 优化查询语句:查询语句是导致主从数据不一致的重要原因之一。通过优化查询语句,可以减少对数据库的访问次数,提高数据的一致性。
- 定期检查主从数据一致性:定期检查主从数据的差异程度,及时发现并处理不一致的数据。可以使用checksum命令来检查表结构的校验和,以帮助发现不一致的数据。
5、何时进行分库分表
一般单表到达几百万的时候,性能就会相对差一些,这时就得分表。分表是将一个表的数据放到多个表中,查询的时候只查一个表。例如,按照项目id来分表:将固定数量的项目数据放在一个表中,这样就可以控制每个表的数据量在可控的范围内。
分库则是将一个库的数据拆分到多个库中,每个库的表结构都一样,每个库的数据都不一样。所有库的并集是全量数据。
6、分库分表会遇到什么问题?
分库分表会遇到以下问题:
- 事务一致性问题:由于数据被分布到不同的数据库或服务器上,原有的单库事务就会失效。在不同的数据库实例完成同一个事务可能会失败,导致分布式事务问题。
- 跨节点关联查询:在进行分库分表后,原本逻辑关联性很强的数据会被划分到不同的表、不同的库上。这时,表的关联操作将受到限制,无法进行跨节点联表查询。为了解决这个问题,可以将原来的关联查询分为两次查询,第一次查询的结果集中找出关联数据id,然后根据id发起第二次请求得到关联数据。
- 跨节点分页、排序函数:在进行跨节点多库查询时,limit分页、order by排序问题会变得比较复杂。
- 公共表问题:在分库分表后,公共表就是业务中经常用的一些存储公共属性的表,比如参数表、数据字典表。这些表因为数据量和变化都不是很大,没必要进行再次的拆分。
- 数据管理负担和数据运算压力:分库分表后,每个数据库都需要进行数据管理,包括备份、恢复、优化等。这增加了数据管理的负担。同时,在进行跨节点查询、排序、分页等操作时,需要额外的数据运算压力。
7、冷数据变热redis如何处理
当冷数据变热时,Redis可以采取以下策略来处理:
- 缓存预热:在系统启动或数据更新后,预先将热门数据加载到Redis缓存中,以便快速响应请求。这可以通过定时任务、后台线程或手动触发的方式实现。
- 动态调整缓存策略:根据数据的访问频率和热度,动态调整Redis的缓存策略。例如,可以使用LFU(Least Frequently Used)或LRU(Least Recently Used)算法来淘汰不常用的冷数据,腾出空间存储热数据。
- 分级缓存:使用多级缓存策略,将热数据存储在更快、更小的缓存中,如Redis内存,而将冷数据存储在较慢、较大的缓存中,如磁盘或其他存储介质。这样可以平衡访问速度和存储成本。
- 冷热数据分离:将热数据和冷数据存储在不同的Redis实例或集群中,以便更好地管理和扩展。热数据可以使用高性能的Redis实例或集群,而冷数据可以使用成本较低的存储方案。
- 定期清理和维护:定期对Redis缓存进行清理和维护,删除过期和无用的冷数据,释放空间给热数据存储。这可以通过设置过期时间、使用Redis的内置命令或自定义脚本实现。
- 监控和调优:持续监控Redis的性能和数据访问模式,根据需要进行调优。例如,可以调整Redis的内存配置、网络参数、持久化策略等来提高性能和处理能力。
- 数据压缩:对于冷数据,可以使用压缩技术来减少存储空间和I/O开销。当数据被访问时,再实时解压并提供给请求方。
8、编程题:有序链表去重问题
思路:
- 遍历链表,比较当前节点的值与下一个节点的值是否相等。
- 如果相等,则继续向后遍历,直到找到一个不同的值或者到达链表的末尾。
- 如果当前节点与下一个节点的值不相等,则将当前节点加入到去重后的链表中。
- 重复步骤1-3,直到遍历完整个链表。
- 返回去重后的链表。
class ListNode {
int val;
ListNode next;
public ListNode(int val) {
this.val = val;
}
}
public class RemoveDuplicates {
public ListNode removeDuplicates(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode prev = dummy;
ListNode curr = head;
while (curr != null && curr.next != null) {
if (curr.val == curr.next.val) {
ListNode temp = curr.next;
while (temp != null && temp.val == curr.val) {
temp = temp.next;
}
prev.next = temp;
} else {
prev = prev.next;
}
curr = curr.next;
}
return dummy.next;
}
}
- 原文链接:https://github.com/warthecatalyst/What-to-in-Graduate-School/blob/main/秋招的面经/华科计科第二人的秋招报告.md