5.Redis【Java面试第三季】

2023-11-06 05:51
文章标签 java 面试 redis 第三季

本文主要是介绍5.Redis【Java面试第三季】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

5.Redis【Java面试第三季】

  • 前言
  • 推荐
  • 5.Redis
  • 40_redis版本升级说明
    • ==1.安装redis6.0.8==
  • 41_redis两个小细节说明
    • 2.redis传统五大数据类型的落地应用
      • 官网命令大全网址
      • 8大类型
      • 备注
  • 42_string类型使用场景
      • string
  • 43_hash类型使用场景
      • hash
  • 44_list类型使用场景
      • list
  • 45_set类型使用场景
      • set
  • 46_zset类型使用场景
      • zset
    • 3.知道分布式锁吗?有哪些实现方案?你谈谈对redis分布式锁的理解,删key的时候有什么问题?
  • 61_redis内存调整默认查看
    • 4.redis缓存过期淘汰策略
      • 粉丝反馈的面试题
      • Redis内存满了怎么办
        • Redis默认内存多少?在哪里查看?如何设置修改?
  • 62_redis打满内存OOM
        • 真要打满了会怎么样?如果Redis内存使用超出了设置的最大值会怎样?
        • 结论
  • 63_redis内存淘汰策略
      • redis缓存淘汰策略
        • 往redis里写的数据是怎么没了的?
          • redis过期键的删除策略
          • 三种不同的删除策略
          • 上述步骤都过堂了,还有漏洞吗?
          • 内存淘汰策略登场
        • 有哪些(redis6.0.8版本)
        • 你平时用哪一种
        • 如何配置、修改
  • 64_lru算法简介
    • 5. redis的LRU算法简介
      • Redis的LRU了解过吗?可否手写一个LRU算法
        • 是什么
        • 算法来源
  • 65_lru的思想
        • 设计思想
        • 编码手写如何实现LRU
  • 66_巧用LinkedHashMap完成lru算法
          • 案例01
  • 67_手写LRU-上
          • 案例02
  • 68_手写LRU-下
  • 最后

前言

2023-2-4 09:57:18

以下内容源自
【尚硅谷Java大厂面试题第3季,跳槽必刷题目+必扫技术盲点(周阳主讲)-哔哩哔哩】
仅供学习交流使用

推荐

Java开发常见面试题详解(LockSupport,AQS,Spring循环依赖,Redis)

5.Redis

40_redis版本升级说明

1.安装redis6.0.8

  • Redis官网:https://redis.io/
  • Redis中文网:http://redis.cn/
  • 安全Bug按照官网提示,升级成为6.0.8
    0355

进入Redis命令行,输入info,返回关于Redis服务器的各种信息(包括版本号)和统计数值。

在这里插入图片描述

PS D:\Desktop> redis-server -v
Redis server v=3.2.100 sha=00000000:0 malloc=jemalloc-3.6.0 bits=64 build=dd26f1f93c5130ee
PS D:\Desktop> redis-cli
127.0.0.1:6379>
PS D:\Desktop> redis-cli
127.0.0.1:6379> server
127.0.0.1:6379> info
# Server
redis_version:3.2.100
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:dd26f1f93c5130ee
redis_mode:standalone
os:Windows
arch_bits:64
multiplexing_api:WinSock_IOCP
process_id:7708
run_id:2cbe9a9a6851280c5c5684938945530f55e6675d
tcp_port:6379
uptime_in_seconds:456
uptime_in_days:0
hz:10
lru_clock:14532145
executable:E:\Redis-x64-3.2.100\redis-server.exe
config_file:

要升级成6,一定要升级到6.0.8
以下学习345都行

41_redis两个小细节说明

redis基本类型:

  • string
  • list
  • set
  • zset(sorted set)
  • hash

除了上述5大数据类型,其他redis的类型

  • bitmap
  • HyperLogLogs
  • GEO
  • Stream

2.redis传统五大数据类型的落地应用

官网命令大全网址

http://www.redis.cn/commands.html

8大类型

1.String(字符类型)
2.Hash(散列类型)
3.List(列表类型)
4.set(集合类型)
5.SortedSet(有序集合类型,简称zset)
6.Bitmap(位图)
7.HyperLogLog(统计)
8.GEO(地理)

