Redis知识体系总结(2024版),2024年最新大数据运维面试题

4、Redis的优劣势

(1)优势

  1. 代码更清晰,处理逻辑更简单

  2. 不用考虑各种锁的问题,不存在加锁和释放锁的操作,没有因为可能出现死锁而导致的性能消耗

  3. 不存在多线程切换而消耗CPU

(2)劣势

无法发挥多核CPU性能优势,不过可以通过单击开多个Redis实例来完善。

二、Redis为什么是单线程的


1、官方答案

Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络宽带。既然单线程容易实现,而且CPU不会成为瓶颈,那么顺理成章的采用单线程的方案。

2、我的理解

(1)不需要各种锁的性能消耗

Redis的数据结构并不全是key-value形式的,还有list,hash等复杂的结构,这些结构有可能会进行很细粒度的操作,比如在很长的列表后面添加一个元素,在hash中添加或删除一个对象,这些操作可能就需要加非常多的锁,导致的结果是同步开销大大增加。

总之,在单线程的情况下,就不用去考虑各种锁的问题,不存在加锁和释放锁的操作,没有因为可能出现的死锁而导致的性能消耗。

(2)单线程多进程集群方案

单线程的威力实际上非常强大,每核心效率也非常高,多线程自然是可以比单线程有更高的性能上限,但是在今天的计算环境中,即使是单机多线程的上限也往往不能满足需要了,需要进一步摸索的是多服务器集群化的方案,这些方案中多线程的技术照样是用不上的。

所以单线程、多进程的集群不失为一个时髦的解决方案。

(3)CPU消耗

采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗CPU。

但是如果CPU称为Redis的瓶颈,或者不想让服务器其它CPU核闲置,那怎么办?

可以考虑多起几个Redis进程,Redis是key-value数据库,不是关系型数据库,数据之间没有约束。只要客户端分清哪些key放在哪个Redis进程中就可以了。

三、Linux中安装Redis


1、Redis下载

2、上传、解压

Redis一般安装在Linux环境下,开启虚拟机,通过xftp将redis压缩包上传到Linux服务器,并进行解压。

修改redis.conf配置文件,使其在后台启动

四、Redis在Java Web中的应用


Redis 在 Java Web 主要有两个应用场景:

  • 存储缓存用的数据

  • 需要高速读写的场合

1、存储缓存用的数据

在日常对数据库的访问中,读操作的次数远超写操作,比例大概在 1:9 到 3:7,所以需要读的可能性是比写的可能大得多的。当我们使用SQL语句去数据库进行读写操作时,数据库就会去磁盘把对应的数据索引取回来,这是一个相对较慢的过程。

如果放在Redis中,也就是放在内存中,让服务器直接读取内存中的数据,那么速度就会快很多,并且会极大减少数据库的压力,但是使用内存进行数据存储开销也是比较大的,限于成本的原因,一般我们只是使用Redis存储一些常用的和主要的数据,比如用户登录信息等。

一般而言在使用 Redis 进行存储的时候,我们需要从以下几个方面来考虑:

(1)业务数据常用吗?使用率如何?

如果使用率较低,就没必要写入缓存。

(2)该业务是读操作多,还是写操作多?

如果写操作多,频繁需要写入数据库,也没必要使用缓存。

(3)业务数据大小如何?

如果要存储几百兆字节的文件,会给缓存带来很大的压力,这样也没必要。

在考虑了这些问题之后,如果觉得有必要使用缓存,那么就使用它!

从上图我们可以知道以下两点:

(1)当第一次读取数据的时候,读取Redis的数据就会失败,此时就会触发程序读取数据库,把数据读取出来,并且写入Redis中

(2)当第二次以及以后需要读取数据时,就会直接读取Redis,读取数据后就结束了流程,这样速度大大提高了。

从上面的分析可以知道,读操作的可能性是远大于写操作的,所以使用 Redis 来处理日常中需要经常读取的数据,速度提升是显而易见的,同时也降低了对数据库的依赖,使得数据库的压力大大减少。

分析了读操作的逻辑,下面我们来看看写操作流程:

从流程可以看出,更新或者写入的操作,需要多个 Redis 的操作,如果业务数据写次数远大于读次数那么就没有必要使用 Redis。

2、高速读写场合

在如今的互联网中,越来越多的存在高并发的情况,比如天猫双11、抢红包、抢演唱会门票等,这些场合都是在某一个瞬间或者是某一个短暂的时刻有成千上万的请求到达服务器,如果单纯的使用数据库来进行处理,就算不崩,也会很慢的,轻则造成用户体验极差用户量流水,重则数据库瘫痪,服务宕机,而这样的场合都是不允许的!

