??大家好,我是陳哈哈,北漂五年,相信大家和我一樣,
都有一個大廠夢,作為一名資深Java選手,深知面試重要性,接下來我準備用100天時間,基于Java崗面試中的高頻面試題,以每日3題的形式,帶你過一遍熱門面試題及恰如其分的解答,
??一路走來,隨著問題加深,發現不會的也愈來愈多,但底氣著實足了不少,相信不少朋友和我一樣,榷訓月累才是最有效的學習方式!想起高三時一個同學的座右銘:只有沉下去,才能浮上來,共勉(juan),

作者:云野.
車票
- 面試題1:如果用mybatis批量插入資料時需要回傳主鍵,你是怎么做的?
- 面試題2:在微服務中你是如何實作不同服務間session 共享的?
- 面試題3:你了解分庫分表么?分庫分表一般出現在哪些場景下?
- 每日小結
??本欄目Java開發崗高頻面試題主要出自以下各技術堆疊:Java基礎知識、集合容器、并發編程、JVM、Spring全家桶、MyBatis等ORMapping框架、MySQL資料庫、Redis快取、RabbitMQ訊息佇列、Linux操作技巧等,
面試題1:如果用mybatis批量插入資料時需要回傳主鍵,你是怎么做的?
??需要在Mapper.xml的中標簽中配置useGeneratedKeys和keyProperty兩個屬性,就可以在批量插入時回傳主鍵,
??比如有個表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、垂直分表
??垂直分表,或者叫豎著切表,是不是感受到該策略是以欄位為依據的!主要按照欄位的活躍性、欄位長度,將表中欄位拆分到不同的表(主表和擴展表)中,
特點:
- 每個表的結構都不一樣;
- 每個表的資料也不一樣,
- 有一個關聯欄位,一般是主鍵或外鍵,用于關聯
兄弟表資料; - 所有兄弟表的并集是該表的全量資料;
場景:
有幾個欄位屬于熱點欄位,更新頻率很高,要把這些欄位單獨切到一張表里,不然innodb行鎖很惡心的,鎖死你呀~~如用戶表里的余額欄位?不,我的余額就很穩定,一直是0,,有大欄位,如text,存盤壓力很大,畢竟innodb資料和索引是同一個檔案;同時,我又喜歡用SELECT *,你懂得,這磁盤IO消耗的,跟玩兒似的,誰都扛不住的,有明顯的業務區分,或表結構設計時欄位冗余;有些小伙伴看到第一點時,就發現陳哈哈是個菜雞,用戶表怎么會有余額欄位?明顯有問題啊!趕緊先到評論區噴陳哈哈一波~~然后笑嘻嘻的發現原來是個小尾巴,真不要臉是吧,,是的,因此不同業務我們要把具體欄位拆開,這樣才有利于業務后續擴展哦,
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://www.uj5u.com/houduan/301278.html
標籤:java