备注

  • 命令不区分大小写,而key是区分大小写的
  • help @类型名词

42_string类型使用场景

string

最常用

  • SET key value
  • GET key

同时设置/获取多个键值

  • MSET key value [key value…]
  • MGET key [key…]

数值增减

  • 递增数字 INCR key(可以不用预先设置key的数值。如果预先设置key但值不是数字,则会报错)
  • 增加指定的整数 INCRBY key increment
  • 递减数值 DECR key
  • 减少指定的整数 DECRBY key decrement

获取字符串长度

  • STRLEN key

分布式锁

  • SETNX key value
  • SET key value [EX seconds] [PX milliseconds] [NX|XX]
    • EX:key在多少秒之后过期
    • PX:key在多少毫秒之后过期
    • NX:当key不存在的时候,才创建key,效果等同于setnx
    • XX:当key存在的时候,覆盖key

应用场景

  • 商品编号、订单号采用INCR命令生成
  • 是否喜欢的文章
    • 阅读数:只要点击了rest地址,直接可以使用incr key命令增加一个数字1,完成记录数字。

43_hash类型使用场景

hash

Redis的Hash类型相当于Java中Map<String, Map<Object, Object>>

一次设置一个字段值

  • HSET key field value

一次获取一个字段值

  • HGET key field

一次设置多个字段值

  • HMSET key field value [field value …]

一次获取多个字段值

  • HMGET key field [field …]

获取所有字段值

  • HGETALL key

获取某个key内的全部数量

  • HLEN

删除一个key

  • HDEL

应用场景

  • 购物车早期,当前小中厂可用

    • 新增商品 hset shopcar:uid1024 334488 1
    • 新增商品 hset shopcar:uid1024 334477 1
    • 增加商品数量 hincrby shopcar:uid1024 334477 1
    • 商品总数 hlen shopcar:uid1024
    • 全部选择 hgetall shopcar:uid1024

44_list类型使用场景

list

向列表左边添加元素

  • LPUSH key value [value …]

向列表右边添加元素

  • RPUSH key value [value …]

查看列表

  • LRANGE key start stop

获取列表中元素的个数

  • LLEN key

应用场景

  • 微信文章订阅公众号
    大V作者李永乐老师和CSDN发布了文章分别是11和22
    阳哥关注了他们两个,只要他们发布了新文章,就会安装进我的List
    lpush likearticle:阳哥id11 22
    查看阳哥自己的号订阅的全部文章,类似分页,下面0~10就是一次显示10条
    lrange likearticle:阳哥id 0 10

45_set类型使用场景

set

添加元素

  • SADD key member [member …]

删除元素

  • SREM key member [member …]

获取集合中的所有元素

  • SMEMBERS key

判断元素是否在集合中

  • SISMEMBER key member

获取集合中的元素个数

  • SCARD key

从集合中随机弹出一个元素,元素不删除

  • SRANDMEMBER key [数字]

从集合中随机弹出一个元素,出一个删一个

  • SPOP key[数字]

集合运算

  • 集合的差集运算A - B
    • 属于A但不属于B的元素构成的集合
    • SDIFF key [key …]
  • 集合的交集运算A ∩ B
    • 属于A同时也属于B的共同拥有的元素构成的集合
    • SINTER key [key …]
  • 集合的并集运算A U B
    • 属于A或者属于B的元素合并后的集合
    • SUNION key [key …]

应用场景

  • 微信抽奖小程序
  1. 用户ID,立即参与按钮
    SADD key 用户ID
  2. 显示已经有多少人参与了、上图23208人参加
    SCARD key
  3. 抽奖(从set中任意选取N个中奖人)
    SRANDMEMBER key 2(随机抽奖2个人,元素不删除)
    SPOP key 3(随机抽奖3个人,元素会删除)
  • 微信朋友圈点赞
  1. 新增点赞
    sadd pub:msglD 点赞用户ID1 点赞用户ID2
  2. 取消点赞
    srem pub:msglD 点赞用户ID
  3. 展现所有点赞过的用户
    SMEMBERS pub:msglD
  4. 点赞用户数统计,就是常见的点赞红色数字
    scard pub:msgID
  5. 判断某个朋友是否对楼主点赞过
    SISMEMBER pub:msglD用户ID
  • 微博好友关注社交关系
    • 共同关注:我去到局座张召忠的微博,马上获得我和局座共同关注的人
      sadd s1 1 2 3 4 5
      sadd s2 3 4 5 6 7
      SINTER s1 s2
    • 我关注的人也关注他(大家爱好相同)
      sadd s1 1 2 3 4 5
      sadd s2 3 4 5 6 7
      SISMEMBER s1 3
      SISMEMBER s1 2
  • QQ内推可能认识的人
    sadd s1 1 2 3 4 5
    sadd s2 3 4 5 6 7
    SINTER s1 s2
    SDIFF s1 s2
    SDIFF s2 s1

