揭秘:大廠面試必考題,常常出現(xiàn)在第二輪
請(qǐng)聽題。
假設(shè)你是一個(gè)資深程序員,已創(chuàng)建完成了SpringBoot項(xiàng)目,需要使用SpringBoot模擬實(shí)現(xiàn)電商平臺(tái)秒殺場(chǎng)景,100萬(wàn)人在線下單搶購(gòu)一個(gè)3000庫(kù)存量的半價(jià)化妝品。
請(qǐng)用Java寫出秒殺系統(tǒng)建表SQL和注意事項(xiàng)
(這是一道送分題,思索片刻。)
下面給出答案示例:
CREATE TABLE `tb_seckill` (
? `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '秒殺活動(dòng)ID',
? `name` varchar(50) NOT NULL COMMENT '秒殺活動(dòng)名稱',
? `start_time` datetime NOT NULL COMMENT '秒殺開始時(shí)間',
? `end_time` datetime NOT NULL COMMENT '秒殺結(jié)束時(shí)間',
? `total` int(11) NOT NULL COMMENT '商品總量',
? PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='秒殺活動(dòng)表';
CREATE TABLE `tb_seckill_item` (
? `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '秒殺活動(dòng)商品ID',
? `seckill_id` bigint(20) NOT NULL COMMENT '秒殺活動(dòng)ID',
? `item_id` bigint(20) NOT NULL COMMENT '商品ID',
? `price` decimal(10,2) NOT NULL COMMENT '秒殺價(jià)格',
? `stock_count` int(11) NOT NULL COMMENT '商品庫(kù)存量',
? `start_time` datetime NOT NULL COMMENT '秒殺開始時(shí)間',
? `end_time` datetime NOT NULL COMMENT '秒殺結(jié)束時(shí)間',
? PRIMARY KEY (`id`),
? KEY `idx_seckill_id` (`seckill_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='秒殺活動(dòng)商品表';
上述建表SQL創(chuàng)建了兩張表:tb_seckill(秒殺活動(dòng)表)和tb_seckill_item(秒殺活動(dòng)商品表),其中:
tb_seckill表用于存儲(chǔ)秒殺活動(dòng)的基本信息,包括活動(dòng)ID、名稱、開始時(shí)間、結(jié)束時(shí)間和商品總量等。
tb_seckill_item表用于存儲(chǔ)秒殺活動(dòng)商品的信息,包括商品ID、秒殺價(jià)格、庫(kù)存量、開始時(shí)間、結(jié)束時(shí)間和所屬的秒殺活動(dòng)ID等。
需要注意的是,對(duì)于秒殺場(chǎng)景而言,高并發(fā)是不可避免的,因此在建表時(shí)需要考慮如何優(yōu)化數(shù)據(jù)庫(kù)性能。
以下是一些建議:
盡量避免使用全表掃描、索引失效和大事務(wù)等問(wèn)題,可以使用合適的索引、拆分表和分庫(kù)分表等技術(shù)來(lái)解決。
合理設(shè)置表結(jié)構(gòu)和數(shù)據(jù)類型,避免浪費(fèi)存儲(chǔ)空間和影響查詢性能。
使用適當(dāng)?shù)木彺婧皖A(yù)熱技術(shù),可以提高數(shù)據(jù)庫(kù)的并發(fā)處理能力和性能。
使用樂(lè)觀鎖和悲觀鎖等機(jī)制,避免數(shù)據(jù)沖突和并發(fā)問(wèn)題。
在實(shí)際的開發(fā)過(guò)程中,還需要根據(jù)具體的業(yè)務(wù)需求和性能要求進(jìn)行優(yōu)化和調(diào)整。
接下來(lái),我們需要使用Spring-Mybatis框架,提供一個(gè)interface接口。其他和數(shù)據(jù)庫(kù)交互的SQL編寫放到對(duì)應(yīng)的XML文件中,開始DAO層接口的編寫。
以下是使用Spring-Mybatis框架編寫DAO層接口的示例:
首先,我們需要在Spring Boot項(xiàng)目中添加MyBatis依賴,例如:
org.mybatis.spring.boot
mybatis-spring-boot-starter 2.2.0
然后,在src/main/resources目錄下創(chuàng)建MyBatis的XML配置文件和Mapper接口,例如:
1.src/main/resources/mybatis-config.xml配置文件? ?
2.src/main/resources/mapper/SeckillMapper.xml文件
UPDATE tb_seckill_item
SET stock_count = stock_count - #{quantity}
WHERE id = #{itemId}
AND stock_count > 0
3.src/main/resources/mapper/SeckillItemMapper.xml文件
4.com.example.demo.dao.SeckillMapper接口
public interface SeckillMapper {
? ? Seckill queryById(Long id);
? ? int reduceStockCount(MapparamMap);
}
5.com.example.demo.dao.SeckillItemMapper接口
kotlin
public interface SeckillItemMapper {
? ? SeckillItem queryById(Long id);
}
現(xiàn)在,我們使用IDEA開發(fā)工具,打開接口文件。并用Java創(chuàng)建 SeckillMapper接口的測(cè)試文件:SeckillMapperTest.java
那么,為了實(shí)現(xiàn)電商平臺(tái)的秒殺場(chǎng)景,我們需要完成以下步驟:
創(chuàng)建一個(gè)名為Seckill的實(shí)體類,用于表示秒殺商品,包括商品的ID、名稱、庫(kù)存數(shù)量、開始時(shí)間和結(jié)束時(shí)間等屬性。
public class Seckill {
? ? private Long id; // 商品ID
? ? private String name; // 商品名稱
? ? private Integer stock; // 商品庫(kù)存
? ? private Date startTime; // 秒殺開始時(shí)間
? ? private Date endTime; // 秒殺結(jié)束時(shí)間
? ? // 省略getter和setter方法
}
創(chuàng)建一個(gè)名為SeckillMapper的Mapper接口,用于操作秒殺商品表。其中,包括根據(jù)ID查詢商品、減少商品庫(kù)存等方法。
@Mapper
public interface SeckillMapper {
? ? /**
? ? * 根據(jù)ID查詢秒殺商品
? ? * @param id 商品ID
? ? * @return 秒殺商品
? ? */
? ? Seckill selectById(Long id);
? ? /**
? ? * 減少商品庫(kù)存
? ? * @param seckill 秒殺商品
? ? * @return 更新記錄數(shù),如果更新成功返回1,否則返回0
? ? */
? ? int reduceStock(Seckill seckill);
}
在application.yml文件中配置數(shù)據(jù)源和Mybatis,如下所示:
spring:
datasource:
url: jdbc:mysql://localhost:3306/seckill?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath:mapper/*.xml
創(chuàng)建一個(gè)名為SeckillMapperTest的測(cè)試類,用于測(cè)試SeckillMapper接口的正確性。
@RunWith(SpringRunner.class)
@SpringBootTest
public class SeckillMapperTest {
? ? @Autowired
? ? private SeckillMapper seckillMapper;
? ? @Test
? ? public void testSelectById() {
? ? ? ? Long id = 1L;
? ? ? ? Seckill seckill = seckillMapper.selectById(id);
? ? ? ? assertNotNull(seckill);
? ? ? ? assertEquals(id, seckill.getId());
? ? }
? ? @Test
? ? public void testReduceStock() {
? ? ? ? Long id = 1L;
? ? ? ? Seckill seckill = seckillMapper.selectById(id);
? ? ? ? assertNotNull(seckill);
? ? ? ? int affectedRows = seckillMapper.reduceStock(seckill);
? ? ? ? assertEquals(1, affectedRows);
? ? }
}
在這個(gè)測(cè)試類中,我們注入了SeckillMapper接口,并測(cè)試了selectById和reduceStock兩個(gè)方法的正確性。其中,testSelectById方法測(cè)試了根據(jù)ID查詢商品的正確性,testReduceStock方法測(cè)試了減少商品庫(kù)存的正確性。
以上就是使用SpringBoot模擬實(shí)現(xiàn)電商平臺(tái)秒殺場(chǎng)景的詳細(xì)說(shuō)明和Java代碼示例。需要注意的是,在實(shí)際開發(fā)中,您還需要完成其他方面的工作,比如實(shí)現(xiàn)秒殺商品的展示、下單、支付等功能,保證整個(gè)電商平臺(tái)的正常運(yùn)行。
同時(shí),作為大廠的面試必考題,常常出現(xiàn)在第二輪,相信你在LEEDCODE刷題的同時(shí),也會(huì)時(shí)常關(guān)注和探討碼農(nóng)的生態(tài)與職業(yè)生涯規(guī)劃。
關(guān)注我??
漲IT姿勢(shì)??
找遠(yuǎn)程工作??
赴日工作內(nèi)推??
