在Java中, volatile关键字可以保证变量的可见性,如果我们将变量声明为 volatile,这就指示 JVM,这个变量是共享且不稳定的,每次使用它都到主存中进行读取。
Java内存模型:
1.Java所有变量都存储在主内存中
2.每个线程都有自己独立的工作内存
变量副本就是主内存中该变量的一份拷贝
1.线程对共享变量的所有操作都必须在自己的工作内存中进行,不能直接在主内存中读写
2.不同线程之间无法直接访问其他线程工作内存中的变量,线程间变量值的传递需要通过主内存来完成
可见性:一个线程对共享变量的修改,能够及时的被其他线程看到的
如上图:线程1在它的工作内存1对共享变量修改,更新到主内存中,将主内存中最新的共享变量更新到线程2 的工作内存2中。
volatile实现内存可见性是通过store和load指令完成的;也就是对volatile变量执行写操作时,会在写操作后加入一条store指令,即强迫线程将最新的值刷新到主内存中;而在读操作时,会加入一条load指令,即强迫从主内存中读入变量的值。
常用的过期数据的删除策略就两个
1.惰性删除:只会在取出key的时候才对数据进行过期检查。这样对CPU最友好,但是可能会造成太多过期key没有被删除。
2.定期删除:每隔一段时间抽取一批key执行删除过期key操作。并且,redis底层会通过限制删除操作执行的时长和频率来减少删除操作对CPU时间的影响。
定期删除对内存更加友好。惰性删除对CPU更加友好。redis一般采用的是定期删除+惰性/懒汉式删除
但是,仅仅通过给key设置过期时间还是有问题的。因为还是可能存在定期删除和惰性删除漏掉了很多过期key的情况。这样就导致大量过期key堆积在内寸中,然后㐇 Out of memory 了 。
解决方案:Redis内寸淘汰机制
6种数据淘汰策略:
volatile-lru(least recently used):从已设置过期时间的数据集中挑选最近最少使用的数据淘汰
volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰
volatile-random:从已设置过期时间的数据集中任意选择数据淘汰
allkeys-lru:当内寸不足以容纳新写入数据时,在键空间中,移除最近最少使用的key(最常用)
allkeys-random:从数据集中任意选择数据淘汰
no-eviction:禁止驱逐数据,也就是说当内存不足以容纳新写入数据时。新写入操作会报错。
4.0版本后增加以下两种:
volatile-lfu(least frequently used):从已设置过期时间的数据集中挑选最不经常使用的数据淘汰
allkeys-lfu:当内寸不足以容纳新写入数据时,在键空间中,移除最不经常使用的key。