热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

封装导入步骤_【194期】Redis——第三方jar没有封装的命令我们该怎么执行?

点击上方“Java面试题精选”,关注公众号面试刷图,查缺补漏号外:往期面试题,10篇为一个单位归置到本公众号菜单栏-面

点击上方“Java面试题精选”,关注公众号

面试刷图,查缺补漏

>>号外:往期面试题,10篇为一个单位归置到本公众号菜单栏->面试题,有需要的欢迎翻阅

阶段汇总集合:001期~180期汇总,方便阅读(增加设计模式)

今天对redis的进阶操作给大家介绍一下,以及对于jedis和redisTemplate等工具包没有封装的命令我们该如何使用?相信大家读了本篇对redis的整体会有更深的认知。

一、Pipelin模式介绍

1、redis的通常使用方式

大多数情况下,我们都会通过请求-相应机制去操作redis。使用这种模式的步骤为

  1. 获得jedis实例

  2. 发送redis命令

  3. 由于redis是单线程的,所以处理完上一个指令之后才会进行执行该命令。

整个交互流程如下

38ce979556de040cbba5c06d42f6c68e.png

2、Pipeline模式

然而使用Pipeline 模式,客户端可以一次性的发送多个命令,无需等待服务端返回。这样就大大的减少了网络往返时间,提高了系统性能。

pipeline是多条命令的组合,使用PIPELINE 可以解决网络开销的问题,原理也非常简单,流程如下, 将多个指令打包后,一次性提交到Redis, 网络通信只有一次

2d0443638e7c62effcdbac8d4e995c89.png

3、性能对比

cc639f14cbbad2cabc5dd709e197004f.png

可以看到,redis的延迟主要出现在网络请求的IO次数上,因此我们在使用redis的时候,尽量减少网络IO次数,通过pipeline的方式将多个指令封装在一个命令里执行。

二、Redis事物

redis的简单事务是将一组需要一起执行的命令放到multi和exec两个命令之间,其中multi代表事务开始,exec代表事务结束

e51b6cb19dead0cac4d2d494aba92011.png

1、事务命令

  • multi:事务开始

  • exec:提交事务

  • watch:事务监控

WATCH命令可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行。监控一直持续到

discard:停止事务

在执行exec之前执行该命令,提交事务会失败,执行的命令会进行回滚

127.0.0.1:6379> multi     //开始事务
 
OK
 
127.0.0.1:6379> sadd tt 1   //业务操作
 
QUEUED
 
127.0.0.1:6379> DISCARD   //停止事务
 
OK
 
127.0.0.1:6379> exec   //提交事务
 
(error) ERR EXEC without MULTI   //报不存在事务异常
 
127.0.0.1:6379> get tt  //获取不到对象
 
(nil)
 
127.0.0.1:6379>

2、事务异常

redis支持事务,但他属于弱事务,中间的一些异常可能会导致事务失效。

往期面试题:001期~180期汇总

1、命令错误,语法不正确,导致事务不能正常结束

127.0.0.1:6379> multi   //开始事务
 
OK
 
127.0.0.1:6379> set aa 123  //业务操作
 
QUEUED
 
127.0.0.1:6379> sett bb 124  //命令错误
 
(error) ERR unknown command 'sett'
 
127.0.0.1:6379> exec 
 
(error) EXECABORT Transaction discarded because of  previous errors.  //提交事务异常
 
127.0.0.1:6379> get aa  //查询不到数据
 
(nil)
 
127.0.0.1:6379>

2、运行错误,语法正确,但类型错误,事务可以正常结束

127.0.0.1:6379> multi
 
OK
 
127.0.0.1:6379> set t 1   //业务操作1
 
QUEUED
 
127.0.0.1:6379> sadd t 1  //业务操作2
 
QUEUED
 
127.0.0.1:6379> set t 2  //业务操作3
 
QUEUED
 
127.0.0.1:6379> exec
 
1) OK
 
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value  //类型异常
 
