Java崗大廠面試百日沖刺【Day42】— 實戰那些事兒3 (日積月累,每日三題)

_陳哈哈 2021-09-20 01:01:44 阅读数:788

java 百日 day42 day 每日

大家好,我是陳哈哈,北漂五年。相信大家和我一樣,都有一個大廠夢,作為一名資深Java選手,深知面試重要性,接下來我准備用100天時間,基於Java崗面試中的高頻面試題,以每日3題的形式,帶你過一遍熱門面試題及恰如其分的解答。

一路走來,隨著問題加深,發現不會的也愈來愈多。但底氣著實足了不少,相信不少朋友和我一樣,日積月累才是最有效的學習方式!想起高三時一個同學的座右銘:只有沉下去,才能浮上來。共勉(juan)。

在這裏插入圖片描述

作者:雲野.



本欄目Java開發崗高頻面試題主要出自以下各技術棧:Java基礎知識集合容器並發編程JVMSpring全家桶MyBatis等ORMapping框架MySQL數據庫Redis緩存RabbitMQ消息隊列Linux操作技巧等。

面試題1:如果用mybatis批量插入數據時需要返回主鍵,你是怎麼做的?

需要在Mapper.xml的中標簽中配置useGeneratedKeyskeyProperty兩個屬性,就可以在批量插入時返回主鍵。

比如有個錶t_user,裏面有 user_id,user_name,sex 這三個字段,其中user_id是自增主鍵

下面是批量插入的Dao層接口:

List<String> insertUsers(@Param("list") List<UserInfo> users);

xml形式:

