1、redis主从架构锁失效问题解析(不容易解决);
redis主节点设置key值成功,立马会返回,加锁成功了,可以执行业务了;redis是异步同步数据到主节点了;这里有个问题,就是主节点刚刚写成功,还没有同步给从节点,此时主节点挂了,该怎么办?此时从节点会变成主节点(选举),此时来了一个线程3也要给同一个商品去加锁,也会加成功,这样会出现问题?这样两个线程都可以执行减库存的业务,导致超卖现象。
2、RedRedis实现原理(和zookper类似)

setnx(key1,value)给三个redis节点,要至少超过半数以上redis节点返回成功才算加锁成功,再开始执行加锁逻辑。
但是再来一个客户端1进行加锁setnx(key1,value),key是相同的,由于有超过半数redis节点才加锁成功,则客户端1是不可能加锁成功的(key1)。
RedRedis加锁要往所有节点上去加锁,损失了一点点可用性,相比主从架构(可用性高一些,几乎没有锁等待);但是对服务端的节点一致性上要好一点。
但是不推荐使用
分布式锁:把多个并行的请求串行话,用redis单线程串行化去实现,当然没有问题了;这是从设计的语义的角度,决定的。说白了,redis分布式锁从这方面说,这和我们的高并发的架构是有所违背的,尽管我们用redis来实现,性能非常高;所以在某些特别高并发(并不多见)情况下面,比如在秒杀场景,大量的请求都针对于同一个商品,要抢购才会出现这样的问题。秒杀场景不是针对同一个商品,比如说不同的请求,不同的用户,A用户抢购的是101商品,B用户抢购的是102商品,不存在并发,锁也不会生效。
用到分布式锁,又要高并发,本身并不是特别多,但如果是碰到了,是要基于场景做各种优化。
重入锁
3、分布式锁场景优化
1、锁的粒度越小越好,很多代码不需要加锁的,加了,别人也执行不了啊
2、分段锁(1000件商品,分成十个key值,性能提升10倍)
大厂线上大规模商品缓存数据冷热分离实战
例如有商品页面,要把商品信息放入缓存,商品很多信息变化都不会很大,基于此,写了商品信息的增删改查
商品新增时,加入到redis里面,设置有效期,比如24h;在查询商品的时候,增加有效期
每天99%访问的热数据都走缓存,那数据库基本上就没什么压力了
缓存击穿
批量导入商品,把信息写入redis,写入的过期时间都是一样的,一旦全部都同时到期,大量的客户端来请求的时候,在缓存查询不到,就会去访问数据库,导致数据库压力比较大
缓存穿透
黑客攻击导致缓存穿透线上数据库宕机bug
第一, 自身业务代码或者数据出现问题。
第二, 一些恶意攻击、 爬虫等造成大量空命中。
缓存穿透问题解决方案:
1、缓存空对象
2、布隆过滤器
缓存雪崩
缓存雪崩指的是缓存层支撑不住或宕掉后, 流量会像奔逃的野牛一样, 打向后端存储层。
由于缓存层承载着大量请求, 有效地保护了存储层, 但是如果缓存层由于某些原因不能提供服务(比如超大并
发过来,缓存层支撑不住,或者由于缓存设计不好,类似大量请求访问bigkey,导致缓存能支撑的并发急剧下
降), 于是大量请求都会打到存储层, 存储层的调用量会暴增, 造成存储层也会级联宕机的情况。
预防和解决缓存雪崩问题, 可以从以下三个方面进行着手。
1) 保证缓存层服务高可用性,比如使用Redis Sentinel或Redis Cluster。
2) 依赖隔离组件为后端限流熔断并降级。比如使用Sentinel或Hystrix限流降级组件。
比如服务降级,我们可以针对不同的数据采取不同的处理方式。当业务应用访问的是非核心数据(例如电商商
品属性,用户信息等)时,暂时停止从缓存中查询这些数据,而是直接返回预定义的默认降级信息、空值或是
错误提示信息;当业务应用访问的是核心数据(例如电商商品库存)时,仍然允许查询缓存,如果缓存缺失,
也可以继续通过数据库读取。
3) 提前演练。 在项目上线前, 演练缓存层宕掉后, 应用以及后端的负载情况以及可能出现的问题, 在此基
础上做一些预案设定。
突发性热点缓存重建导致系统压力报增问题分析
参考单列模式的DCL(双重检测锁)
先查询redis缓存一次,再加锁查询redis缓存一次,如果没有则查询数据库,并写入redis缓存,那其他请求则能直接在redis缓存查询到,而不会去访问数据库。
缓存与数据库双写不一致(概率小)
写数据库,并更新缓存(可以用分布式锁解决)