3) OK
 
127.0.0.1:6379> get t  //可以获取到t
 
"2"
 
127.0.0.1:6379>
三、redis发布与订阅

redis提供了“发布、订阅”模式的消息机制,其中消息订阅者与发布者不直接通信,发布者向指定的频道(channel)发布消息,订阅该频道的每个客户端都可以接收到消息

78ecb4206e9bab257a32c40e65a14596.png

1、Redis发布订阅常用命令

8cfd4048dc79d938a55e70614c98c78a.png

2、性能测试

参考:

https://blog.csdn.net/b379685397/article/details/95626295

3、应用场景

redis主要提供发布消息、订阅频道、取消订阅以及按照模式订阅和取消订阅,和很多专业的消息队列(kafka rabbitmq),redis的发布订阅显得很lower, 比如无法实现消息规程和回溯, 但就是简单,如果能满足应用场景,用这个也可以

  1. 订阅号、公众号、微博关注、邮件订阅系统等

  2. 即使通信系统

  3. 群聊部落系统(微信群)

四、键的迁移

键迁移大家可能用的不是很多,因为一般都是使用redis主从同步。不过对于我们做数据统计分析使用的时候,可能会使用到,比如用户标签。为了避免key批量删除导致的redis雪崩,一般都是通过一个计算使用的redis和一个最终业务使用的redis,通过将计算时用的redis里的键值通过迁移的方式一个一个的更新到业务redis中,使其对业务冲击最小化。

1、move

move指令将redis一个库中的数据迁移到另外一个库中。

move key db  //reids有16个库, 编号为0-15
set name DK;  move name 5 //迁移到第6个库
elect 5 ;//数据库切换到第6个库,
get name  可以取到james1

如果key在目标数据库中已存在,那么什么也不会发生。这种模式不建议在生产环境使用,在同一个reids里可以玩

2、dump

Redis DUMP 命令用于将key给序列化 ,并返回被序列化的值。用于导入到其他服务中

一般通过dump命令导出,使用restore命令导入。

1,在A服务器上

set name james;
dump name;       //  得到"\x00\x05james\b\x001\x82;f\"DhJ"

2,在B服务器上

restore name 0 "\x00\x05james\b\x001\x82;f\"DhJ"    //0代表没有过期时间
get name           //返回james

3、migrate

migrate用于在Redis实例间进行数据迁移,实际上migrate命令是将dump、restore、del三个命令进行组合,从而简化了操作流程。

往期面试题:001期~180期汇总

migrate命令具有原子性,从Redis 3.0.6版本后已经支持迁移多个键的功能。migrate命令的数据传输直接在源Redis和目标Redis上完成,目标Redis完成restore后会发送OK给源Redis。

f6578ee4ae003725c318d3ea0770c4ad.png

比如:把111上的name键值迁移到112上的redis

192.168.42.111:6379> migrate 192.168.42.112 6379 name 0 1000 copy
五、自定义命令封装

当我们使用jedis或者jdbctemplate时,想执行键迁移的指令的时候,发现根本没有给我们封装相关指令,这个时候我们该怎么办呢?除了框架帮我们封装的方法外,我们自己也可以通过反射的方式进行命令的封装,主要步骤如下

  1. 建立Connection链接,使用Connection连接Redis

  2. 通过反射获取Connection中的sendCommand方法(protected Connection sendCommand(Command cmd, String... args))。

  3. 调用connection的sendCommand方法,第二个参数为执行的命令(比如set,get,client等),第三个参数为命令的参数。可以看到ProtocolCommand这个枚举对象包含了redis的所有指令,即所有的指令都可以通过这个对象获取到。并封装执行

  4. 执行invoke方法,并且按照redis的指令封装参数

  5. 获取Redis的命令执行结果

package com.james.cache.jedis;
 
import redis.clients.jedis.Connection;
import redis.clients.jedis.Protocol;
 
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
 
