Java面试通关要点汇总集之核心篇参考答案
核心篇
数据存储
MySQL 索引使用的注意事项
1.索引不会包含有NULL的列
说说反模式设计
简单的来说,反模式是指在对经常面对的问题经常使用的低效,不良,或者有待优化的设计模式/方法。甚至,反模式也可以是一种错误的开发思想/理念。在这里我举一个最简单的例子:在面向对象设计/编程中,有一条很重要的原则, 单一责任原则(Single responsibility principle)。其中心思想就是对于一个模块,或者一个类来说,这个模块或者这个类应该只对系统/软件的一个功能负责,而且该责任应该被该类完全封装起来。当开发人员需要修改系统的某个功能,这个模块/类是最主要的修改地方。相对应的一个反模式就是上帝类(God Class),通常来说,这个类里面控制了很多其他的类,同时也依赖其他很多类。整个类不光负责自己的主要单一功能,而且还负责了其他很多功能,包括一些辅助功能。很多维护老程序的开发人员们可能都遇过这种类,一个类里有几千行的代码,有很多功能,但是责任不明确单一。单元测试程序也变复杂无比。维护/修改这个类的时间要远远超出其他类的时间。很多时候,形成这种情况并不是开发人员故意的。很多情况下主要是由于随着系统的年限,需求的变化,项目的资源压力,项目组人员流动,系统结构的变化而导致某些原先小型的,符合单一原则类慢慢的变的臃肿起来。最后当这个类变成了维护的噩梦(特别是原先熟悉的开发人员离职后),重构该类就变成了一个不容易的工程。
说说分库与分表设计
垂直分表在日常开发和设计中比较常见,通俗的说法叫做“大表拆小表”,拆分是基于关系型数据库中的“列”(字段)进行的。通常情况,某个表中的字段比较多,可以新建立一张“扩展表”,将不经常使用或者长度较大的字段拆分出去放到“扩展表”中。在字段很多的情况下,拆分开确实更便于开发和维护(笔者曾见过某个遗留系统中,一个大表中包含100多列的)。某种意义上也能避免“跨页”的问题(MySQL、MSSQL底层都是通过“数据页”来存储的,“跨页”问题可能会造成额外的性能开销,拆分字段的操作建议在数据库设计阶段就做好。如果是在发展过程中拆分,则需要改写以前的查询语句,会额外带来一定的成本和风险,建议谨慎。
分库与分表带来的分布式困境与应对之策
数据迁移与扩容问题
说说 SQL 优化之道
一、一些常见的SQL实践res = mysql_query(
MySQL 遇到的死锁问题
产生死锁的四个必要条件:
存储引擎的 InnoDB 与 MyISAM
◆1.InnoDB不支持FULLTEXT类型的索引。) from table时,InnoDB要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。注意的是,当count()语句包含 where条件时,两种表的操作是一样的。
数据库索引的原理
数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B树及其变种B+树。
为什么要用 B-tree
一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。这样的话,索引查找过程中就要产生磁盘I/O消耗,相对于内存存取,I/O存取的消耗要高几个数量级,所以评价一个数据结构作为索引的优劣最重要的指标就是在查找过程中磁盘I/O操作次数的渐进复杂度。换句话说,索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数。
聚集索引与非聚集索引的区别
1).聚集索引一个表只能有一个,而非聚集索引一个表可以存在多个
limit 20000 加载很慢怎么解决
mysql的性能低是因为数据库要去扫描N+M条记录,然后又要放弃之前N条记录,开销很大
选择合适的分布式主键方案
数据库自增长序列或字段
UUID
使用UUID to Int64的方法
Redis生成ID
Twitter的snowflake算法
利用zookeeper生成唯一ID
MongoDB的ObjectId
选择合适的数据存储方案
关系型数据库 MySQL
ObjectId 规则
[0,1,2,3] [4,5,6] [7,8] [9,10,11]
聊聊 MongoDB 使用场景
高伸缩性的场景
倒排索引
倒排索引(英语:Inverted index),也常被称为反向索引、置入档案或反向档案,是一种索引方法,被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射。它是文档检索系统中最常用的数据结构。
聊聊 ElasticSearch 使用场景
全文搜索,这个是用的最多的。加上分词插件、拼音插件什么的可以做成强大的全文搜索引擎。
缓存使用
Redis 有哪些类型
在Redis中有五种数据类型
Redis 内部结构
Redis 内部使用一个 redisObject 对象来表示所有的 key 和 value。type :代表一个 value 对象具体是何种数据类型。
聊聊 Redis 使用场景
缓存
会话缓存
时效性
访问频率
计数器
社交列表
记录用户判定信息
交集、并集和差集
热门列表与排行榜
最新动态
消息队列
Redis 持久化机制
redis有两种持久化机制RDB与AOF。
Redis 如何实现持久化
RDB持久化方式会在一个特定的间隔保存那个时间点的一个数据快照。
Redis 集群方案与实现
客户端分片
路由查询
Redis 为什么是单线程的
因为CPU不是Redis的瓶颈。Redis的瓶颈最有可能是机器内存或者网络带宽。(以上主要来自官方FAQ)既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了。
缓存奔溃
碰到这种情况,一般并发量不是特别多的时候,使用最多的解决方案是加锁排队。
加锁排队只是为了减轻数据库的压力,并没有提高系统吞吐量。假设在高并发下,缓存重建期间key是锁着的,这是过来1000个请求999个都在阻塞的。同样会导致用户等待超时,这是个治标不治本的方法。
缓存降级
页面降级:在大促或者某些特殊情况下,某些页面占用了一些稀缺服务资源,在紧急情况下可以对其整个降级,以达到丢卒保帅;
使用缓存的合理性问题
热点数据,缓存才有价值
频繁修改的数据,看情况考虑使用缓存
数据不一致性
缓存更新机制
缓存可用性
缓存服务降级
缓存预热
缓存穿透
消息队列
消息队列的使用场景
校验用户名等信息,如果没问题会在数据库中添加一个用户记录
消息的重发补偿解决思路
可靠消息服务定时查询状态为已发送并超时的消息
消息的幂等性解决思路
查询操作
删除操作
token机制,防止页面重复提交
悲观锁
乐观锁
分布式锁
select + insert
状态机幂等
对外提供接口的api如何保证幂等
消息的堆积解决思路
如果还没开始投入使用kafka,那应该在设计分区数的时候,尽量设置的多点(当然也不要太大,太大影响延迟,具体可以参考我前面提到的文章),从而提升生产和消费的并行度,避免消费太慢导致消费堆积。
自己如何实现消息队列
大体上的设计是由一条线程1执行从等待列表中获取任务插入任务队列再由线程池中的线程从任务队列中取出任务去执行.
如何保证消息的有序性
通过轮询所有队列的方式来确定消息被发送到哪一个队列(负载均衡策略)。订单号相同的消息会被先后发送到同一个队列中,
后期更多猛料放出,关注 Felordcn 公众号关注实时动态。