所以我们需要使用 Redis 来应对这样的高并发需求的场合,我们先来看看一次请求操作的流程:

我们来进一步阐述这个过程:

(1)当一个请求到达服务器时,只是把业务数据在Redis上进行读写,而没有对数据库进行任何的操作,这样就能大大提高读写的速度,从而满足高速相应的需求。

(2)但是这些缓存的数据仍然需要持久化,也就是存入数据库之中,所以在一个请求操作完Redis的读写之后,会去判断该高速读写的业务是否结束,这个判断通常会在秒杀商品为0,红包金额为0时成立,如果不成立,则不会操作数据库;如果成立,则触发事件将Redis的缓存的数据以批量的形式一次性写入数据库,从而完成持久化的工作。

五、Redis代码实例


1、Java整合Redis

(1)导入pom

redis.clients

jedis

3.2.0

(2)编写Java主方法

调用Redis中的ping方法,惊现异常:

开始的时候以为是防火墙的问题,后来通过查看redis状态发现IP地址不对,不应该是127.0.0.1

修改redis.conf

注意:需要注意的是在修改redis.conf时,①注掉bind 127.0.0.1;②需要将本机访问保护模式设置为no;③此时可以配置多个ip

(3)再次执行主方法,执行成功!

2、五大数据类型代码实例

package com.guor.redis;

import redis.clients.jedis.Jedis;

import java.util.List;

import java.util.Set;

public class JedisTest01 {

public static void main(String[] args) {

test05();

}

private static void test01(){

Jedis jedis = new Jedis(“192.168.194.131”, 6379);

String value = jedis.ping();

System.out.println(value);

//添加

jedis.set(“name”,“GooReey”);

//获取

String name = jedis.get(“name”);

System.out.println(name);

jedis.set(“age”,“30”);

jedis.set(“city”,“dalian”);

//获取全部的key

Set keys = jedis.keys(“*”);

for(String key : keys){

System.out.println(key+" --> "+jedis.get(key));

}

//加入多个key和value

jedis.mset(“name1”,“zs”,“name2”,“ls”,“name3”,“ww”);

List mget = jedis.mget(“name1”, “name2”);

System.out.println(mget);//[zs, ls]

}

//list

private static void test02(){

Jedis jedis = new Jedis(“192.168.194.131”, 6379);

jedis.lpush(“key1”,“01”,“02”,“03”);

List values = jedis.lrange(“key1”,0,-1);

System.out.println(values);//[03, 02, 01]

}

//set

private static void test03(){

Jedis jedis = new Jedis(“192.168.194.131”, 6379);

jedis.sadd(“username”,“zs”,“ls”,“ww”);

Set names = jedis.smembers(“username”);

System.out.println(names);//[ww, zs, ls]

}

//hash

private static void test04(){

Jedis jedis = new Jedis(“192.168.194.131”, 6379);

jedis.hset(“users”,“age”, “20”);

String hget = jedis.hget(“users”,“age”);

System.out.println(hget);

}

//zset

private static void test05(){

Jedis jedis = new Jedis(“192.168.194.131”, 6379);

jedis.zadd(“china”,100d,“shanghai”);

Set names = jedis.zrange(“china”,0,-1);

System.out.println(names);//[shanghai]

}

}

3、手机验证码功能代码实例

package com.guor.redis;

import redis.clients.jedis.Jedis;

import java.util.Random;

public class PhoneCode {

public static void main(String[] args) {

verifyCode(“10086”);//795258

getRedisCode(“10086”,“795258”);//success.

}

//1、生成6位数字验证码

public static String getCode(){

Random random = new Random();

String code = “”;

for (int i = 0; i < 6; i++) {

int rand = random.nextInt(10);

code += rand;

}

return code;//849130

}

//2、每个手机每天只能发送三次,验证码放到redis中,设置过期时间

public static void verifyCode(String phone){

Jedis jedis = new Jedis(“192.168.194.131”, 6379);

//拼接key

//手机发送次数key

String countKey = “VerifyCode” + phone + “:count”;

//验证码key

String codeKey = “VerifyCode” + phone + “:code”;

//每个手机每天只能发送三次

String count = jedis.get(countKey);

if(count == null){

//设置过期时间

jedis.setex(countKey,246060,“1”);

}else if(Integer.parseInt(count)<=2){

//发送次数+1

jedis.incr(countKey);

}else if(Integer.parseInt(count)>2){

System.out.println(“今天的发送次数已经超过三次”);

jedis.close();

}

String vCode = getCode();

jedis.setex(codeKey,120,vCode);

jedis.close();

}

//3、验证码校验

public static void getRedisCode(String phone, String code){

//从redis中获取验证码

Jedis jedis = new Jedis(“192.168.194.131”, 6379);

//验证码key

String codeKey = “VerifyCode” + phone + “:code”;

String redisCode = jedis.get(codeKey);

if(redisCode.equals(code)){

System.out.println(“success.”);

}else{

System.out.println(“error”);

}

jedis.close();

}

}