46_zset类型使用场景

zset

向有序集合中加入一个元素和该元素的分数

添加元素

  • ZADD key score member [score member …]

按照元素分数从小到大的顺序返回索引从start到stop之间的所有元素

  • ZRANGE key start stop [WITHSCORES]

获取元素的分数

  • ZSCORE key member

删除元素

  • ZREM key member [member …]

获取指定分数范围的元素

  • ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]

增加某个元素的分数

  • ZINCRBY key increment member

获取集合中元素的数量

  • ZCARD key

获得指定分数范围内的元素个数

  • ZCOUNT key min max

按照排名范围删除元素

  • ZREMRANGEBYRANK key start stop

获取元素的排名

  • 从小到大 ZRANK key member

  • 从大到小 ZREVRANK key member

建议:score设置为固定不变的量

应用场景

  • 根据商品销售对商品进行排序显示
    思路:定义商品销售排行榜(sorted set集合),key为goods:sellsort,分数为商品销售数量。
  1. 商品编号1001的销量是9,商品编号1002的销量是15
    zadd goods:sellsort 9 1001 15 1002
  2. 有一个客户又买了2件商品1001,商品编号1001销量加2
    zincrby goods:sellsort 2 1001
  3. 求商品销量前10名
    ZRANGE goods:sellsort 0 10 withscores
  • 抖音热搜
  1. 点击视频
    ZINCRBY hotvcr:20200919 1 八佰
    ZINCRBY hotvcr:20200919 15 八佰 2 花木兰
  2. 展示当日排行前10条
    ZREVRANGE hotvcr:20200919 0 9 withscores

3.知道分布式锁吗?有哪些实现方案?你谈谈对redis分布式锁的理解,删key的时候有什么问题?

61_redis内存调整默认查看

4.redis缓存过期淘汰策略

粉丝反馈的面试题

  • 生产上你们的redis内存设置多少?
  • 如何配置、修改redis的内存大小
  • 如果内存满了你怎么办?
  • redis清理内存的方式?定期删除和惰性删除了解过吗
  • redis缓存淘汰策略
  • redis的LRU了解过吗?可否手写一个LRU算法
  • 。。。

Redis内存满了怎么办

Redis默认内存多少?在哪里查看?如何设置修改?

查看Redis最大占用内存

  • 配置文件redis.conf的maxmemory参数,maxmemory是bytes字节类型,注意转换。
    0342

redis默认内存多少可以用?

  • 如果不设置最大内存大小或者设置最大内存大小为0,在64位操作系统下不限制内存大小,在32位操作系统下最多使用3GB内存

一般生产上你如何配置?

  • 一般推荐Redis设置内存为最大物理内存的四分之三。

如何修改redis内存设置

  • 修改配置文件redis.conf的maxmemory参数,如:maxmemory 104857600
  • 通过命令修改
    config set maxmemory 1024
    config get maxmemory

什么命令查看redis内存使用情况?

  • info memory

62_redis打满内存OOM

真要打满了会怎么样?如果Redis内存使用超出了设置的最大值会怎样?

我改改配置,故意把最大值设为1个byte试试

127.0.0.1:6379> config get maxmemory
1) "maxmemory"
2) "0"
127.0.0.1:6379> config set maxmemory 1
OK
127.0.0.1:6379> set a 123
(error) OOM command not allowed when used memory > 'maxmemory'.
结论
  • 设置了maxmemory的选项,假如redis内存使用达到上限
  • 没有加上过期时间就会导致数据写满maxmemory

为了避免类似情况,引出下一章内存淘汰策略

