20240122面试练习题10

1. Redis为什么执行这么快?

二、Redis为什么这么快?
1、完全基于内存,数据存在内存中,绝大部分请求是纯粹的内存操作,非常快速,跟传统的磁盘文件数据存储相比,避免了通过磁盘IO读取到内存这部分的开销。

2、数据结构简单,对数据操作也简单。Redis中的数据结构是专门进行设计的,每种数据结构都有一种或多种数据结构来支持。Redis正是依赖这些灵活的数据结构,来提升读取和写入的性能。

3、采用单线程,省去了很多上下文切换的时间以及CPU消耗,不存在竞争条件,不用去考虑各种锁的问题,不存在加锁释放锁操作,也不会出现死锁而导致的性能消耗。

4、使用基于IO多路复用机制的线程模型,可以处理并发的链接。


2. Redis是单线程执行还是多线程执行?它有线程安全问题吗?为什么吗?

1、Redis5及之前是单线程版本
2、Redis6开始引入多线程版本(单线程+多线程 版本)
请求是多线程的,但核心的内存读写操作(或者说读写计算)仍然是单线程的。

线程安全的场景:
1、单个键的读写操作:对于单个键的读操作和写操作是线程安全的。多个线程可以同时读取或写入同一个键,不会引发并发问题。
例如:

SET key value
GET key

2、原子操作:Redis 提供了一些原子性的操作,例如 INCR、LPUSH、SADD 等。这些操作是线程安全的,多个线程同时执行也不会引发问题。
例如:

INCR counter
LPUSH mylist value
SADD myset value

3、发布与订阅:Redis 的发布与订阅功能是线程安全的,多个线程可以同时进行发布和订阅操作。 例如:

PUBLISH channel message
SUBSCRIBE channel

线程不安全的场景:1、多个键的事务操作:如果多个线程同时对不同的键进行事务操作,可能会引发竞态条件。在这种情况下,需要使用分布式锁或其他并发控制技术来保证操作的一致性。
例如:

MULTI
SET key1 value1
SET key2 value2
EXEC

2、对于同一个键的并发写操作:如果多个线程同时对同一个键进行写操作,可能会引发竞态条件。在这种情况下,需要使用分布式锁或其他并发控制技术来保证操作的一致性。
例如:

SET key value1
SET key value2

总之,对于单个键的读写操作、原子操作和发布与订阅功能,Redis 是线程安全的。但在多个键的事务操作和对同一个键的并发写操作时,需要注意并发问题,并使用适当的并发控制机制来保证数据的一致性。


3. 在实际工作中,使用Redis实现了哪些业务场景?

1、缓存
例如:热点数据缓存(商品信息详情),可以提升热点数据的访问效率。

2、分布式锁
String 类型setnx方法,只有不存在时才能添加成功,返回true

public static boolean getLock(String key) {
    Long flag = jedis.setnx(key, "1");
    if (flag == 1) {
        jedis.expire(key, 10);
    }
    return flag == 1;
}

public static void releaseLock(String key) {
    jedis.del(key);
}

3、全局ID
int类型,incrby,利用原子性

incrby userid 1000

分库分表的场景,一次性拿一段

4、计数器
int类型,incr方法
例如:文章的阅读量、微博点赞数、允许一定的延迟,先写入Redis再定时同步到数据库

5、限流
int类型,incr方法
以访问者的ip和其他信息作为key,访问一次增加一次计数,超过次数则返回false

6、位统计
String类型的bitcount
字符是以8位二进制存储的

例如:在线用户统计,留存用户统计

setbit onlineusers 01 
setbit onlineusers 11 
setbit onlineusers 20

7、购物车
String 或hash。所有String可以做的hash都可以做。
例如:
key:用户id;field:商品id;value:商品数量。
+1:hincr。-1:hdecr。删除:hdel。全选:hgetall。商品数:hlen。

8、用户消息时间线timeline
list,双向链表,直接作为timeline就好了。插入有序

9、消息队列
List提供了两个阻塞的弹出操作:blpop/brpop,可以设置超时时间

blpop:blpop key1 timeout 移除并获取列表的第一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
brpop:brpop key1 timeout 移除并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。