当超过三次时:

4、SpringBoot整合Redis

(1)建工程,引入pom

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns=“http://maven.apache.org/POM/4.0.0” xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”

xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd”>

4.0.0

org.springframework.boot

spring-boot-starter-parent

2.2.1.RELEASE

com.guor

redisspringboot

0.0.1-SNAPSHOT

redisspringboot

Demo project for Spring Boot

<java.version>1.8</java.version>

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-test

test

org.springframework.boot

spring-boot-starter-data-redis

2.4.5

org.apache.commons

commons-pool2

2.9.0

org.springframework.boot

spring-boot-maven-plugin

(2)配置类

application.properties

Redis数据库索引(默认为0)

spring.redis.database=0

Redis服务器地址

spring.redis.host=192.168.194.131

Redis服务器连接端口

spring.redis.port=6379

Redis服务器连接密码(默认为空)

spring.redis.password=

连接池最大连接数(使用负值表示没有限制)

spring.redis.jedis.pool.max-active=20

连接池最大阻塞等待时间(使用负值表示没有限制)

spring.redis.jedis.pool.max-wait=-1

连接池中的最大空闲连接

spring.redis.jedis.pool.max-idle=10

连接池中的最小空闲连接

spring.redis.jedis.pool.min-idle=0

连接超时时间(毫秒)

spring.redis.timeout=1000

RedisConfig

package com.guor.redisspringboot.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;

import com.fasterxml.jackson.annotation.JsonTypeInfo;

import com.fasterxml.jackson.annotation.PropertyAccessor;

import com.fasterxml.jackson.databind.ObjectMapper;

import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;

import org.springframework.cache.annotation.EnableCaching;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.data.redis.cache.RedisCacheConfiguration;

import org.springframework.data.redis.cache.RedisCacheManager;

import org.springframework.data.redis.cache.RedisCacheWriter;

import org.springframework.data.redis.connection.RedisConnectionFactory;

import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.data.redis.serializer.*;

import java.time.Duration;

@EnableCaching

@Configuration

public class RedisConfig {

@Bean

public RedisTemplate redisTemplate(RedisConnectionFactory factory) {

RedisTemplate<String, Object> template = new RedisTemplate<>();

template.setConnectionFactory(factory);

Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

ObjectMapper om = new ObjectMapper();

om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);

// om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);

jackson2JsonRedisSerializer.setObjectMapper(om);

StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

// key采用String的序列化方式

template.setKeySerializer(stringRedisSerializer);

// hash的key也采用String的序列化方式

template.setHashKeySerializer(stringRedisSerializer);

// value序列化方式采用jackson

template.setValueSerializer(jackson2JsonRedisSerializer);

// hash的value序列化方式采用jackson

template.setHashValueSerializer(jackson2JsonRedisSerializer);

template.afterPropertiesSet();

return template;

}

/**

  • 基于SpringBoot2 对 RedisCacheManager 的自定义配置

  • @param redisConnectionFactory

  • @return

*/

@Bean

public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {

//初始化一个RedisCacheWriter

RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);

//设置CacheManager的值序列化方式为json序列化

RedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer();

RedisSerializationContext.SerializationPair pair = RedisSerializationContext.SerializationPair.fromSerializer(jsonSerializer);

RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);

//设置默认超过时期是1天

defaultCacheConfig.entryTtl(Duration.ofDays(1));

//初始化RedisCacheManager

return new RedisCacheManager(redisCacheWriter, defaultCacheConfig);

}

}

(3)控制类测试

package com.guor.redisspringboot.controller;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

@RestController

@RequestMapping(“/redisTest”)

