1. 关于池化技术,以下说法错误的是:
A. 使用线程池应该关注队列中,数据的堆积情况
B. 线程池中应该使用无界队列尽量降低任务丢弃的概率
C. 对于任何类型的系统,我们都可以使用原生的 Java 线程池,来提升任务执行的并发度
D. 可以定时地校验数据库连接池中的连接可用情况
答案: BC
解析: Java 线程池中,会使用队列来暂存任务,如果任务被长时间堆积,会造成任务消费延迟的问题,所以 A 是正确的。数据库的连接可能会被数据库服务端关闭,所以可以配置连接池定期地轮询检测数据库连接池的状态,避免使用失效的连接,造成请求失败的情况,所以 D 也是正确的;在使用线程池时,我们尽量不用要使用无界队列,因为一旦任务执行缓慢,就会造成任务大量堆积,占据大量内存资源,也会造成频繁 Full GC,影响系统可用性,所以 B 是错误的;原生的 Java 线程池适用于处理 CPU 密集型的任务,而我们的系统中的任务,大部分是 I/O 密集型的,所以最好对 Java 原生的线程池做一些改造来使用,所以 C 也是错误的。
2. 以下那种场景不适合使用缓存?
A. 社区系统中查询用户信息
B. 电商系统中查询商品信息
C. 社区系统中搜索社区内容信息
D. 网站中查看图片和视频信息
答案: C
解析:缓存比较适合读多写少的业务场景,并且数据最好带有一定的热点属性。因为缓存了热点的数据,才能保证一定的缓存命中率。而在搜索内容的场景下,每个人搜索的关键词各有不同,所以,如果以关键词为缓存的 Key,缓存的命中率不会很高,所以 C 是不适合使用缓存的。
3. 以下哪种场景可能造成读出数据的错误?
A. 数据写入主库,读取从库
B. 新数据在写入数据库的同时也写入缓存,读取时,优先从缓存读取数据
C. 更新数据库中的数据之后,也更新缓存中的数据
D. 更新数据库中的数据之后,让缓存中的数据过期
答案: AC
解析:主从之间存在延迟,所以写入主库后立刻读取从库,可能会造成读取到已经过期的数据。而如果在写入新的数据的同时,也写入到缓存,那么就可以避免主从延迟的影响。另外,更新数据库的同时更新缓存,会存在并发的问题,造成数据库和缓存中的数据不一致,而如果在更新数据库的同时,删除缓存中的数据,或者让缓存中的数据过期,就会避免这种情况发生。
4. 以下关于一致性 Hash 算法的说法,错误的是:
A. 一致性 Hash 算法可以避免缓存穿透的发生
B. 一致性 Hash 算法可以减少缓存节点数量变化,导致的数据访问抖动
C. 在缓存节点发生故障时,可以通过增加虚拟节点的方式,将请求尽量平均分配到其它节点上
D. 一致性 Hash 算法可能会产生脏数据
答案: A
解析:一致性 Hash 算法并不能够避免缓存穿透的发生,这是一个常见的误区。即使使用了一致性 Hash 算法,当节点故障时,原本应该被这个节点承担的请求,虽然会被分配到其它节点,但由于其它节点上并没有缓存数据,所以还是会穿透到数据库中查询。一致性 Hash 算法解决的核心问题是,尽量减少增加和删除节点对于读取缓存数据的影响。
5. 以下哪些场景不适合于使用 NoSQL 数据库:
A. 在一个社区系统中搜索社区中的用户
B. 支付之类的强事务场景
C. 存储电商用户的未读消息数量
D. 存储电商系统中的商品信息
答案: B
解析: NoSQL 数据库一般不支持事务,并且对于一些复杂的 SQL 查询支持程度不高。它的优势是提供更好的读写性能,提升扩展性,以及弥补传统数据库不适合的场景,比如选项 A 中的搜索。选项 D 中提到的商品信息,一般来说,会有非常多的字段,并且不同商品的字段有可能不同,所以适合使用 MongoDB 之类的 NoSQL 来存储。
6. 关于分表策略的选择,以下哪一种是不正确的?
A. 在通过创建时间,查询用户内容列表的场景下,按照创建时间做区间拆分存储列表数据
B. 查询一个人内容列表场景下,用户内容列表数据,按照用户 ID 做 Hash 拆分存储,内容实体数据,按照内容 ID 做 Hash 拆分存储
C. 查询一条内容下的图片信息,按照图片的 ID 做 Hash 拆分存储图片信息
D. 按照昵称查询用户,按照昵称 Hash 拆分存储昵称, 和 ID 之间的关系,再按照用户 ID 做 Hash 拆分存储用户信息
答案: C
解析: 分库分表的拆分应该按照常用查询语句,来决定分区键是什么。选项 C 中的场景是查询图片信息时需要按照内容 ID 来查询,所以拆分的时候也应该按照内容 ID 做 Hash 拆分,这样每次查询图片信息的时候,都需要带上内容 ID 了。
7. 下面解决缓存穿透的方法,哪一种说法是不对的?
A. 大量地请求不存在的用户信息,在这种场景下,可以使用回种空值的方式来解决
B. 使用布隆过滤器时,可以使用多个 Hash 函数,来减少 Hash 冲突的几率
C. 可以通过增加分布式锁的方式,减少缓存穿透造成的,大量请求到数据库的情况
D. 缓存穿透的问题也要结合缓存的原理来分析,比如 Memcached 的 Slab Class 满了,Memcached 会剔除数据,也会造成缓存的穿透
答案: A
解析:回种空值的方式需要占用一定的存储空间,所以采用这种方式时,需要考虑存储的成本,如果是大量的不存在用户的请求,那么推荐使用布隆过滤器的方式,来减少内存空间的占用。
8. 下面关于消息丢失的说法,哪种是错误的?
A. 可以通过配置服务集群的方式,来解决消息丢失的问题
B. 可以在接收到消息后,自动更新消费进度,然后再执行消费处理逻辑
C. 可以配置同步刷盘的方式,减少消息丢失的可能
D. 可以重复发送消息,来减少消息丢失的可能
答案: BC
解析:如果自动更新了消费进度,那么如果在消息处理时,出现了异常,这条消息就会丢失了,所以 B 选项是错误;C 选项中提到的同步刷盘,会极大地影响消息队列写入的性能,所以不建议开启。
9. 关于降低消息延迟的方式,哪种说法是错误的?
A. 你可以增加消费者的数量,来提升存储在 Kafka 中的消息的消费性能
B. 你可以在消费端启动多个线程,来提升消息的消费性能
C. 在存储上使用 Page Cache 异步刷盘,提升写入的性能
D. 使用零拷贝技术,减少数据拷贝的次数,提升消息队列的性能
答案: A
解析: Kafka 中,一个 Partition 中的数据,只能被一个消费者所消费,所以增加消费者的数量而不增加 Partition 的数量是不能够提升消费的并行度的,也就不能提升消费的性能。
10. 下面提升系统性能的说法,哪一种是错误的?
A. 数据库分库分表可以减少单表的数据量,能有效地提升数据的查询性能
B. 可以使用本地缓存来提升热点数据的读取性能,本地缓存越大,容纳的热点数据越多,所以应该尽量增加本地缓存的大小
C. CDN 可以让用户就近访问静态资源,避免跨地域的获取资源,对性能的提升比较明显
D. 数据在缓存中要分片存储,分片越多,并行度越高,性能越好
答案: BD
解析: 选项 B 中提到的本地缓存,确实可以提升极热点的读取性能,但是如果存储过多的数据到本地缓存中,会带来比较大的管理成本。同时,如果使用 JVM 来管理本地缓存,还会因为占用了过多的内存,造成垃圾回收暂停时间变长,可能对性能有负面影响,所以不建议本地缓存中放置过多数据。
选项 D 中,当缓存被分配到大量的节点上时,根据木桶原则,数据的读取性能取决于最慢、最坏的节点的情况,节点数过多,也会增加出问题的概率,所以一般一组缓存的节点数以 4 到 6 个节点为最佳。