10、抽奖
自带一个随机获得值

spop myset

11、点赞、签到、打卡

假如上面的微博ID是t1001,用户ID是u3001

用 like:t1001 来维护 t1001 这条微博的所有点赞用户
点赞了这条微博:sadd like:t1001 u3001
取消点赞:srem like:t1001 u3001
是否点赞:sismember like:t1001 u3001
点赞的所有用户:smembers like:t1001
点赞数:scard like:t1001

12、商品筛选

// 获取差集
sdiff set1 set2
// 获取交集(intersection )
sinter set1 set2
// 获取并集
sunion set1 set2

筛选商品,苹果的、ios的、屏幕在6.0-6.24之间的,屏幕材质是LCD屏幕

sinter brand:apple brand:ios screensize:6.0-6.24 screentype:lcd

13、用户关注、推荐模型
follow 关注 fans 粉丝

相互关注:

sadd 1:follow 2
sadd 2:fans 1
sadd 1:fans 2
sadd 2:follow 1

我关注的人也关注了他(取交集):

sinter 1:follow 2:fans

可能认识的人:

用户1可能认识的人(差集):sdiff 2:follow 1:follow
用户2可能认识的人:sdiff 1:follow 2:follow

4. Redis常用数据类型有哪些?

1、String(字符串)
字符串类型是Redis中最为基础的数据存储类型,每个键最大可存储数据512MB
使用方法:

redis 127.0.0.1:6379> set key1 value1
OK
redis 127.0.0.1:6379> set key2 value2
OK
redis 127.0.0.1:6379> get key1
value1
redis 127.0.0.1:6379> get key2
value2
redis 127.0.0.1:6379> set onlineNum 0
OK
redis 127.0.0.1:6379> incr onlineNum
(integer) 1
redis 127.0.0.1:6379> incrby onlineNum 4
(integer) 5
redis 127.0.0.1:6379> decr onlineNum
(integer) 4

适用场景:
很常见的场景用于统计网站访问数量,当前在线人数等。

2、Hash (散列Hash)
hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象或者map。Redis中的散列可以看成具有String key和String value的map容器,可以将多个key-value存储到一个key中。
使用方法:

redis 127.0.0.1:6379> hset user name zhangsan
(integer) 1
redis 127.0.0.1:6379> hmset user user age 10 sex 30
(integer) 2
redis 127.0.0.1:6379> hget user age
"10"
redis 127.0.0.1:6379> hmget user name sex
1)"zhangsan"
2)"30"
redis 127.0.0.1:6379>

适用场景:
存储、读取、修改用户属性(name,age,pwd等)

3、list (列表)
列表是简单的字符串列表,按照插入顺序排序。双向链表,可从头部或尾部插入或取出数据。
使用方法:

redis 127.0.0.1:6379> lpush users zhangsan
(integer) 1
redis 127.0.0.1:6379> lpush users lisi
(integer) 2
redis 127.0.0.1:6379> lpush users xiaofang
(integer) 3
redis 127.0.0.1:6379> lrange users 0 10 
1) "xiaofang"
2) "lisi"
3) "zhangsan"
redis 127.0.0.1:6379> rpush users chacha
(integer) 4
redis 127.0.0.1:6379> lrange users 0 10 
1) "xiaofang"
2) "lisi"
3) "zhangsan"
4) "chacha"
redis 127.0.0.1:6379> rpop users 
"chacha"
redis 127.0.0.1:6379> rpop users
"zhangsan"
redis 127.0.0.1:6379> lpop users
xiaofang
redis 127.0.0.1:6379>

适用场景
1)最新消息排行榜(如朋友圈的时间线)。
2)消息队列。生产者可以用push操作将任务存在list中,消费者用pop操作将任务取出。

4、set (无序集合)
列表是简单的字符串列表。数据插入无序且不可重复。

使用方法:

redis 127.0.0.1:6379> sadd friends zhangsan
(integer) 1
redis 127.0.0.1:6379> sadd friends lisi
(integer) 1
redis 127.0.0.1:6379> sadd friends zhangsan
(integer) 0
redis 127.0.0.1:6379> sadd friends wupeng
(integer) 1
redis 127.0.0.1:6379> scard friends
(integer) 3
redis 127.0.0.1:6379> sismember friends wupeng
(integer) 1
redis 127.0.0.1:6379> sismember friends shasha
(integer) 0
redis 127.0.0.1:6379> srem friends shasha
(inetegr) 0
redis 127.0.0.1:6379> srem friends zhangsan
(integer) 1
redis 127.0.0.1:6379> scard friends
(integer) 2
redis 127.0.0.1:6379> 

适用场景
利用不可重复性,实现求共同好友、访问某地址ip去重,当前在线用户人数去重等

5、zset (有序集合)
redis的zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复

使用方法

redis 127.0.0.1:6379>  zadd rank  97 zhangsan
(integer) 1
redis 127.0.0.1:6379>  zadd rank  70 lisi
(integer) 1
redis 127.0.0.1:6379>  zadd rank  78 wupeng
(integer) 1
redis 127.0.0.1:6379>  zadd rank  75 zhangsan
(integer) 1
redis 127.0.0.1:6379>  zcard rank 
(integer) 3
redis 127.0.0.1:6379>  

适用场景
排行榜、带权重的消息队列


5. 存储Session信息你会使用哪种数据类型?为什么?

Session 数据结构复杂且需要频繁更新或查询其中的个别字段,通常建议使用哈希表来存储 Session;而在 Session 数据较为简单、不涉及局部更新的情况下,使用字符串存储也是可行的选择


6. 有序集合底层是如何实现的?

Redis中的有序集合zset底层实现采用了两种编码方式:

REDIS_ENCODING_SKIPLIST 跳跃列表
REDIS_ENCODING_ZIPLIST 压缩列表

当zset满足以下两个条件的时候,使用ziplist:

保存的元素少于128个
保存的所有元素大小都小于64字节

不满足这两个条件则使用skiplist。


7. 什么是跳表?为什么要用跳表?

跳表是一个随机化的数据结构,实质就是一种可以进行二分查找的有序链表。
跳表在原有的有序链表上面增加了多级索引,通过索引来实现快速查找。
跳表不仅能提高搜索性能,同时也可以提高插入和删除操作的性能。


8. 说一下跳表的查询流程?

把一些节点从有序表中提取出来,缓存一级索引,就组成了下面这样的结构:
在这里插入图片描述
要查找17这个元素,只要从一级索引往后遍历即可,只需要经过1、6、15、17这几个元素就可以找到17了。

查找11这个元素,从一级索引的1开始,向右到6,再向右发现是15,它比11大,此路不通,从6往下走,再从下面的6往右走,到7,再到11。

同样地,一级索引也可以往上再提取一层,组成二级索引,如下:

在这里插入图片描述


9. 说一下跳表的添加流程?为什么要有“随机层数”这个概念?

每一个元素添加到跳表中时,首先需要随机指定这个元素在跳表中的层数,如果随机指定的层数大于了跳表的层数,则在将元素添加到跳表中之前,还需要扩大跳表的层数,而扩大跳表的层数就是将头尾节点的层数扩大。
关于“随机层数”的概念,其主要目的是为了保持跳表的平衡性。如果我们固定每个元素的层数,那么在某些情况下,跳表可能会退化成普通的链表,从而导致查找效率降低。通过随机选择每个元素的层数,我们可以确保跳表的高度大致为log(n),从而保证查找、插入和删除操作的时间复杂度为O(log n)


10. 使用Redis如何实现分布式锁?

想要实现分布式锁,必须要求Redis有互斥的能力。可以使用SETNX命令,其含义是SET IF NOT EXIST,即如果key不存在,才会设置它的值,否则什么也不做。两个客户端进程可以执行这个命令,达到互斥,就可以实现一个分布式锁。

加锁操作完成后,加锁成功的客户端,就可以去操作共享资源,例如,修改MySQL的某一行数据。操作完成后,还要及时释放锁,给后来者让出操作共享资源的机会。释放锁直接使用DEL命令删除这个key即可。

// 加锁
SETNX lock_key 1
// 业务逻辑
DO THINGS
// 释放锁
DEL lock_key