<insert id="insertUsers" useGeneratedKeys="true" keyProperty="user_id" resultType="String">
insert into t_user (user_name,sex)
values
<foreach collection="list" item="c" separator=",">
(#{c.user_name},#{c.sex})
</foreach>
</insert>

注解形式:

@Insert("<script>insert into t_user (user_name,sex) values " +
"<foreach collection='list' item='c' separator=','>(#{c.user_name},#{c.sex})</foreach></script>")
@Options(useGeneratedKeys = true, keyProperty = "user_id", resultType="String")
List<String> insertUsers(@Param("list") List<UserInfo> users);

注意:@Param裏和foreach的collection裏都需要寫成list, 其實是源碼中寫死了key為list,否則批量插入後會報錯說找不到"user_id"字段,而無法返回主鍵。

這種方式的前提是該錶主鍵有序自增,它的原理其實就是拿到當前錶中最大ID,然後結合影響行數來返回相應數據。但這就需要固定的insert場景,如果是insert ignore這種可能和實際影響行數不同的情况,就會出現不准確的情况。


在這裏插入圖片描述

課間休息,來秀一下來自咱們群裏同學搬磚工地附近的夜市。

作者:山一程雪一更


面試題2:在微服務中你是如何實現不同服務間session 共享的?

在微服務中,一個完整的項目被拆分成多個不相同的獨立的服務,各個服務獨立部署在不同的服務器上,各自的 session 被從物理空間上隔離開了,但是經常,我們需要在不同微服務之間共享 session

常見的方案就是 Spring Session + Redis 來實現 session 共享。將所有微服務的 session 統一保存在 Redis 上,當各個微服務對 session 有相關的讀寫操作時,都去操作 Redis 上的 session 。這樣就實現了session 共享,Spring Session 基於 Spring 中的代理過濾器實現,使得 session 的同步操作對開發人員而言是透明的,非常簡便。

同時,Spring Session已經集成了redis,可以很方便的將session存到redis中從而實現單點登陸/登出的效果,但是從微服務的角度來說,為了降低系統間的耦合度,一般會單獨建一個Redis服務來搞session共享。

1、pom 文件中引入以下包

<!--spring boot 與redis應用基本環境配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--spring session 與redis應用基本環境配置 -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>

2、application.properties配置好 redis

spring.redis.database = 0
spring.redis.host = 192.168.xx.xx
spring.redis.port = 6379
spring.redis.password = test
spring.redis.pool.max-active = 200
spring.redis.pool.max-wait = -1
spring.redis.pool.max-idle = 10
spring.redis.pool.min-idle = 0
spring.redis.pool.timeout = 1000

在需要共享 session 的服務的啟動類上,加上注解即可

@EnableRedisHttpSession
@SpringBootApplication(exclude= {
DataSourceAutoConfiguration.class})
public class PhoneApplication {

public static void main(String[] args) {

SpringApplication.run(PhoneApplication.class, args);
}
}

在這裏插入圖片描述

來了,CSDN的中秋禮品已到比特

作者:陳哈哈


面試題3:你了解分庫分錶麼?分庫分錶一般出現在哪些場景下?

  • 分庫:由單個數據庫實例拆分成多個數據庫實例,將數據分布到多個數據庫實例中。
  • 分錶:由單張錶拆分成多張錶,將數據劃分到多張錶內。

隨著業務數據量和網站QPS日益增高,對數據庫壓力也越來越大,單機版數據庫很快會到達存儲和並發瓶頸,就需要做數據庫性能方面的優化,分庫分錶采取的是分而治之的策略,分庫目的是减輕單臺MySQL實例存儲壓力及可擴展性,而分錶是解决單張錶數據過大以後查詢的瓶頸問題,坦白說,這些問題也是所有關系型數據庫的“硬傷”

常用策略包括:垂直分錶水平分錶垂直分庫水平分庫

一、樸實無華的 - 分錶
在這裏插入圖片描述

1、垂直分錶

垂直分錶,或者叫豎著切錶,是不是感受到該策略是以字段為依據的!主要按照字段的活躍性、字段長度,將錶中字段拆分到不同的錶(主錶和擴展錶)中。

特點:

  • 每個錶的結構都不一樣;
  • 每個錶的數據也不一樣,
  • 有一個關聯字段,一般是主鍵或外鍵,用於關聯兄弟錶數據;
  • 所有兄弟錶的並集是該錶的全量數據;

場景

  1. 有幾個字段屬於熱點字段,更新頻率很高,要把這些字段單獨切到一張錶裏,不然innodb行鎖很惡心的,鎖死你呀~~如用戶錶裏的餘額字段?不,我的餘額就很穩定,一直是0。。
  2. 有大字段,如text,存儲壓力很大,畢竟innodb數據和索引是同一個文件;同時,我又喜歡用SELECT *,你懂得,這磁盤IO消耗的,跟玩兒似的,誰都扛不住的。
  3. 有明顯的業務區分,或錶結構設計時字段冗餘;有些小夥伴看到第一點時,就發現陳哈哈是個菜雞,用戶錶怎麼會有餘額字段?明顯有問題啊!趕緊先到評論區噴陳哈哈一波~~然後笑嘻嘻的發現原來是個小尾巴,真不要臉是吧。。是的,因此不同業務我們要把具體字段拆開,這樣才有利於業務後續擴展哦。

2、水平分錶

水平分錶,也叫“橫著切”。。以行數據為依據進行切分,一般按照某列的自容進行切分。

如手機號錶,我們可以通過前兩比特或前三比特進行切分,如131、132、133 → phone_131、phone_132、phone_133,手機號有11比特(100億),量大是很正常的事兒,這年頭誰家老頭老太太每個手機呢是吧。這樣切就把一張大錶切成了好幾十張小錶,數據量不就下來了。有同學就問了那我怎麼知道我這手機號查哪個錶呢?一看你就沒認真看前兩行標紅的點,為啥標紅嘞?比如我查13100001111,那我截取前三比特,動態拼接到查詢的錶名上,就行了。

特點:

  • 每個錶的結構都一樣;
  • 每個錶的數據都不一樣,沒有交集;
  • 所有錶的並集是該錶的全量數據;

場景:單錶的數據量過大或增長速度很快,已經影響或即將會影響SQL查詢效率,加重了CPU負擔,提前到達瓶頸。記得水平分錶越早越好,別問我為什麼。。

在這裏插入圖片描述
二、花裏胡哨的 - 分庫

需要你注意的是,傳統的分庫和我們熟悉的集群、主從複制可不是一個事兒;多節點集群是將一個庫複制成N個庫,從而通過讀寫分離實現多個MySQL服務的負載均衡,實際是圍繞一個庫來搞的,這個庫稱為Master主庫。而分庫就不同了,分庫是將這個主庫一分為N,比如一分為二,然後針對這兩個主庫,再配置2N個從庫節點。

3、垂直分庫

縱向切庫,太經典的切分方式,基於錶進行切分,通常是把新的業務模塊或集成公共模塊拆分出去,比如我們最熟悉的單點登錄、鑒權模塊。熟悉的味道,記得有一次我把一些沒用的錶切到一個性能很好的服務器中,這服務器我專門用來學習,後來也不知被哪個狗腿子告密了~ 我**你個**,有種站出來,你個**東西。

在這裏插入圖片描述

特點:

  • 每個庫的錶都不一樣;
  • 錶不一樣,數據就更不一樣了~ 沒有任何交集;
  • 每個庫相對獨立,模塊化

場景:可以抽象出單獨的業務模塊時,可以抽象出公共區時(如字典、公共時間、公共配置等),或者想有一臺屬於自己的服務器時?

4、水平分庫

以行數據為依據,將一個庫中的數據拆分到多個庫中。大型分錶體驗一下?坦白說這種策略並不實用,因為會對後臺開發很不友好,有很多坑,不建議采用,理解即可。

特點:

  • 每個庫的結構都一樣;
  • 每個庫的數據都不一樣,沒有交集;
  • 所有庫的並集是全量數據;

場景:系統絕對並發量上來了,CPU內存壓力大。分錶難以根本上解决量的問題,並且還沒有明顯的業務歸屬來垂直分庫,主庫磁盤接近飽和。

其實,在實際工作中,我們在選擇分庫分錶策略前,想到的應該是從緩存、讀寫分離、SQL優化等方面,因為這些能够更直接、代價更小的解决問題。要記住動錶就是動根本,你永遠不知道這張錶後面會連帶多少曆史遺留問題,如果是個很大型的項目,遇到些問題你就跟經理提議要分庫分錶,小心被呼死~

每日小結

今天我們複習了面試中常問的三個實戰問題,你做到心中有數了麼?對了,如果你的朋友也在准備面試,請將這個系列扔給他,如果他認真對待,肯定會感謝你的!!好了,今天就到這裏,學廢了的同學,記得在評論區留言:打卡。,給同學們以激勵。

版权声明:本文为[_陳哈哈]所创,转载请带上原文链接,感谢。 https://gsmany.com/2021/09/20210920010143670p.html