电子产业一站式赋能平台

PCB联盟网

搜索
查看: 158|回复: 0
收起左侧

海康威视,开了体面的薪资!

[复制链接]

312

主题

312

帖子

2398

积分

三级会员

Rank: 3Rank: 3

积分
2398
发表于 2024-11-1 17:02:00 | 显示全部楼层 |阅读模式
大家好,我是库森。& q% g$ ?; k* V) c3 z' c
海康威视作为一家体面厂,我们来看看今年海康威视的校招薪资开了多少?. Q7 ?7 S3 n0 M5 j- x
我根据一些同学的反馈,整理了海康威视软件开发岗位的校招薪资,在目前的就业背景下,海康威视的校招薪资还是很体面的。
" \. e4 c" p* w/ a7 K, @1 |
  • 14k x 15 = 21w(本科 985,武汉)
  • 15k x 15 =  22.5w(硕士双一流,杭州)
  • 16 x 15 =  24w (本硕 211,杭州)
  • 19 x 15 = 28.5w (本硕 211,杭州)那海康威视的面试难度如何呢?
    $ p* x  F; l" [1 x" x* F1 _我也找了一位今年秋招面海康威视同学的面经,给大家做做参考参考,总共 1 轮技术面 + 1 轮 HR 面,3-5 个工作日出结果。6 F: F, f+ {$ N! ^7 t5 l3 ]
    一面是技术面,问的问题不算多,主要拷打了 Java、MySQL、Redis 方面的八股文,都属于经典的面试问题,不算难。
    $ b' I& z- w, F1 C6 [

    fmvmujcputf64078576854.jpg

    fmvmujcputf64078576854.jpg
    & ?# b! H3 J* T9 `" \! B
    Java 介绍一下 Spring Boot 整体的启动流程?
  • 首先从main找到run()方法,在执行run()方法之前new一个SpringApplication对象
  • 进入run()方法,创建应用监听器SpringApplicationRunListeners开始监听
  • 然后加载SpringBoot配置环境(ConfigurableEnvironment),然后把配置环境(Environment)加入监听对象中
  • 然后加载应用上下文(ConfigurableApplicationContext),当做run方法的返回对象
  • 最后创建Spring容器,refreshContext(context),实现starter自动化配置和bean的实例化等工作。[/ol]说一说 Spring MVC 整体的执行流程?
    . ]; Z" C" f9 ?0 r

    cxzzckxp1pl64078576954.jpg

    cxzzckxp1pl64078576954.jpg

    0 i# [0 c& ^" q3 c9 C! H流程图步骤详解:
  • 发送请求:用户发送的所有请求都会到前端控制器DispatcherServlet
  • 请求查找Handler:DispatcherServlet收到请求会调用HandlerMapping(处理器映射器)查找Handler
  • 返回Handler:处理器映射器根据url返回具体的处理器,生成HandlerExecutionChain对象,其中包含了目标Handler和若干拦截器(可能没有)
  • 请求调用Handler:DispatcherServlet通过Handler寻找匹配到HandlerAdapter
  • 执行Handler:HandlerAdapter调用Handler
  • 返回结果:Handler执行完成,返回一个ModelAndView对象
  • 返回结果给DispatcherServlet:HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet
  • 如果Handler返回的View是逻辑视图名称而不是真正的View对象,DispatcherServlet调用resolveViewName方法在配置的所有视图解析器(ViewResolver)中,寻找合适的,最终通过ViewResolver将逻辑视图名解析成真正的View对象
  • ViewResolver通过调用createView方法尝试将视图名解析成View,如果无法解析会返回Null(注: 如果ViewResolver是派生自AbstractCachingViewResolver则在调用createView方法前会先尝试根据viewName和Iocale从缓存中查找对应的视图对象)
  • DispatcherServlet调用View的render方法进行渲染视图 (即将模型数据填充至request域)
  • DispatcherServlet响应用户[/ol]MySQL MySQL 索引的机制,类型有哪些?MySQL可以按照四个角度来分类索引。. z5 x- X* _! s( z# r
  • 按「数据结构」分类:B+tree索引、Hash索引、Full-text索引
  • 按「物理存储」分类:聚簇索引(主键索引)、二级索引(辅助索引)
  • 按「字段特性」分类:主键索引、唯一索引、普通索引、前缀索引
  • 按「字段个数」分类:单列索引、联合索引接下来,按照这些角度来说说各类索引的特点。
    7 k  |4 }3 b( u+ }9 |6 _$ |" l8 o& ~按数据结构分类% y9 s6 g( U: B- v+ F. {4 |+ t, h+ J
    从数据结构的角度来看,MySQL 常见索引有 B+Tree 索引、HASH 索引、Full-Text 索引。, r7 o' l9 M& y6 U+ y: Y
    每一种存储引擎支持的索引类型不一定相同,我在表中总结了 MySQL 常见的存储引擎 InnoDB、MyISAM 和 Memory 分别支持的索引类型。
      z! j: ]% c+ C6 D/ b: k# Y9 @  D

    zjro0uixxki64078577054.jpg

    zjro0uixxki64078577054.jpg
    . q* Z8 Y4 x4 s2 u
    InnoDB 是在 MySQL 5.5 之后成为默认的 MySQL 存储引擎,B+Tree 索引类型也是 MySQL 存储引擎采用最多的索引类型。6 D7 _$ l& b5 @
    在创建表时,InnoDB 存储引擎会根据不同的场景选择不同的列作为索引:
    8 J) c( o* K8 }5 ?% f
  • 如果有主键,默认会使用主键作为聚簇索引的索引键(key);
  • 如果没有主键,就选择第一个不包含 NULL 值的唯一列作为聚簇索引的索引键(key);
  • 在上面两个都没有的情况下,InnoDB 将自动生成一个隐式自增 id 列作为聚簇索引的索引键(key);其它索引都属于辅助索引(Secondary Index),也被称为二级索引或非聚簇索引。创建的主键索引和二级索引默认使用的是 B+Tree 索引1 s' [. t: \: g8 D. d/ ~' N. M+ T. ~
    按物理存储分类" T4 ~5 U1 i6 T4 u
    从物理存储的角度来看,索引分为聚簇索引(主键索引)、二级索引(辅助索引)。; H. \3 Q7 Z  z/ @4 l; b8 {* \
    这两个区别在前面也提到了:2 W! D4 m; A% r7 k, p$ Y$ K
  • 主键索引的 B+Tree 的叶子节点存放的是实际数据,所有完整的用户记录都存放在主键索引的 B+Tree 的叶子节点里;
  • 二级索引的 B+Tree 的叶子节点存放的是主键值,而不是实际数据。所以,在查询时使用了二级索引,如果查询的数据能在二级索引里查询的到,那么就不需要回表,这个过程就是覆盖索引。如果查询的数据不在二级索引里,就会先检索二级索引,找到对应的叶子节点,获取到主键值后,然后再检索主键索引,就能查询到数据了,这个过程就是回表。  {3 c+ `2 F/ X' P
    按字段特性分类
    % t7 K* D( z* ~; D" E) G/ h  h. B
    从字段特性的角度来看,索引分为主键索引、唯一索引、普通索引、前缀索引。" D- r% X- {' L; D
  • 主键索引主键索引就是建立在主键字段上的索引,通常在创建表的时候一起创建,一张表最多只有一个主键索引,索引列的值不允许有空值。
    ' j) L% a) U) Y. {- b在创建表时,创建主键索引的方式如下:
    ! c( \4 {+ H2 ~7 w2 z4 I; XCREATE TABLE table_name  (& j* ]4 C4 d  o2 l
      ....
    " b/ T+ k7 n, A9 J( o3 V5 j  PRIMARY KEY (index_column_1) USING BTREE
    * w1 C6 k3 v# L; Y7 D. m);
    , j( Y- r4 J+ \) m: |% X, E
  • 唯一索引唯一索引建立在 UNIQUE 字段上的索引,一张表可以有多个唯一索引,索引列的值必须唯一,但是允许有空值。( q1 J. M6 s1 u
    在创建表时,创建唯一索引的方式如下:
    # M7 K& S  M% T9 M: lCREATE TABLE table_name  (
    0 O# P, N( ]' M) Q* ^# r  x' W  ....3 o* M* b- f* E3 G
      UNIQUE KEY(index_column_1,index_column_2,...) . l! R2 ?: f$ @" [
    );
    / `: Z# }# Y+ z建表后,如果要创建唯一索引,可以使用这面这条命令:% @3 a1 n6 s/ S) M
    CREATE UNIQUE INDEX index_name+ P) d* C; g8 J* R: Y  X1 o1 B3 r
    ON table_name(index_column_1,index_column_2,...);- d+ ~2 x/ P' G& ~& `6 ~2 E# `
  • 普通索引普通索引就是建立在普通字段上的索引,既不要求字段为主键,也不要求字段为 UNIQUE。
    7 f; |* r' p2 P2 M在创建表时,创建普通索引的方式如下:
    4 S6 C6 C: h. Y5 {7 X! F  d% a, _CREATE TABLE table_name  () |8 l: }! f' C6 E5 U- N! C2 p0 d
      ....
    2 N: [! ~  [" W( m  INDEX(index_column_1,index_column_2,...) 8 C* X" X; V! I$ n5 h
    );0 a; C6 O4 e# L$ C. s5 K
    建表后,如果要创建普通索引,可以使用这面这条命令:/ A- H" g  V  ?
    CREATE INDEX index_name0 N+ a- {& r, d. }) S- H" |% K
    ON table_name(index_column_1,index_column_2,...);# k  Q$ [5 C8 z6 I
  • 前缀索引前缀索引是指对字符类型字段的前几个字符建立的索引,而不是在整个字段上建立的索引,前缀索引可以建立在字段类型为 char、 varchar、binary、varbinary 的列上。" W* ^& L% [! k" I) o# p- V9 u
    使用前缀索引的目的是为了减少索引占用的存储空间,提升查询效率。
    6 {. o* Z4 x& j  L( e在创建表时,创建前缀索引的方式如下:+ Y0 {& c, z/ ~. r1 v6 f- `1 L
    CREATE TABLE table_name() ^  o' I9 m4 T" C+ s
        column_list,& X+ s8 c& m8 @0 H1 r' A- B
        INDEX(column_name(length))
    1 \; }+ L8 g- T! B0 U( C);2 c/ f0 z& D4 v  x& M! a
    建表后,如果要创建前缀索引,可以使用这面这条命令:
    ( m+ k4 Z/ p, Z4 eCREATE INDEX index_name( o7 \8 P. W, o* f( d) n! |
    ON table_name(column_name(length));
    9 q9 Q+ q! i( v5 f5 W) H按字段个数分类! q4 J7 G8 W  e! \4 T) K, z
    从字段个数的角度来看,索引分为单列索引、联合索引(复合索引)。
    & Y, k9 X% q2 w5 ?, \( V. A- I
  • 建立在单列上的索引称为单列索引,比如主键索引;
  • 建立在多列上的索引称为联合索引;通过将多个字段组合成一个索引,该索引就被称为联合索引。
    5 e( G. S; c% G, r! c比如,将商品表中的 product_no 和 name 字段组合成联合索引(product_no, name),创建联合索引的方式如下:" E) Z* L% P1 E# a; e9 }! s9 `
    CREATE INDEX index_product_no_name ON product(product_no, name);$ g& q4 |) {' d
    联合索引(product_no, name) 的 B+Tree 示意图如下(图中叶子节点之间我画了单向链表,但是实际上是双向链表,原图我找不到了,修改不了,偷个懒我不重画了,大家脑补成双向链表就行)。/ Y4 Z" T( A% h/ j7 J1 }! x! P6 d

    ibea4h5cthi64078577154.jpg

    ibea4h5cthi64078577154.jpg

    4 f4 A! h4 M4 i& ?$ {. a可以看到,联合索引的非叶子节点用两个字段的值作为 B+Tree 的 key 值。当在联合索引查询数据时,先按 product_no 字段比较,在 product_no 相同的情况下再按 name 字段比较。
    7 r, w, Z4 f. p3 ^0 {! m' J( q也就是说,联合索引查询的 B+Tree 是先按 product_no 进行排序,然后再 product_no 相同的情况再按 name 字段排序。
    % u1 I' e0 a# M因此,使用联合索引时,存在最左匹配原则,也就是按照最左优先的方式进行索引的匹配。在使用联合索引进行查询的时候,如果不遵循「最左匹配原则」,联合索引会失效,这样就无法利用到索引快速查询的特性了。
    8 C2 Q- ~& V. ?, I* U0 ?4 v8 ~: }比如,如果创建了一个 (a, b, c) 联合索引,如果查询条件是以下这几种,就可以匹配上联合索引:
    $ B* c( P" m6 N
  • where a=1;
  • where a=1 and b=2 and c=3;
  • where a=1 and b=2;需要注意的是,因为有查询优化器,所以 a 字段在 where 子句的顺序并不重要。
    4 I4 T; ~9 v; {1 l但是,如果查询条件是以下这几种,因为不符合最左匹配原则,所以就无法匹配上联合索引,联合索引就会失效:
    ! ~( {5 J" C% f2 V7 O( c- v
  • where b=2;
  • where c=3;
  • where b=2 and c=3;上面这些查询条件之所以会失效,是因为(a, b, c) 联合索引,是先按 a 排序,在 a 相同的情况再按 b 排序,在 b 相同的情况再按 c 排序。所以,b 和 c 是全局无序,局部相对有序的,这样在没有遵循最左匹配原则的情况下,是无法利用到索引的。0 r% e( I1 J' F" ?- ]% P$ L& y
    联合索引有一些特殊情况,并不是查询过程使用了联合索引查询,就代表联合索引中的所有字段都用到了联合索引进行索引查询,也就是可能存在部分字段用到联合索引的 B+Tree,部分字段没有用到联合索引的 B+Tree 的情况。
    . q, ^; N% {* P" v这种特殊情况就发生在范围查询。联合索引的最左匹配原则会一直向右匹配直到遇到「范围查询」就会停止匹配。也就是范围查询的字段可以用到联合索引,但是在范围查询字段的后面的字段无法用到联合索引9 B9 V) o  n( R# ]: S5 ]" G0 s0 V
    有无排查索引失效的经验,展开讲讲?可以使用 EXPLAIN 来查看 SQL 的执行计划,判断SQL是否走了索引,如果没有走索引,就代表索引发生失效了。
    9 s/ f+ _# a% y1 c" B8 J, H% i' i/ @如下图,就是一个没有使用索引,并且是一个全表扫描的查询语句。
    $ w3 k/ f' c/ {( F, V- T

    53a05fgp4c264078577254.jpg

    53a05fgp4c264078577254.jpg
    3 v. d/ s3 \( X. E: T! F. {
    对于执行计划,参数有:
    - F3 f: b1 j; Y9 t3 j  W% m
  • possible_keys 字段表示可能用到的索引;
  • key 字段表示实际用的索引,如果这一项为 NULL,说明没有使用索引;
  • key_len 表示索引的长度;
  • rows 表示扫描的数据行数。
  • type 表示数据扫描类型,我们需要重点看这个。type 字段就是描述了找到所需数据时使用的扫描方式是什么,常见扫描类型的执行效率从低到高的顺序为
    1 L" O4 [+ t$ E0 T
  • All(全表扫描):在这些情况里,all 是最坏的情况,因为采用了全表扫描的方式。
  • index(全索引扫描):index 和 all 差不多,只不过 index 对索引表进行全扫描,这样做的好处是不再需要对数据进行排序,但是开销依然很大。所以,要尽量避免全表扫描和全索引扫描。
  • range(索引范围扫描):range 表示采用了索引范围扫描,一般在 where 子句中使用 、in、between 等关键词,只检索给定范围的行,属于范围查找。从这一级别开始,索引的作用会越来越明显,因此我们需要尽量让 SQL 查询可以使用到 range 这一级别及以上的 type 访问方式
  • ref(非唯一索引扫描):ref 类型表示采用了非唯一索引,或者是唯一索引的非唯一性前缀,返回数据返回可能是多条。因为虽然使用了索引,但该索引列的值并不唯一,有重复。这样即使使用索引快速查找到了第一条数据,仍然不能停止,要进行目标值附近的小范围扫描。但它的好处是它并不需要扫全表,因为索引是有序的,即便有重复值,也是在一个非常小的范围内扫描。
  • eq_ref(唯一索引扫描):eq_ref 类型是使用主键或唯一索引时产生的访问方式,通常使用在多表联查中。比如,对两张表进行联查,关联条件是两张表的 user_id 相等,且 user_id 是唯一索引,那么使用 EXPLAIN 进行执行计划查看的时候,type 就会显示 eq_ref。
  • const(结果只有一条的主键或唯一索引扫描):const 类型表示使用了主键或者唯一索引与常量值进行比较,比如 select name from product where id=1。需要说明的是 const 类型和 eq_ref 都使用了主键或唯一索引,不过这两个类型有所区别,const 是与常量进行比较,查询效率会更快,而 eq_ref 通常用于多表联查中extra 显示的结果,这里说几个重要的参考指标:. m' @3 m+ z  _  o0 {2 a! U
  • Using filesort :当查询语句中包含 group by 操作,而且无法利用索引完成排序操作的时候, 这时不得不选择相应的排序算法进行,甚至可能会通过文件排序,效率是很低的,所以要避免这种问题的出现。
  • Using temporary:使了用临时表保存中间结果,MySQL 在对查询结果排序时使用临时表,常见于排序 order by 和分组查询 group by。效率低,要避免这种问题的出现。
  • Using index:所需数据只需在索引即可全部获得,不须要再到表中取数据,也就是使用了覆盖索引,避免了回表操作,效率不错。索引失效的场景有哪些?会发生索引失效的情况:
    ' K9 ]4 ~/ P. d3 k6 ^7 w6 K
  • 当我们使用左或者左右模糊匹配的时候,也就是 like %xx 或者 like %xx%这两种方式都会造成索引失效;
  • 当我们在查询条件中对索引列使用函数,就会导致索引失效。
  • 当我们在查询条件中对索引列进行表达式计算,也是无法走索引的。
  • MySQL 在遇到字符串和数字比较的时候,会自动把字符串转为数字,然后再进行比较。如果字符串是索引列,而条件语句中的输入参数是数字的话,那么索引列会发生隐式类型转换,由于隐式类型转换是通过 CAST 函数实现的,等同于对索引列使用了函数,所以就会导致索引失效。
  • 联合索引要能正确使用需要遵循最左匹配原则,也就是按照最左优先的方式进行索引的匹配,否则就会导致索引失效。
  • 在 WHERE 子句中,如果在 OR 前的条件列是索引列,而在 OR 后的条件列不是索引列,那么索引会失效。Redis Redis 为什么这么快?官方使用基准测试的结果是,单线程的 Redis 吞吐量可以达到 10W/每秒,如下图所示:, d3 _# A5 R3 g

    h1twxfhtg3w64078577354.jpg

    h1twxfhtg3w64078577354.jpg

    ; R9 H# t1 w2 d0 m5 H之所以 Redis 采用单线程(网络 I/O 和执行命令)那么快,有如下几个原因:. h8 ?( x. k+ G- ?! E
  • Redis 的大部分操作都在内存中完成,并且采用了高效的数据结构,因此 Redis 瓶颈可能是机器的内存或者网络带宽,而并非 CPU,既然 CPU 不是瓶颈,那么自然就采用单线程的解决方案了;
  • Redis 采用单线程模型可以避免了多线程之间的竞争,省去了多线程切换带来的时间和性能上的开销,而且也不会导致死锁问题。
  • Redis 采用了 I/O 多路复用机制处理大量的客户端 Socket 请求,IO 多路复用机制是指一个线程处理多个 IO 流,就是我们经常听到的 select/epoll 机制。简单来说,在 Redis 只运行单线程的情况下,该机制允许内核中,同时存在多个监听 Socket 和已连接 Socket。内核会一直监听这些 Socket 上的连接请求或数据请求。一旦有请求到达,就会交给 Redis 线程处理,这就实现了一个 Redis 线程处理多个 IO 流的效果。Redis 6.0 之后为什么引入了多线程?Redis 单线程指的是「接收客户端请求->解析请求 ->进行数据读写等操作->发送数据给客户端」这个过程是由一个线程(主线程)来完成的,这也是我们常说 Redis 是单线程的原因。0 }2 U3 u1 T) Q4 y3 z  S
    但是,Redis 程序并不是单线程的,Redis 在启动的时候,是会启动后台线程(BIO)的:
    " b; Q3 F! P. i6 ^
  • Redis 在 2.6 版本,会启动 2 个后台线程,分别处理关闭文件、AOF 刷盘这两个任务;
  • Redis 在 4.0 版本之后,新增了一个新的后台线程,用来异步释放 Redis 内存,也就是 lazyfree 线程。例如执行 unlink key / flushdb async / flushall async 等命令,会把这些删除操作交给后台线程来执行,好处是不会导致 Redis 主线程卡顿。因此,当我们要删除一个大 key 的时候,不要使用 del 命令删除,因为 del 是在主线程处理的,这样会导致 Redis 主线程卡顿,因此我们应该使用 unlink 命令来异步删除大key。之所以 Redis 为「关闭文件、AOF 刷盘、释放内存」这些任务创建单独的线程来处理,是因为这些任务的操作都是很耗时的,如果把这些任务都放在主线程来处理,那么 Redis 主线程就很容易发生阻塞,这样就无法处理后续的请求了。
    . t1 H1 a6 Q& A9 B0 K后台线程相当于一个消费者,生产者把耗时任务丢到任务队列中,消费者(BIO)不停轮询这个队列,拿出任务就去执行对应的方法即可。" M4 C0 u- Z7 P4 A! F; e7 \0 p

    znfflvyj2bj64078577454.jpg

    znfflvyj2bj64078577454.jpg

    * G# a! q4 {: e  P% u: t$ I+ T, e虽然 Redis 的主要工作(网络 I/O 和执行命令)一直是单线程模型,但是在 Redis 6.0 版本之后,也采用了多个 I/O 线程来处理网络请求这是因为随着网络硬件的性能提升,Redis 的性能瓶颈有时会出现在网络 I/O 的处理上
    * w9 k# c& o, z/ k" U1 e& j所以为了提高网络 I/O 的并行度,Redis 6.0 对于网络 I/O 采用多线程来处理。但是对于命令的执行,Redis 仍然使用单线程来处理,所以大家不要误解Redis 有多线程同时执行命令3 i/ A- C' i! P0 `6 R3 k; t  N
    Redis 官方表示,Redis 6.0 版本引入的多线程 I/O 特性对性能提升至少是一倍以上( n8 n% E* @! n3 R
    Redis 6.0 版本支持的 I/O 多线程特性,默认情况下 I/O 多线程只针对发送响应数据(write client socket),并不会以多线程的方式处理读请求(read client socket)。要想开启多线程处理客户端读请求,就需要把 Redis.conf 配置文件中的 io-threads-do-reads 配置项设为 yes。. b2 v; W1 H& n) `# a' m
    //读请求也使用io多线程
    % H5 K" C  m% j" Q+ Q: _8 Hio-threads-do-reads yes
    9 U2 h( P) G% x9 |同时, Redis.conf 配置文件中提供了 IO 多线程个数的配置项。# ]7 F  R% G; T4 T9 w
    // io-threads N,表示启用 N-1 个 I/O 多线程(主线程也算一个 I/O 线程)
    $ a( S" n* z3 o$ |! ]* Zio-threads 4
    ; M% J# F" q: ~- N2 `7 E关于线程数的设置,官方的建议是如果为 4 核的 CPU,建议线程数设置为 2 或 3,如果为 8 核 CPU 建议线程数设置为 6,线程数一定要小于机器核数,线程数并不是越大越好。
    9 N: \, S7 _5 z; g. ~( ~& o& q因此, Redis 6.0 版本之后,Redis 在启动的时候,默认情况下会额外创建 6 个线程(这里的线程数不包括主线程):
    + |" ~0 `' @9 ~6 y1 Z; M5 ~
  • Redis-server :Redis的主线程,主要负责执行命令;
  • bio_close_file、bio_aof_fsync、bio_lazy_free:三个后台线程,分别异步处理关闭文件任务、AOF刷盘任务、释放内存任务;
  • io_thd_1、io_thd_2、io_thd_3:三个 I/O 线程,io-threads 默认是 4 ,所以会启动 3(4-1)个 I/O 多线程,用来分担 Redis 网络 I/O 的压力。Redis 分布式锁怎么解决超卖问题的?同一个锁key,同一时间只能有一个客户端拿到锁,其他客户端会陷入无限的等待来尝试获取那个锁,只有获取到锁的客户端才能执行下面的业务逻辑。  l4 k' \! v2 A! O9 B
    比如说,用户要一次性买 10 台手机,那么避免超卖的流程如下:+ j) e! }! A& t
  • 只有一个订单系统实例可以成功加分布式锁,然后只有他一个实例可以查库存、判断库存是否充足、下单扣减库存,接着释放锁。
  • 释放锁之后,另外一个订单系统实例才能加锁,接着查库存,一下发现库存只有 2 个了,库存不足,无法购买,下单失败,不会将库存扣减为-8的,就避免超卖的问题。这种方案的缺点是同一个商品在多用户同时下单的情况下,会基于分布式锁串行化处理,导致没法同时处理同一个商品的大量下单的请求。
  • 回复

    使用道具 举报

    发表回复

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则


    联系客服 关注微信 下载APP 返回顶部 返回列表