以上实现存在一个很大的问题,当客户端1拿到锁后,如果发生下面的场景,就会造成死锁。

程序处理业务逻辑异常,没及时释放锁
进程挂了,没机会释放锁
以上情况会导致已经获得锁的客户端一直占用锁,其他客户端永远无法获取到锁。

为了解决以上死锁问题,最容易想到的方案是在申请锁时,在Redis中实现时,给锁设置一个过期时间,假设操作共享资源的时间不会超过10s,那么加锁时,给这个key设置10s过期即可。

但以上操作还是有问题,加锁、设置过期时间是2条命令,有可能只执行了第一条,第二条却执行失败,例如:

SETNX执行成功,执行EXPIRE时由于网络问题,执行失败
SETNX执行成功,Redis异常宕机,EXPIRE没有机会执行
SETNX执行成功,客户端异常崩溃,EXPIRE没有机会执行
总之这两条命令如果不能保证是原子操作,就有潜在的风险导致过期时间设置失败,依旧有可能发生死锁问题。在Redis 2.6.12之后,Redis扩展了SET命令的参数,可以在SET的同时指定EXPIRE时间,这条操作是原子的,例如以下命令是设置锁的过期时间为10秒。

SET lock_key 1 EX 10 NX

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/349081.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

配置接口策略路由案例

知识改变命运,技术就是要分享,有问题随时联系,免费答疑,欢迎联系 厦门微思网络​​​​​​ https://www.xmws.cn 华为认证\华为HCIA-Datacom\华为HCIP-Datacom\华为HCIE-Datacom Linux\RHCE\RHCE 9.0\RHCA\ Oracle OCP\CKA\K8S\…

如何使用Jellyfin+cpolar搭建私人影音平台实现无公网ip远程访问

文章目录 1. 前言2. Jellyfin服务网站搭建2.1. Jellyfin下载和安装2.2. Jellyfin网页测试 3.本地网页发布3.1 cpolar的安装和注册3.2 Cpolar云端设置3.3 Cpolar本地设置 4.公网访问测试5. 结语 1. 前言 随着移动智能设备的普及,各种各样的使用需求也被开发出来&…

jQuery实现选择方法和保护信息方法

最近呢!一直在学习jQuery语法,也没时间发布文章,现在学的差不多了,先跟大家分享下学习感受吧!JavaScript学过后,再学习jQuery语法,应该是简单的,但我总是容易把它们搞混,…

Alzet渗透泵工作原理,你清楚么?

由于Alzet渗透泵独特的释放原理,使得许多化学试剂、药剂或者其他物质,可以通过Alzet渗透泵应用到科研试验中。一个小小的胶囊就可以完成持续的动物给药实验,对于科研实验者来说就是一个福音。 那你了解Alzet渗透泵么?让我们一起来简单了解一…

Android HIDL概述与绑定模式的实现

一、前言 Android O(8.0) 版本之后,底层实现有了比较大的变化,最显著的一个方面就是 HIDL 机制的全面实施。本文对于理解系统源码中 Gnss、Usb、Camera 等模块的工作原理有极大帮助。 二、HIDL 设计目的 在 Android O(8.0) 之前系统的升级牵扯多方协作…

循环购:电商新时代的消费革命

随着电商市场的竞争加剧,消费者需求日益多样化,电商企业需要不断创新以满足市场需求。循环购模式作为一种新兴的消费模式,正逐渐受到消费者的青睐,成为电商行业的新热点。本文将深入剖析循环购模式的魅力,探索其在电商…

chromedriver下载地址与安装方法

用到例如selenium时,需要使用谷歌浏览器并配合chromedriver进行模拟浏览等 分享chromedriver的实时更新的下载网址: https://registry.npmmirror.com/binary.html?pathchromedriver/ 。。。 需要找到自己电脑谷歌浏览器版本所对应的chromedriver版本 …

CQ 社区版 2.8.0 | 支持TiDB、StarRocks,新增列过滤算法、导出模式设置等