63_redis内存淘汰策略

redis缓存淘汰策略

往redis里写的数据是怎么没了的?
redis过期键的删除策略

如果一个键是过期的,那它到了过期时间之后是不是马上就从内存中被被删除呢?

如果回答yes,你自己走还是面试官送你?

如果不是,那过期后到底什么时候被删除呢??是个什么操作?

三种不同的删除策略

定期删除

Redis不可能时时刻刻遍历所有被设置了生存时间的key,来检测数据是否已经到达过期时间,然后对它进行删除。

立即删除能保证内存中数据的最大新鲜度,因为它保证过期键值会在过期后马上被删除,其所占用的内存也会随之释放。但是立即删除对cpu是最不友好的。因为删除操作会占用cpu的时间,如果刚好碰上了cpu很忙的时候,比如正在做交集或排序等计算的时候,就会给cpu造成额外的压力,让CPU心累,时时需要删除,忙死。

这会产生大量的性能消耗,同时也会影响数据的读取操作。

  • 总结:对CPU不友好,用处理器性能换取存储空间(拿时间换空间)

惰性删除

数据到达过期时间,不做处理。等下次访问该数据时,

如果未过期,返回数据;

发现已过期,删除,返回不存在。

惰性删除策略的缺点是,它对内存是最不友好的

如果一个键已经过期,而这个键又仍然保留在数据库中,那么只要这个过期键不被删除,它所占用的内存就不会释放。

在使用惰性删除策略时,如果数据库中有非常多的过期键,而这些过期键又恰好没有被访问到的话,那么它们也许永远也不会被删除(除非用户手动执行FLUSHDB),我们甚至可以将这种情况看作是一种内存泄漏 – 无用的垃圾数据占用了大量的内存,而服务器却不会自己去释放它们,这对于运行状态非常依赖于内存的Redis服务器来说,肯定不是一个好消息。

  • 总结:对memory不友好,用存储空间换取处理器性能(拿空间换时间)

上面两种方案都走极端

定期删除

定期删除策略是前两种策略的折中:

定期删除策略每隔一段时间执行一次删除过期键操作,并通过限制删除操作执行的时长和频率来减少删除操作对CPU时间的影响。

周期性轮询Redis库中的时效性数据,来用随机抽取的策略,利用过期数据占比的方式控制删除频度

特点1:CPU性能占用设置有峰值,检测频度可自定义设置

特点2:内存压力不是很大,长期占用内存的冷数据会被持续清理

总结:周期性抽查存储空间(随机抽查,重点抽查)

举例:

redis默认每个100ms检查,是否有过期的key,有过期key则删除。注意:redis不是每隔100ms将所有的key检查一次而是随机抽取进行检查(如果每隔100ms,全部key进行检查,redis直接进去ICU)。因此,如果只采用定期删除策略,会导致很多key到时间没有删除。

定期删除策略的难点是确定删除操作执行的时长和频率:如果删除操作执行得太频繁,或者执行的时间太长,定期删除策略就会退化成定时删除策略,以至于将CPU时间过多地消耗在删除过期键上面。如果删除操作执行得太少,或者执行的时间太短,定期删除策略又会和惰性删除束略一样,出现浪费内存的情况。因此,如果采用定期删除策略的话,服务器必须根据情况,合理地设置删除操作的执行时长和执行频率。

  • 定期抽样key,判断是否过期(存在漏网之鱼)
上述步骤都过堂了,还有漏洞吗?
  1. 定期删除时,从来没有被抽查到
  2. 惰性删除时,也从来没有被点中使用过

上述2步骤====>大量过期的key堆积在内存中,导致redis内存空间紧张或者很快耗尽

必须要有一个更好的兜底方案

内存淘汰策略登场
有哪些(redis6.0.8版本)
  • noeviction:不会驱逐任何key
  • volatile-lfu:对所有设置了过期时间的key使用LFU算法进行删除
  • volatile-Iru:对所有设置了过期时间的key使用LRU算法进行删除
  • volatile-random:对所有设置了过期时间的key随机删除
  • volatile-ttl:删除马上要过期的key
  • allkeys-lfu:对所有key使用LFU算法进行删除
  • allkeys-Iru:对所有key使用LRU算法进行删除
  • allkeys-random:对所有key随机删除

