Redis面试
Redis的使用场景有哪些?缓存、分布式锁、计数器、消息队列、延迟队列等等。比较重要的就两个方面:
缓存:穿透、击穿、雪崩、双写一致、持久化、数据过期、数据淘汰
分布式锁:setnx、redisson
缓存穿透问题即查询一个数据库中不存在的数据,而引发的问题。请求先去查询 Redis 缓存,发现缓存中没有,然后去查找数据库,结果数据库中也没有,所以不会写入缓存,这就导致每次请求都会去查询数据库。
和缓存击穿的区别在于,击穿主要是因为 Key 过期了。
解决方案一:缓存空数据。
数据库中查询为空,则把这个空结果进行缓存。优点是简单,缺点是消耗内存,并且可能会发生不一致的问题。
解决方案二:布隆过滤器。
查询 Redis 之前,先经过布隆过滤器,若不存在则直接返回,不会去查询 Redis,也不会去查数据库。优点是内存占用较少,缺点是实现复杂并存在误判。
布隆过滤器布隆过滤器依赖着 bitmap(位图)这样的数据结构,它用于快速检索一个元素是否存在在一个集合中。原理是将数据用多个哈希函数进行计算,并将位图数组的对应位置修改为 1。当过滤时,同样用多个哈希函数进行计算,若发现计 ...
消息队列
一、RabbitMQ 在项目中的使用1.1 基本配置1.1.1 两个交换机配置(1) 订单实际消费队列(死信队列)绑定的交换机。也即,延迟队列中的消息过期后,会经该交换机转发到死信队列中去:
DirectExchange orderDirect() { return ExchangeBuilder .directExchange(QueueEnum.QUEUE_ORDER_CANCEL.getExchange()) .durable(true) .build();}
directExchange 代表这是一个直连交换机,名称从枚举类 QueueEnum 中获取(按顺序分别是交换机名称,队列名称,路由键):
QUEUE_ORDER_CANCEL("mall.order.direct", "mall.order.cancel", "mall.order.cancel");
durable(true) 表示该交换机是持久化的,即 Rabbit ...
SpringBoot一些笔记
初识SpringBootSpringBoot 是一个基于 Spring 的套件,它帮我们预组装了 Spring 的一系列组件,以便以尽可能少的代码和配置来开发基于 Spring 的 Java 应用程序。
以汽车为例,如果我们想组装一辆汽车,我们需要发动机、传动、轮胎、底盘、外壳、座椅、内饰等各种部件,然后把它们装配起来。Spring 就相当于提供了一系列这样的部件,但是要装好汽车上路,还需要我们自己动手。而 SpringBoot 则相当于已经帮我们预装好了一辆可以上路的汽车,如果有特殊的要求,例如把发动机从普通款换成涡轮增压款,可以通过修改配置或编写少量代码完成。
SpringBoot的项目结构SpringBoot 的目标就是提供一个开箱即用的应用程序架构,我们基于 SpringBoot 的预置结构继续开发,省时省力。SpringBoot 的标准工程项目结构:
pom.xml
src
main
java
resources
application.yml
logback-spring.xml
static
templates
target
SpringBoot 默认的 ...
数学技巧
什么是数学技巧运用数学的技巧来解决复杂(有趣)的算法问题。
Nim游戏力扣题目链接你和你的朋友,两个人一起玩 Nim 游戏:桌子上有一堆石头。你们轮流进行自己的回合,你作为先手。每一回合,轮到的人拿掉 1 - 3 块石头。拿掉最后一块石头的人就是获胜者。假设你们每一步都是最优解。请编写一个函数,来判断你是否可以在给定石头数量为 n 的情况下赢得游戏。如果可以赢,返回 true;否则,返回 false。
作为先手,石头数量为 4 的倍数则必输
class Solution { public boolean canWinNim(int n) { return n % 4 != 0; }}
石子游戏力扣题目链接Alice 和 Bob 用几堆石子在做游戏。一共有偶数堆石子,排成一行;每堆都有正整数颗石子,数目为 piles[i]。游戏以谁手中的石子最多来决出胜负。石子的总数是奇数,所以没有平局。Alice 和 Bob 轮流进行,Alice 先开始。每回合,玩家从行的开始或结束处取走整堆石头。这种情况一直持续到没有更多的石子 ...
堆
认识堆堆(heap)是一种满足特定条件的完全二叉树,主要可分为两种类型:
小顶堆:任意节点的值 <= 其子节点的值
大顶堆:任意节点的值 >= 其子节点的值
堆作为完全二叉树的一个特例,具有以下特性:
最底层节点靠左填充,其他层的节点都被填满。
我们将二叉树的根节点称为堆顶,将底层最靠右的节点称为堆底
对于大顶堆(小顶堆),堆顶元素即根节点的值是最大(最小)的
实际上,堆通常用于实现优先队列,大顶堆相当于元素按从大到小的顺序出队的优先队列。从使用角度来看,我们可以将优先队列和堆看作等价的数据结构。Java中堆的一些操作使用优先队列来实现,具体代码如下所示:
// 初始化小顶堆Queue<Integer> minHeap = new PriorityQueue<>();// 初始化大顶堆(使用 lambda 表达式修改 Comparator 即可)Queue<Integer> maxHeap = new PriorityQueue<>((a, b) -> b - a);/* 元素入堆 */max ...
字符串
认识字符串在学习算法的过程中,我们经常会遇到输入是字符串的题目,然后利用各种技巧例如标准库、动态规划,或者是一些字符串遍历的技巧来解决问题。
反转字符串力扣题目链接编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
双指针技巧,每次交换最左与最右的字符
class Solution { public void reverseString(char[] s) { for (int i = 0; i < s.length / 2; i++) { char tem = s[s.length - i - 1]; s[s.length - i - 1] = s[i]; s[i] = tem; } }}
反转字符串Ⅱ力扣题目链接给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。如果剩余字符少于 k 个,则将剩余字 ...