day06-缓存,redisson

1.查询缓存

为了系统性能的提升,一般都会将数据放入缓存中,加速访问。而db承担数据的持久化操作

高并发系统,缓存是必备的

 

2.压力测试工具

jmeter

 

3.分布式的锁

由于以前的锁都是进程内的锁,所以在分布式系统下并没有效果,这里就需要更加先进的适合分布式的锁

锁的原理就是多个线程使用同一把锁

以前的锁:进程内的锁

RPC需要的是进程间的锁

 

 

spring的组件是单例模式的,就算有100个Controller请求,spring也只会注入一个bean.所以一个Sereviced的锁是同一个锁

所以在Service通过synchronized(this)可以锁住,通过synchronize(组件)也可以锁住当前线程,因为bean是单实例的

 

那么分布式下怎么办呢?

1)加锁操作一定要是原子性的。这里的思想就是利用了redis,往redis中存一个值,其他线程想获取锁就是从redis取出这个值,谁拿到了这个值谁就拿到了锁,没拿到的就自旋等待。因为redis是单线程的,所以可以把操作弄成一个原子操作,,即setnx 也就是set if not exist

Integer lock = setnx("lock","111")

lock =0说明已经有人获得锁,此次获取失败,lock=1说明可以开始获取锁,即别人没有占用锁,setnx能保证就算1万个线程进来也只有一个线程可以执行setnx得到值1

但是这个时候如果得到锁的线程无限循环等原因导致锁没释放,其他线程永远自旋等待

2)设置过期时间        加锁和设置过期时间也必须是原子性的,这两个操作合在一起是原子操作。也就是这样设置 set lock ex 10 nx

(设置一个key叫做lock,超时时间10s,当该key不存在时执行),用这个代替setnx lock,即多了超时时间

String ok = setnxex().还要保证删除的锁是自己的锁,把自己的uuid作为key存进redis,最后的问题是我们获取锁时,锁的值正在给我们返回的过程中过期了,redis删除了该key,这里的原因又是因为删除锁不是原子操作的

 

所以,分布式锁的核心

1)加锁一定要是原子性的

2)锁要设置超时时间

3)解锁也要是原子性的

 

 

锁的考虑

1)自旋

      自旋次数

      自旋超时

2)锁设置

       锁粒度:细,记录级别

              a)各自服务各自的锁

             b)分析好粒度,不要锁住无关数据。一种数据一种锁,一条数据一个锁

3)锁类型

       读写锁

       。。。

 

要解决上述的考虑,就要用到redisson了

附上redisson的github地址:https://github.com/redisson/redisson/wiki/8.-%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E5%92%8C%E5%90%8C%E6%AD%A5%E5%99%A8

 

我们知道CAP原理,很多时候电商的操作也是最后满足最终一致性就行了,原来我们想的的读取商品时加读锁,修改商品时加写锁,读取商品就是说先从缓存读,读不到再去数据库,写商品是写入数据库的时候同时写入缓存,但是这里会出现一个问题,假如我写入的是一个大对象,要5s钟,由于是读写锁,读商品的线程是阻塞的,假如这个时候来了100W个请求,堵在这里5s,就会出问题,为了解决这个问题,我们可以通过最终一致性来解决,也就是在真正下单的时候会再去访问一次缓存或者数据库,而从你浏览商品到下单的这段时间数据库与缓存已经完成了同步。我们只在下单的时候加上读锁,这样就避免了上述的问题

 

所以分布式锁这样用:缓存双写+读写锁

 

缓存使用模式分为两大类:Cache-Aside和Cache As SoR

专业名词:

  • SoR(system-of-record):记录系统,或者可以叫数据源,实际存储原始数据的系统

  • Cache:缓存,是SoR的快照数据,Cache的访问速度比SoR要快,放入Cache的目的是提升系统速度,减少回源到SoR的次数

  • 回源:回到数据源头检索数据,Cache没有命中需要回到SoR读取数据,这叫做回源

 

缓存使用模式一:CacheAside

也就业务代码围绕着缓存编写

 

 

 

 

 

写缓存框架时需要考虑缓存污染,为了缓存的安全,应该这样做

1)读到数据,然后BeanUtil复制一个,用复制的数据(读时复制)

2)缓存框架给我们写数据的时候,new一个一模一样的给我们(写时复制)

即如果用内存级别缓存,一定要考虑污染问题

redis就不要考虑缓存污染问题,因为redis不是内存级缓存,是靠的序列化与反序列化

 

缓存使用两种复制模式,注意。Copy-On-Read(读时复制)、Copy-On-Write(写时复制)。

有些进程内缓存很多是基于引用的,所以拿到缓存中的数据如果进行修改,可能发生不可预测的问题。

读时复制:读取到的缓存的值,复制内容封装一个新的对象。

写时复制:给缓存中写的值,复制一个新的对象写入

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值