上面总结

  • 2*4得8
  • 2个维度
    • 过期键中筛选
    • 所有键中筛选
  • 4个方面
    • LRU
    • LFU
    • random
    • ttl(Time To Live)
  • 8个选项
你平时用哪一种

allkeys-Iru:对所有key使用LRU算法进行删除

不使用noeviction,redis服务会崩
不敢使用random,可能删除热点key

如何配置、修改
  • 命令
    • config set maxmemory-policy noeviction
    • config get maxmemory
  • 配置文件
    • 配置文件redis.conf的maxmemory-policy参数

64_lru算法简介

5. redis的LRU算法简介

Redis的LRU了解过吗?可否手写一个LRU算法

是什么

LRU是Least Recently Used的缩写,即最近最少使用,是一种常用的页面置换算法

选择最近最久未使用的数据予以淘汰。

算法来源

LeetCode - Medium - 146. LRU Cache

65_lru的思想

设计思想

1.所谓缓存,必须要有读+写两个操作,按照命中率的思路考虑,写操作+读操作时间复杂度都需要为O(1)
2.特性要求
2.1 必须要有顺序之分,一区分最近使用的和很久没有使用的数据排序。
2.2 写和读操作一次搞定。
2.3 如果容量(坑位)满了要删除最不长用的数据,每次新访问还要把新的数据插入到队头(按照业务你自己设定左右那一边是队头)
查找快、插入快、删除快,且还需要先后排序---------->什么样的数据结构可以满足这个问题?

你是否可以在O(1)时间复杂度内完成这两种操作?

如果一次就可以找到,你觉得什么数据结构最合适?

  • LRU的算法核心是哈希链表
    本质就是HashMap + DoubleLinkedList
    时间复杂度是O(1),哈希表+双向链表的结合体
编码手写如何实现LRU

66_巧用LinkedHashMap完成lru算法

  • 参考LinkedHashMap
    This kind of map is well-suited to building LRU caches.
  • 依赖JDK
案例01
package lru;import java.util.LinkedHashMap;
import java.util.Map;public class LRUCacheDemo<K,V> extends LinkedHashMap<K,V> {private int capacity;//缓存坑位/**** accessOrder – the ordering mode -*      true for access-order,*      false for insertion-order*/public LRUCacheDemo(int capacity) {super(capacity,0.75f,true);this.capacity = capacity;}@Overrideprotected boolean removeEldestEntry(Map.Entry<K, V> eldest) {return super.size() > capacity;}public static void main(String[] args) {LRUCacheDemo lruCacheDemo = new LRUCacheDemo(3);lruCacheDemo.put(1,"a");lruCacheDemo.put(2,"b");lruCacheDemo.put(3,"c");System.out.println(lruCacheDemo.keySet());//[1, 2, 3]lruCacheDemo.put(4,"d");System.out.println(lruCacheDemo.keySet());//[2, 3, 4]lruCacheDemo.put(3,"c");System.out.println(lruCacheDemo.keySet());//[2, 4, 3]lruCacheDemo.put(4,"d");System.out.println(lruCacheDemo.keySet());//[2, 3, 4]lruCacheDemo.put(3,"c");System.out.println(lruCacheDemo.keySet());//[2, 4, 3]lruCacheDemo.put(3,"c");System.out.println(lruCacheDemo.keySet());//[2, 4, 3]lruCacheDemo.put(3,"c");System.out.println(lruCacheDemo.keySet());//[2, 4, 3]lruCacheDemo.put(5,"x");System.out.println(lruCacheDemo.keySet());//[4, 3, 5]}/***  accessOrder – the ordering mode -*      true for access-order,  访问顺序* [1, 2, 3]* [2, 3, 4]* [2, 4, 3]* [2, 3, 4]* * [2, 4, 3]* [2, 4, 3]* [2, 4, 3]* * [4, 3, 5]*//**** accessOrder – the ordering mode -*      false for insertion-order 插入顺序** [1, 2, 3]* [2, 3, 4]* [2, 3, 4]* [2, 3, 4]* * [2, 3, 4]* [2, 3, 4]* [2, 3, 4]* * [3, 4, 5]*/
}

67_手写LRU-上

案例02
  • 不依赖JDK