或者写数据库,并删除缓存
延迟双删
延迟双删,即在写数据库,并删除缓存之后,再等待一会儿,再次删除缓存。
可以解决缓存与数据库不一致的问题,但是影响了性能,毕竟这种不一致是小范围发生的事,却要把每一个写数据库,删除缓存,延迟一点时间,再删除,得不偿失。
redis读写锁实现原理
读锁内部实现
读锁绑定一个read,写锁绑定一个write
有多个请求来执行这个方法,都同步去加锁(对同一个商品),第一个请求可以加锁,第二个请求来也可以加锁,但是加锁的次数相当于重入+1,也就可以多个请求并行执行。解锁就-1。
—————————————————————————————————————————————————————————
如果多个请求进来,是写锁,判断是否为”write锁”,是的话,就等着,等写锁释放掉,其他线程再去加锁
假设有几万个线程请求进来,只有一个线程会执行后面的业务,也只会执行1秒
此时可以用tryLock(1, TimeUnit.SECONDS);那几万个线程1秒以后再去抢锁
—————————————————————————————————————————————————————————-
一次微博明星热点事件导致系统崩溃原因分析
上亿粉丝的微博大V发一个微博,同时可能有几十上百万粉丝去查询,此时哪怕用redis缓存,一个key存在单redis节点上,再怎么优化达到10万并发很了不起了,现在一下子来了几十万的用户去redis查询,redis也不一定能扛得住,其他访问也要去等待,这样就一层一层的hong住了,导致其他系统也崩溃了,这就造成了缓存雪崩。
多级缓存
jvm内存-缓存(相比redis,要高一两个数量级,百万并发/s,因为没有远程请求操作,只有内存操作),但是jvm级别缓存有容量限制的,不像redis做缓存多节点,分片存储,哪怕只是存储热点数据也是不够的,因为到了这个地步,数据量何其庞大,即使百分之一的热点数据量,你可能要存储几个G的数据,那就太占JVM进程的内存了,不太合适,而且有的商品现在是热点数据,将来又不是,不及时清理会导致内存泄漏。
现在web应用是集群的,一旦单个wen应用更新了redis数据和JVM内存数据,其他web应用并没有更新,该如何?可以用发布订阅去更新其他web应用中redis和JVM中的数据。
关于此时的数据不一致性问题,就不需要过度关注了,你用了多级缓存还需要数据一致性,那整个架构的设计就更加复杂了。此时需要做一些权衡,用了多级缓存架构了,就不需要数据一致性了,此时的架构模式已经非常实时一致性了,我刚刚更新完就发了MQ消息,MQ消息效率也很高,只有一点点时间差,几乎可以忽略不计了。如果再用分布式锁再来一下,那你这个架构就太复杂了,以后可能就无法维护了,性能太低了。
热点缓存系统(大厂)
一般而言,维护缓存并不是在查询,或者更新操作之前取做的,而是有一个热点缓存系统;当然会让web应用与缓存做一个监听之类的操作,回头计算到哪些商品是热点数据,我会通知web应用,在后台去更新数据。这里我就只会去这个热点缓存系统去读一下热点数据,至于插入到热点缓存系统的操作,会在其他地方进行。
对redis的操作进行一个拦截aop,每一个操作都会往热点缓存系统(分布式实时计算去维护这个热点缓存的)发一个请求,进行一些规则计算,比如满足了什么样频率的请求redis的key值,会给web应用消息,保存进redis中。