public class RedisTestController {

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

总目录展示

该笔记共八个节点(由浅入深),分为三大模块。

高性能。 秒杀涉及大量的并发读和并发写,因此支持高并发访问这点非常关键。该笔记将从设计数据的动静分离方案、热点的发现与隔离、请求的削峰与分层过滤、服务端的极致优化这4个方面重点介绍。

一致性。 秒杀中商品减库存的实现方式同样关键。可想而知,有限数量的商品在同一时刻被很多倍的请求同时来减库存,减库存又分为“拍下减库存”“付款减库存”以及预扣等几种,在大并发更新的过程中都要保证数据的准确性,其难度可想而知。因此,将用一个节点来专门讲解如何设计秒杀减库存方案。

高可用。 虽然介绍了很多极致的优化思路,但现实中总难免出现一些我们考虑不到的情况,所以要保证系统的高可用和正确性,还要设计一个PlanB来兜底,以便在最坏情况发生时仍然能够从容应对。笔记的最后,将带你思考可以从哪些环节来设计兜底方案。


篇幅有限,无法一个模块一个模块详细的展示(这些要点都收集在了这份《高并发秒杀顶级教程》里),麻烦各位转发一下(可以帮助更多的人看到哟!)

由于内容太多,这里只截取部分的内容。

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img

89)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-DiqqaUNx-1712805797190)]

总目录展示

该笔记共八个节点(由浅入深),分为三大模块。

高性能。 秒杀涉及大量的并发读和并发写,因此支持高并发访问这点非常关键。该笔记将从设计数据的动静分离方案、热点的发现与隔离、请求的削峰与分层过滤、服务端的极致优化这4个方面重点介绍。

一致性。 秒杀中商品减库存的实现方式同样关键。可想而知,有限数量的商品在同一时刻被很多倍的请求同时来减库存,减库存又分为“拍下减库存”“付款减库存”以及预扣等几种,在大并发更新的过程中都要保证数据的准确性,其难度可想而知。因此,将用一个节点来专门讲解如何设计秒杀减库存方案。

高可用。 虽然介绍了很多极致的优化思路,但现实中总难免出现一些我们考虑不到的情况,所以要保证系统的高可用和正确性,还要设计一个PlanB来兜底,以便在最坏情况发生时仍然能够从容应对。笔记的最后,将带你思考可以从哪些环节来设计兜底方案。


篇幅有限,无法一个模块一个模块详细的展示(这些要点都收集在了这份《高并发秒杀顶级教程》里),麻烦各位转发一下(可以帮助更多的人看到哟!)

[外链图片转存中…(img-oXoRBKMb-1712805797190)]

[外链图片转存中…(img-cWT4xaca-1712805797190)]

由于内容太多,这里只截取部分的内容。

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-MNTw9S1A-1712805797190)]

  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在MySQL和Redis运维面试中,可能会涉及到以下一些常见问题和主题: 1. 数据库备份和恢复:你可以使用mysqlbinlog命令来备份和恢复MySQL二进制日志文件。此外,你可能还需要了解如何使用Redis的持久化功能进行备份和恢复。 2. 负载均衡和高可用性:了解如何配置MySQL和Redis的负载均衡,以及如何实现高可用性的方案,比如使用LVS、HAProxy、Keepalived等工具。 3. 监控和性能调优:了解如何使用工具监控MySQL和Redis的性能,并进行相应的性能调优操作。例如,可以使用zabbix、Prometheus等工具进行监控,可以使用slow query日志来识别慢查询,并使用索引和优化查询语句来提高性能。 4. 主从复制和高可用性:了解如何配置MySQL的主从复制,并了解如何检查复制状态。可以使用类似于"show slave status\G"命令来检查Slave_IO_Running和Slave_SQL_Running状态。 5. 数据库模式设计和架构:了解如何设计和规划数据库模式,包括表的拆分、索引的设计等。对于需要短时间响应的查询操作,可能需要考虑使用NoSQL数据库,因为它们在此方面通常更具优势。 6. 缓存和性能优化:了解如何使用Redis作为缓存来提高数据库性能,以及如何在应用程序中正确使用Redis缓存。 7. 容灾和灾难恢复:了解如何设置数据库容灾和灾难恢复方案,包括备份和恢复计划、故障切换和数据恢复。 8. 安全性和权限管理:了解如何设置数据库的安全性措施,包括用户权限管理、访问控制、加密和审计。 这些是一些可能在MySQL和Redis运维面试中会涉及到的主题和问题。当然,具体的面试题目可能会因面试者的需求和公司的要求而有所不同。在准备面试时,建议深入研究和理解这些主题,并结合自己的实际经验来回答问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值