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