完成数据结构 哈希表 + 双向链表

package lru;import java.util.HashMap;
import java.util.Map;public class LRUCacheDemo {//map复杂查找,构建一个虚拟的双向链表,它里面安装的就是一个个Node结点,作为数据载体。//构造一个Node结点,作为数据载体。class Node<K,V>{K key;V value;Node<K, V> prev;Node<K, V> next;public Node() {this.prev = this.next = null;}public Node(K key, V value) {this.key = key;this.value = value;this.prev = this.next = null;}}//2 构造一个双向队列,里面安放的就是我们的Nodeclass DoubleLinkedList<K, V>{Node<K, V> head;Node<K, V> tail;//2.1构造方法public DoubleLinkedList() {//头尾哨兵节点this.head = new Node<K, V>();this.tail = new Node<K, V>();this.head.next = this.tail;this.tail.prev = this.head;}//2.2 添加到头public void addHead(Node<K, V> node) {node.next = head.next;node.prev = head;head.next.prev = node;head.next = node;}//2.3删除结点public void removeNode(Node<K, V> node) {node.next.prev = node.prev;node.prev.next = node.next;node.prev = null;node.next = null;}//2.4获得最后一个结点public Node<K, V> getLast() {return tail.prev;}}private int cacheSize;private Map<Integer, Node<Integer, Integer>> map;private DoubleLinkedList<Integer, Integer> doubleLinkedList;public LRUCacheDemo(int cacheSize) {//该写构造方法了}}

68_手写LRU-下

完成算法 LRU

package lru;import java.util.HashMap;
import java.util.Map;public class LRUCacheDemo {//map复杂查找,构建一个虚拟的双向链表,它里面安装的就是一个个Node结点,作为数据载体。//构造一个Node结点,作为数据载体。class Node<K,V>{K key;V value;Node<K, V> prev;Node<K, V> next;public Node() {this.prev = this.next = null;}public Node(K key, V value) {this.key = key;this.value = value;this.prev = this.next = null;}}//2 构造一个双向队列,里面安放的就是我们的Nodeclass DoubleLinkedList<K, V>{Node<K, V> head;Node<K, V> tail;//2.1构造方法public DoubleLinkedList() {//头尾哨兵节点this.head = new Node<K, V>();this.tail = new Node<K, V>();this.head.next = this.tail;this.tail.prev = this.head;}//2.2 添加到头public void addHead(Node<K, V> node) {node.next = head.next;node.prev = head;head.next.prev = node;head.next = node;}//2.3删除结点public void removeNode(Node<K, V> node) {node.next.prev = node.prev;node.prev.next = node.next;node.prev = null;node.next = null;}//2.4获得最后一个结点public Node<K, V> getLast() {return tail.prev;}}private int cacheSize;private Map<Integer, Node<Integer, Integer>> map;private DoubleLinkedList<Integer, Integer> doubleLinkedList;public LRUCacheDemo(int cacheSize) {this.cacheSize = cacheSize;map=new HashMap<>();doubleLinkedList =new DoubleLinkedList<>();}public int get(int key) {if(!map.containsKey(key)) {return -1;}Node<Integer, Integer> node = map.get(key);//更新节点位置,将节点移置链表头doubleLinkedList.removeNode(node);doubleLinkedList.addHead(node);return node.value;}//saveOrUpdate methodpublic void put(int key, int value) {if(map.containsKey(key)) {//updateNode<Integer, Integer> node = map.get(key);node.value = value;map.put(key, node);doubleLinkedList.removeNode(node);doubleLinkedList.addHead(node);}else {if(map.size() == cacheSize) {//如果已达到最大容量了,把旧的移除,让新的进来Node<Integer, Integer> lastNode = doubleLinkedList.getLast();map.remove(lastNode.key);//node.key主要用处,反向连接mapdoubleLinkedList.removeNode(lastNode);}//才是新增Node<Integer, Integer> newNode = new Node<>(key, value);map.put(key, newNode);doubleLinkedList.addHead(newNode);}}public static void main(String[] args) {LRUCacheDemo lruCacheDemo = new LRUCacheDemo(3);lruCacheDemo.put(1,1);lruCacheDemo.put(2,2);lruCacheDemo.put(3,3);System.out.println(lruCacheDemo.map.keySet());//[1, 2, 3]lruCacheDemo.put(4,1);System.out.println(lruCacheDemo.map.keySet());//[2, 3, 4]lruCacheDemo.put(3,1);System.out.println(lruCacheDemo.map.keySet());//[2, 3, 4]lruCacheDemo.put(3,1);System.out.println(lruCacheDemo.map.keySet());//[2, 3, 4]lruCacheDemo.put(3,1);System.out.println(lruCacheDemo.map.keySet());//[2, 3, 4]lruCacheDemo.put(5,1);System.out.println(lruCacheDemo.map.keySet());//[3, 4, 5]}}

最后

2023-2-4 19:06:24

这篇博客能写好的原因是:站在巨人的肩膀上

这篇博客要写好的目的是:做别人的肩膀

开源:为爱发电

学习:为我而行

这篇关于5.Redis【Java面试第三季】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/354815

相关文章

在Ubuntu上部署SpringBoot应用的操作步骤

《在Ubuntu上部署SpringBoot应用的操作步骤》随着云计算和容器化技术的普及,Linux服务器已成为部署Web应用程序的主流平台之一,Java作为一种跨平台的编程语言,具有广泛的应用场景,本... 目录一、部署准备二、安装 Java 环境1. 安装 JDK2. 验证 Java 安装三、安装 mys

Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单

《Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单》:本文主要介绍Springboot的ThreadPoolTaskScheduler线... 目录ThreadPoolTaskScheduler线程池实现15分钟不操作自动取消订单概要1,创建订单后

详谈redis跟数据库的数据同步问题

《详谈redis跟数据库的数据同步问题》文章讨论了在Redis和数据库数据一致性问题上的解决方案,主要比较了先更新Redis缓存再更新数据库和先更新数据库再更新Redis缓存两种方案,文章指出,删除R... 目录一、Redis 数据库数据一致性的解决方案1.1、更新Redis缓存、删除Redis缓存的区别二

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

Redis与缓存解读

《Redis与缓存解读》文章介绍了Redis作为缓存层的优势和缺点,并分析了六种缓存更新策略,包括超时剔除、先删缓存再更新数据库、旁路缓存、先更新数据库再删缓存、先更新数据库再更新缓存、读写穿透和异步... 目录缓存缓存优缺点缓存更新策略超时剔除先删缓存再更新数据库旁路缓存(先更新数据库,再删缓存)先更新数

Redis事务与数据持久化方式

《Redis事务与数据持久化方式》该文档主要介绍了Redis事务和持久化机制,事务通过将多个命令打包执行,而持久化则通过快照(RDB)和追加式文件(AOF)两种方式将内存数据保存到磁盘,以防止数据丢失... 目录一、Redis 事务1.1 事务本质1.2 数据库事务与redis事务1.2.1 数据库事务1.

SpringCloud集成AlloyDB的示例代码

《SpringCloud集成AlloyDB的示例代码》AlloyDB是GoogleCloud提供的一种高度可扩展、强性能的关系型数据库服务,它兼容PostgreSQL,并提供了更快的查询性能... 目录1.AlloyDBjavascript是什么?AlloyDB 的工作原理2.搭建测试环境3.代码工程1.

mac安装redis全过程

《mac安装redis全过程》文章内容主要介绍了如何从官网下载指定版本的Redis,以及如何在自定义目录下安装和启动Redis,还提到了如何修改Redis的密码和配置文件,以及使用RedisInsig... 目录MAC安装Redis安装启动redis 配置redis 常用命令总结mac安装redis官网下

Java调用Python代码的几种方法小结

《Java调用Python代码的几种方法小结》Python语言有丰富的系统管理、数据处理、统计类软件包,因此从java应用中调用Python代码的需求很常见、实用,本文介绍几种方法从java调用Pyt... 目录引言Java core使用ProcessBuilder使用Java脚本引擎总结引言python

SpringBoot操作spark处理hdfs文件的操作方法

《SpringBoot操作spark处理hdfs文件的操作方法》本文介绍了如何使用SpringBoot操作Spark处理HDFS文件,包括导入依赖、配置Spark信息、编写Controller和Ser... 目录SpringBoot操作spark处理hdfs文件1、导入依赖2、配置spark信息3、cont