Hello,CloudQuery 社区版 2.8.0 已发布,本文将带大家详细解析本次更新的功能~(完整的讲解视频可点击 👉🏻 CloudQuery 社区版2.8.0 功能讲解演示 本期亮点更新 新增支持数据源 TiDB、StarRocks数据保护新增列过滤脱敏…

HNSW算法

From: HNSW算法(nsmlib/hnswlib)-CSDN博客HNSW算法的基本原理及使用 - 知乎 HNSW是一种广泛使用的ANN图索引结构,包括DiskANN、DF-GAS、SmartSSD等。本文档主要总结HNSW的结构与工作流程,便于后期研究其工作流程在迁移到CSD中存在的I/O问题…

计算CNN卷积层和全连接层的参数量

计算CNN卷积层和全连接层的参数量 先前阅读 CNN ExplainerA Comprehensive Guide to Convolutional Neural Networks — the ELI5 way 本文主旨意在搞明白2个问题: 第一个问题 一个卷积操作,他的参数,也就是我们要训练的参数,也…

50. Pow(x, n)

分治算法: 从右往左开始递归计算,假设yx^(n/2),那么当n为偶数时,x^ny*y,当n为奇数时,x^ny*y*x。 另外,注意n有可能是负数。 class Solution {public double myPow(double x, int n) {int N n…

Kettle-Docker部署+Sqlserver数据同步Mysql+Start定时任务

一. 背景介绍 1. ETL是什么 ETL(Extract-Transform-Load),即数据抽取、转换、装载的过程。它是一种思想,主要是说,从不同的数据源获取数据,并通过对数据进行处理(格式,协议等转换&a…

ChatGPT 全域调教高手:成为人工智能交流专家

随着人工智能的快速发展,ChatGPT作为一种强大的文本生成模型,在各行各业中越来越受到重视和应用。想要利用ChatGPT实现更加智能、自然的交流,成为 ChatGPT 全域调教高手吗?本文将为您介绍如何通过优化ChatGPT的训练方法&#xff0…

全新5IUX极简搜索主页源码 /自定义浏览器主页

源码介绍: 全新5IUX极简搜索主页源码,专为自定义浏览器主页而设计。厌倦了各种导航首页上满屏幕的广告和资讯,可以自己尝试编写一个个性化的主页。这款源码并非镜像或代理,而是作为浏览器主页使用,同时支持自适应屏幕…

springboot快速写接口

1. 建proj形式 name会变成文件夹的名字,相当于你的项目名称 基础包 2. 基础依赖 3. 配置数据库 这里要打开mysql,并且创建数据库 方法: 安装好数据库,改好账号密码用navicat来建表和账号配置properties.yml文件即可 4.用res…

基于SpringBoot的玩具租赁系统

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式 🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 &…

腾讯云轻量应用Windows服务器如何搭建幻兽帕鲁Palworld私服?

幻兽帕鲁/Palworld是一款2024年Pocketpair开发的开放世界生存制作游戏,在帕鲁的世界,玩家可以选择与神奇的生物“帕鲁”一同享受悠闲的生活,也可以投身于与偷猎者进行生死搏斗的冒险。而帕鲁可以进行战斗、繁殖、协助玩家做农活,也…

Linux文件管理(上)

因为 Linux中一切皆文件,所以在了解了 Linux基础和会使用一些入门级命令之后,接下来的重点便是 Linux文件管理的学习,就像 Java中一切皆对象一样,面向对象是 Java基础的核心和重点。该部分内容学习的重要性就像面向对象在 Java中重…

为什么时序逻辑电路会落后一拍?

1、时序逻辑电路落后一拍&#xff1f; FPGA初学者可能经常听到一句话&#xff1a;“时序逻辑电路&#xff0c;或者说用 < 输出的电路会延迟&#xff08;落后&#xff09;一个时钟周期。”但在仿真过程中经常会发现不符合这一“定律”的现象–明明是在仿真时序逻辑&#xff…

netstat引发系统负载升高故障案例一则

关键词 linux、centoscpu load、netstat、strace阻塞、卡顿 There are many things that can not be broken&#xff01; 如果觉得本文对你有帮助&#xff0c;欢迎点赞、收藏、评论&#xff01; 在一次线上业务的阻塞故障中&#xff0c;发现罪魁祸首是执行了大量netstat的命令…