/**
 * @Auther: DK
 * @Date: 2020/10/11 23:17
 * @Description:
 */
public class RedisKeyMove {
 
    public static void main(String[] args) throws IOException {
        //1.使用Connection连接Redis
        try (Connection connection = new Connection("10.1.253.188", 6379)) {
            // 2. 通过反射获取Connection中的sendCommand方法(protected Connection sendCommand(Command cmd, String... args))。
            Method method = Connection.class.getDeclaredMethod("sendCommand", Protocol.Command.class, String[].class);
            method.setAccessible(true); // 设置可以访问private和protected方法
            // 3. 调用connection的sendCommand方法,第二个参数为执行的命令(比如set,get,client等),第三个参数为命令的参数。
            // 3.1 该命令最终对应redis中为: set test-key test-value
            method.invoke(connection, Protocol.Command.MIGRATE,
                    new String[] {"10.1.253.69", "6379", "name", "0", "1000", "copy"});
            // 4.获取Redis的命令执行结果
            System.out.println(connection.getBulkReply());
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
六、键全量遍历

1、keys

672f31d940a9ae85d1f146535a807906.png

考虑到是单线程,使用改命令会阻塞线程, 在生产环境不建议使用,键多可能会阻塞。

2、渐进式遍历 scan

1,初始化数据

mset n1 1 n2 2 n3 3 n4 4 n5 5 n6 6 n7 7 n8 8 n9 9 n10 10 n11 11 n12 12 n13 13

2,遍历匹配

scan 0 match n* count 5    匹配以n开头的键,最大是取5条,第一次scan 0开始

第二次从游标4096开始取20个以n开头的键,相当于一页一页的取当最后返回0时,键被取完。

3、scan 和keys对比

  1. 通过游标分布进行的,不会阻塞线程;

  2. 提供 limit 参数,可以控制每次返回结果的最大条数,limit 不准,返回的结果可多可少;

  3. 同 keys 一样,Scan也提供模式匹配功能;

  4. 服务器不需要为游标保存状态,游标的唯一状态就是 scan 返回给客户端的游标整数;

  5. scan返回的结果可能会有重复,需要客户端去重复;

  6. scan遍历的过程中如果有数据修改,改动后的数据能不能遍历到是不确定的;

  7. 单次返回的结果是空的并不意味着遍历结束,而要看返回的游标值是否为零;

4、其他遍历命令

SCAN 命令用于迭代当前数据库中的数据库键。

SSCAN 命令用于迭代集合键中的元素。

HSCAN 命令用于迭代哈希键中的键值对。

ZSCAN 命令用于迭代有序集合中的元素(包括元素成员和元素分值)。

用法和scan一样

END

来源:blog.csdn.net/b379685397/article/details/109015852

十期推荐

【181期】HashMap 面试二十一问!

【182期】SpringCloud常见面试题(2020最新版)

【183期】面试官:线上服务平均响应时间太长,怎么排查?

【184期】SQL数据库面试题以及答案(50例题)

【185期】面试官:你能说说 Synchronized实现对象锁的两种方式以及它的原理吗?

【186期】一口气说出 Synchronized 同步方法的八种使用场景

【187期】出现几率比较大的Redis面试题(含答案)

【188期】面试官:delete、truncate、drop的区别有哪些,该如何选择

【189期】delete后加 limit是个好习惯么

【190期】MQ消息中间件,面试能问写什么?

与其在网上拼命找题? 不如马上关注我们~

b9fd1ae2ee781328f6c4eb8fce67c388.png




推荐阅读
  • 深入解析Hadoop的核心组件与工作原理
    本文详细介绍了Hadoop的三大核心组件:分布式文件系统HDFS、资源管理器YARN和分布式计算框架MapReduce。通过分析这些组件的工作机制,帮助读者更好地理解Hadoop的架构及其在大数据处理中的应用。 ... [详细]
  • 本文介绍如何在Spring Boot项目中集成Redis,并通过具体案例展示其配置和使用方法。包括添加依赖、配置连接信息、自定义序列化方式以及实现仓储接口。 ... [详细]
  • Spring Boot单元测试中Redis连接失败的解决方案
    本文探讨了在Spring Boot项目中进行单元测试时遇到Redis连接问题的原因及解决方法,详细分析了配置文件加载路径不当导致的问题,并提供了有效的解决方案。 ... [详细]
  • 深入解析Java枚举及其高级特性
    本文详细介绍了Java枚举的概念、语法、使用规则和应用场景,并探讨了其在实际编程中的高级应用。所有相关内容已收录于GitHub仓库[JavaLearningmanual](https://github.com/Ziphtracks/JavaLearningmanual),欢迎Star并持续关注。 ... [详细]
  • 深入解析Java虚拟机(JVM)架构与原理
    本文旨在为读者提供对Java虚拟机(JVM)的全面理解,涵盖其主要组成部分、工作原理及其在不同平台上的实现。通过详细探讨JVM的结构和内部机制,帮助开发者更好地掌握Java编程的核心技术。 ... [详细]
  • 优化Flask应用的并发处理:解决Mysql连接过多问题
    本文探讨了在Flask应用中通过优化后端架构来应对高并发请求,特别是针对Mysql 'too many connections' 错误的解决方案。我们将介绍如何利用Redis缓存、Gunicorn多进程和Celery异步任务队列来提升系统的性能和稳定性。 ... [详细]
  • 本文深入探讨了MySQL中常见的面试问题,包括事务隔离级别、存储引擎选择、索引结构及优化等关键知识点。通过详细解析,帮助读者在面对BAT等大厂面试时更加从容。 ... [详细]
  • 本文深入探讨了UNIX/Linux系统中的进程间通信(IPC)机制,包括消息传递、同步和共享内存等。详细介绍了管道(Pipe)、有名管道(FIFO)、Posix和System V消息队列、互斥锁与条件变量、读写锁、信号量以及共享内存的使用方法和应用场景。 ... [详细]
  • 本文探讨了如何通过一系列技术手段提升Spring Boot项目的并发处理能力,解决生产环境中因慢请求导致的系统性能下降问题。 ... [详细]
  • 序列化与反序列化是数据处理中的重要技术,特别是在网络通信和数据存储中。它们允许将复杂的数据结构转换为可传输或存储的格式,再从这些格式恢复原始数据。本文探讨了序列化与反序列化的基本概念,以及它们在不同协议模型中的角色。 ... [详细]
  • 2018-2019学年第六周《Java数据结构与算法》学习总结
    本文总结了2018-2019学年第六周在《Java数据结构与算法》课程中的学习内容,重点介绍了非线性数据结构——树的相关知识及其应用。 ... [详细]
  • Spring Boot 中静态资源映射详解
    本文深入探讨了 Spring Boot 如何简化 Web 应用中的静态资源管理,包括默认的静态资源映射规则、WebJars 的使用以及静态首页的处理方法。通过本文,您将了解如何高效地管理和引用静态资源。 ... [详细]
  • 本文详细探讨了Java中的ClassLoader类加载器的工作原理,包括其如何将class文件加载至JVM中,以及JVM启动时的动态加载策略。文章还介绍了JVM内置的三种类加载器及其工作方式,并解释了类加载器的继承关系和双亲委托机制。 ... [详细]
  • 2017-2018年度《网络编程与安全》第五次实验报告
    本报告详细记录了2017-2018学年《网络编程与安全》课程第五次实验的具体内容、实验过程、遇到的问题及解决方案。 ... [详细]
  • 本文详细解析了Java中throw和throws的关键区别,同时涵盖了JDK的定义、Java虚拟机的关键约定、Java的跨平台性、自动垃圾回收机制、源文件结构、包的概念及作用等多个核心知识点,旨在帮助学生更好地准备Java期末考试。 ... [详细]
author-avatar
9位特权QQ号码连号
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有