赣州新闻网

首页 / 科技

比特币是不是庞氏骗局?看完这篇文你就懂了

2020-01-10 · 赣州新闻网 · 科技

0 欢迎关注 https://github.com/Wasabi1234

欢迎关注全是干货的技术公众号

突破Java面试(22) - Redis过期策略及手写LRU

1 面试题

Redis的过期策略都有哪些?内存淘汰机制都有哪些?手写一下LRU代码实现?

2 考点分析

1)往redis里写的数据怎么没了?

生产环境的redis怎么经常会丢掉一些数Q = ^ ~ l O h据?写进去了,过一会儿可能就没了。

问这个问题就说明redis你就H p K V * 2 s Eredis是缓存,你给当存储了是吧?

啥叫缓存?8 U P 用内存当缓存。内存是无限的吗,内存是很宝贵而且是有限的,而i 5 = c ` Z i $磁盘是廉价且大量的!可能一台机器就几十个G的内存,但是可以有几个T的硬盘空间。redis主要是基于内存来进行高f z T q j {性能、高并发的读写操作的。

那既然内存是有限的,比如redis就只能用10个G,你要是往里面` 7 9 f写了20个G的数据,会咋办?当然会干掉10个G的数据,然b H 1 / [后就保留10个G的数据了。那干掉哪些数据?保留哪些数据?当然是干掉不常用的数据,保留常用的数据了。

所以说,这是缓存的一X & P s 8 v a个最} p f e基本的概念,数据是会过期的,要么是你6 D i !自己设置个过期时间,要么是redis自己给干掉H ! } z ` J t -。

set key value 过期时间(c B } * / E ? S  g 4 - ~失效了

2)数据明明都过期了,怎么还占用着内存?

还有一种就E ; w ( 8 ) M d是如果你设置好了一个过期时间,你知道redis是怎么给你弄成过期的吗?什么时候删除掉?如果你不知道,之前有个人就问了,为啥好多数v O ] # }据明明应该过期了,结果发现redis内存占用还是很高?那是因为你不知道redis是怎么删除那些过期key的。

redis 内存一共是10g,你现在往里面写了5g的数据,结果这G N ^些数据明明你都设置了过期时间,要求这些数据1小时之后都会$ ~ b 3 s S N D过期,结果1小时之后,你回来一看,redis机器,怎么内存占用还是50%呢?5g数据过期了,我从redis里查,是查不到了,结果过. ! 6 E j Q A X 8期的数据还占用着redis的内存。

如果你连这个问题都不知道,上来就懵了,回答不出来,那线上你写代码的时候,想当然的认为写进redis的数据就一定会存在,后面导致系统各, k R种漏洞和bug,谁来负责?

3 详解


3.1 设置过期时间

我们set key的时候,都可以给一个expire time,就是过期时间,指定这个key比如说只能存活1个小时?10分钟?这b k T { ) ! o j k个很有用D o 7 6 W,我们自己可以指定缓存到期就失效。

如果假设你设x ? )置一个一批key只能存活1个小时,那么接下来1小时后,redis是怎么对这批key进行删除的?

答案是:定期删除+惰性删除

定期删除

指的 % . a X B | 1是[ K + G #redis默认是每隔100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就B l C N a 删除。

假设redis里R * L X K A H Y 放了10万个key,都设置了过期时间,你每隔几百毫秒,就检查10万个key,那redis基本上就死了,cpu负载会很高的,消耗在你的检查过期key上了。

注意,这里可不是每隔100ms就4 S [ & - [ 0遍历所有的设置过期时间的key,那样就是一场性能上的灾难。实际上redis是每隔100ms随机抽取一些key来检Y j K ^ w m a { ?查和删除的。

但是问题是,定期删除可能会导致N p 6 B很多过期key到了时间并没有被删除掉,那咋整呢?所以就是

惰性删除

这就是说,在你获取某个key的时候, J [ & ` G W $,redis会检查一下 ,这个key如果设置了过期时@ ? { n s X X在已经满了,redis需要删除掉5个key

1个key,最近1分钟被查询了100次n 6 Y 7 = W I l1个key,最近10分钟被查询了50次1个key,最近q 7 B X m 9 L ; U1个小时倍查询了1次

  • noeviction:当内存不足以容纳新写入数据时,新写入操作会报错,这个一般没. Z L H人用吧,(太恶心了,但是默认的)
  • allkeys-lru:当内存不足以容纳m { J新写入数据时,在键空间中,移除最近最少使用的key(最常用)
  • allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个keK D 3 U 6 2 Zy,这个一般没人用吧,为啥要随机,肯定是把最近最少使用的key给h Z q ( } _ y干掉
  • volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key(不太合适)
  • volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空s R o { 1 L :间中,随机移除某个key
  • volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期# L c F ^ 9时间的key优先移除@ j ? } u 1

3.3 手写一个LRU

确实有时会问这个,因为有些候选人如果确实过五关斩六将,前面- | . J ] ] Y S v的问题都答的很好,那么其实让他写一下LRU算法,可以考察一下编码功底

你可以现场手写最原始的LRU算法,那个代码量太大了,不太现实

public class LRUCach& : ; C Xe<K, V&g$ C $ u ? It; extends LinkedHashMap<K, V> {

private final int CACHE_SIZE;

// 这里就是传递进来最多能缓存多少数据
public LRUCache(int cacheSize) {
sq : quper((int) Math.ceil(cacheSize / 0.75) + 1, 0.75f, true); // 这块就是设置一个hashmap的初始大小,同时最后一个true指的是让linkedhasC k I zhmap按照访问顺序来进行排序,最近访问的放在头,最老访n j { z 1 U %问的就在尾
CACHE_SIZE = caj p L . 2 x ` Y ]cheSt o 0 { c Vize;
}

@Override
protected boolean rem& R 3 + x R ` b FoveEldestEntry(Map.Entry el[ f 9 r edey $ 5 /st) {
return size() > CACHE_SIZE; // 这个意思就是说当map中的数据量大于指定的缓存个数的时候,就自动删J ? ) t X ! v $除最老的数据S ? U 6 H
}

}

最起码你也得写出来上面那L ! R t y # Q ;种代码,不求自己纯手工从底层开始打造出自己的LRU,但是起码知道如何利用已有的jdk数据结构实现一个java版的LRU

参考

《Jav o f I $va工程师面试突击第1季-中华石杉老师》

设置考察不出这是东西让他候选人石城比特币