当前位置: 首页 > news >正文

长沙企业网站建设企业/热搜词排行榜关键词

长沙企业网站建设企业,热搜词排行榜关键词,简单大气网站模板,网络营销推广渠道都有哪些方面本文介绍Redis pipeline相关的知识点及代码示例,包括Redis客户端-服务端的一次完整的网络请求、pipeline与client执行多命令的区别、pipeline与Redis"事务"、pipeline的使用代码示例; pipeline与client执行多命令的区别 Redis是一种基于客户…

本文介绍Redis pipeline相关的知识点及代码示例,包括Redis客户端-服务端的一次完整的网络请求、pipeline与client执行多命令的区别、pipeline与Redis"事务"、pipeline的使用代码示例;

pipeline与client执行多命令的区别

Redis是一种基于客户端-服务端模型以及请求/响应的TCP服务;Redis客户端-服务端的一次完整的网络请求来回如下图;

简化一下,一次Redis请求和响应,会经历如下的步骤

  • 客户端发起一个(查询/插入)请求,并监听socket返回,通常情况都是阻塞模式等待Redis服务器的响应;
  • 服务端处理命令,并且返回处理结果给客户端;
  • 客户端接收到服务的返回结果,程序从阻塞代码处返回;

Redis客户端和服务端之间通过网络连接进行数据传输,这个连接可以很快(loopback接口)或很慢(建立了一个多次跳转的网络连接);但无论网络延如何延时,数据包总是能从客户端到达服务器,并从服务器返回数据回复客户端,这个时间被称之为RTT(Round Trip Time - 往返时间)

我们可以很容易就意识到,Redis在连续请求服务端时,即使Redis每秒能处理100k请求,但也会因为网络传输花费大量时间,导致整体性能的下降

因此如果遇到大量的批处理,我们可以考虑使用Redis的pipeline(管道);

对于pipeline技术而言,对于N个命令,就相当于将N个上图中的步骤,合并成1个,其他多余的时间开销仅作用于命令的执行,这样服务请求响应的总体时间将会大大的减少

关于pipeline与client单命令的压测结果可参考Redis精通系列——Pipeline(管道);

值得注意的是,管道技术并不是Redis特有的技术,管道技术往往需要客户端-服务器的共同配合,大部分工作任务其实是在客户端完成;Redis在较早的版本就已经支持管道技术;

如下图,多个连续的incr指令,使用pipeline(管道)后,多个连续的incr指令只会花费一次网络来回开销;这个开销会随着N数值的增大,大幅减少网络IO开销,从而提升整体服务的性能;

Redis pipeline的使用注意事项

1. pipeline一次执行的命令不宜过多

结合上面redis命令完整执行流程图,有个值得注意的点——可能出现我们经常说到的IO阻塞

  • 当write操作发生,并且发送缓冲区(send buffer)满时,就会导致write操作阻塞;
  • 当read操作发生,并且接收缓冲区(recv buffer)满时,就会导致read操作阻塞;

上述的这两个阻塞如果出现,将会导致整个请求时间变长;

因此我们操作大批量指令的时候,比如10k个指令,我们可以合理的对指令分多次批量发送,这样可以减少出现阻塞的情况,也可以避免服务器响应一个过大的response包,导致客户端内存负载过重;

即使不发生IO阻塞,pipeline每批打包的命令不能过多还有一个原因:因为 pipeline 方式打包命令再发送,那么 redis server 必须在处理完所有命令前,先缓存起所有命令的处理结果,这样就有一个缓存结果的内存的消耗

2. pipeline不保证命令执行的原子性

官方文档的一句话——

Redis::PIPELINE block is simply transmitted faster to the server, but without any guarantee of atomicity.

其实Redis的高性能设计本就不支持包含多命令的严格事务,哪怕是multi/exec操作还是Lua脚本;Redis只是提供了一些命令来一定程度实现"事务";

multi/exec操作针对命令语法错误和执行时参数错误,处理是不一样的,详情见我之前的文章《Redis——“事务“/Lua脚本》;

Lua脚本也只能一定程度保证逻辑处理和Redis命令打包的原子性,例如库存扣减;

pipeline的使用代码示例

代码示例的背景是:根据appId批量查询本地缓存的App信息,未命中本地缓存的,需要从redis中拿这多个key的value,然后刷入本地缓存;在"从redis中拿这多个key的value",在key数量较多时,做个优化,使用Redis的pipeline;

    private List<AppSimpleInfoDTO> querySimpleAppWithCache(List<String> payAppIds) {if (CollectionUtils.isEmpty(payAppIds)) {return Lists.newArrayList();}List<AppSimpleInfoDTO> appList = Lists.newArrayList();try {// 从本地缓存读取APPfinal List<String> tobeQry = Lists.newArrayList();for (String payAppId : payAppIds) {AppSimpleInfoDTO appSimpleInfoDTO = null;appSimpleInfoDTO = appSimpleInfoCache.getIfPresent(payAppId);if (appSimpleInfoDTO != null) {log.info("get_appSimpleInfoDTO_fr_appSimpleInfoCache_suc. [appSimpleInfoDTO={}]", JSON.toJSONString(appSimpleInfoDTO));appList.add(appSimpleInfoDTO);} else {tobeQry.add(payAppId);}}// 未命中本地缓存则去redis查询if (CollectionUtils.isNotEmpty(tobeQry)) {final List<AppSimpleInfoDTO> cacheAppSimpleInfoDTOs = getAndCacheAppSimpleInfoDTOs(tobeQry);if (CollectionUtils.isNotEmpty(cacheAppSimpleInfoDTOs)) {appList.addAll(cacheAppSimpleInfoDTOs);}}return appList;} catch (Exception e) {log.error("querySimpleAppWithCache error.", e);// 异常时刷全量缓存return getAndCacheAppSimpleInfoDTOs(payAppIds);}}

使用pipeline做多个key的get命令:

    private List<AppSimpleInfoDTO> getAndCacheAppSimpleInfoDTOs(List<String> payAppIds) {final Set<String> payAppIds2Qry = new HashSet<>(payAppIds);final List<AppSimpleInfoDTO> result = Lists.newArrayList();// 先尝试从redis获取 pipeline模式JedisClusterPipeLine pipeline = null;try {pipeline = jedisCluster.pipelined();for (String payAppId : payAppIds) {final String appSimpleInfoKey = CacheKeyUtils.getAppSimpleInfoKey(payAppId);// pipeline添加get命令pipeline.get(appSimpleInfoKey);}// pipeline执行并获取结果final List<Object> allVal = pipeline.syncAndReturnAll();if (CollectionUtils.isNotEmpty(allVal)) {allVal.forEach(val -> {if (val != null) {final String jsonStr = String.valueOf(val);if (StringUtils.isNotBlank(jsonStr)) {Optional.ofNullable(JSON.parseObject(jsonStr, AppSimpleInfoDTO.class)).ifPresent(appSimpleInfoDTO -> {result.add(appSimpleInfoDTO);appSimpleInfoCache.put(appSimpleInfoDTO.getPayAppId(), appSimpleInfoDTO);log.info("localCache_AppSimpleInfoDTO_fr_redis_suc. [simpleApp={}]", JSON.toJSONString(appSimpleInfoDTO));payAppIds2Qry.remove(appSimpleInfoDTO.getPayAppId());});}}});}} catch (Exception e) {log.error("localCache_AppSimpleInfoDTOs_fr_redis_error. [payAppIds={}]", JSON.toJSONString(payAppIds), e);} finally {if (pipeline != null) {pipeline.close();}}// redis未查到的数据走RPC查询 并异步加载到redis和localCacheif (CollectionUtils.isNotEmpty(payAppIds2Qry)) {final List<String> payAppIds2QryList = new ArrayList<>(payAppIds2Qry);List<App> apps = Lists.newArrayList();int index = 0;while (index < payAppIds2QryList.size()) {int toIndex = Math.min(index + max_batch, payAppIds2QryList.size());List<String> payAppIds2QryTemp = payAppIds2QryList.subList(index, toIndex);// 实时查APP信息接口List<App> appsTemp = queryAppByPayAppIds(new ArrayList<>(payAppIds2QryTemp));apps.addAll(appsTemp);index += max_batch;}// 异步加载到redis和localCacheif (CollectionUtils.isNotEmpty(apps)) {for (App app : apps) {AppSimpleInfoDTO simpleApp = new AppSimpleInfoDTO(app.getName(), app.getPackname(), app.getCode(), app.getBigType());CompletableFuture.runAsync(() -> {// redis缓存1小时jedisClusterTemplate.setex(CacheKeyUtils.getAppSimpleInfoKey(simpleApp.getPayAppId()), VivoConfigManager.getInteger(JointOperateConfigConstants.APP_SIMPLEINFO_REDIS_CACHE_TTL, JointOperateConfigConstants.APP_SIMPLEINFO_REDIS_CACHE_TTL_DEFAULT), JSON.toJSONString(simpleApp));log.info("redisCache_AppSimpleInfoDTO_suc. [simpleApp={}]", JSON.toJSONString(simpleApp));// local cache 缓存5分钟appSimpleInfoCache.put(simpleApp.getPayAppId(), simpleApp);log.info("localCache_AppSimpleInfoDTO_suc. [simpleApp={}]", JSON.toJSONString(simpleApp));});result.add(simpleApp);}}}// 重新排序final Map<String, AppSimpleInfoDTO> payAppIdMap = result.stream().collect(Collectors.toMap(AppSimpleInfoDTO::getPayAppId, Function.identity(), (old, newly) -> newly));result.clear();payAppIds.forEach(payAppId -> Optional.ofNullable(payAppIdMap.get(payAppId)).ifPresent(result::add));return result;}

本文参考:

Redis精通系列——Pipeline(管道)

相关文章:

编码技巧——Redis Pipeline

本文介绍Redis pipeline相关的知识点及代码示例&#xff0c;包括Redis客户端-服务端的一次完整的网络请求、pipeline与client执行多命令的区别、pipeline与Redis"事务"、pipeline的使用代码示例&#xff1b; pipeline与client执行多命令的区别 Redis是一种基于客户…...

ArcGIS制图技巧:制图入门与点、线、面状符号制作

目的&#xff1a; 1、了解地图制作目的&#xff1b; 2、了解在ArcMap平台中制作地图大致过程。 3、掌握地形图生成的操作&#xff1b; 4、掌握地形图的正确输出方法。 5、理解点状符号、线状符号、面状符号的基本概念&#xff1b; 6、理解地形点状符号、线状符号、面状符…...

Java基础 关于字典数据维护接口设计

开发环境 Eclipse2022JDK1.8 目录 1. 概述 2. 实现步骤 2.1 定义通用接口 2.2 定义实体类 2.3 接口扩展 2.4 接口实现 2.5 功能测试 3. 结语 1. 概述 每一个信息系统或多或少都带有一些数据字典&#xff0c;在维护上&#xff0c;基本上分为增删改查&#xff0c;也就是对数据…...

从零开始学架构——复杂度来源

复杂度来源——高性能 对性能孜孜不倦的追求是整个人类技术不断发展的根本驱动力。例如计算机,从电子管计算机到晶体管计算机再到集成电路计算机,运算性能从每秒几次提升到每秒几亿次。但伴随性能越来越高&#xff0c;相应的方法和系统复杂度也是越来越高。现代的计算机CPU集成…...

什么时候需要分表分库?

在当今互联网时代&#xff0c;海量数据基本上是每一个成熟产品的共性&#xff0c;特别是在移动互联网产品中&#xff0c;几乎每天都在产生数据&#xff0c;例如&#xff0c;商城的订单表、支付系统的交易明细以及游戏中的战报等等。对于一个日活用户在百万数量级的商城来说&…...

冰刃杀毒工具使用实验(29)

实验目的 &#xff08;1&#xff09;学习冰刃的基本功能&#xff1b; &#xff08;2&#xff09;掌握冰刃的基本使用方法&#xff1b;预备知识 windows操作系统的基本知识&#xff0c;例如&#xff1a;进程、网络、服务和文件等的了解。 冰刃是一款广受好评的ARK工…...

聊聊图像分割的DICE和IOU指标

目录 1. 介绍 2. dice 和 iou 的联系 3. 代码实现 3.1 dice 3.2 iou 3.3 test 3.4 dice 和 iou 的关系曲线 4. 代码 1. 介绍 dice 和 iou 都是衡量两个集合之间相似性的度量 dice计算公式&#xff1a; iou计算公式&#xff1a; iou的集合理解&#xff1a; iou 其实就…...

软件设计师教程(十)计算机系统知识-结构化开发

软件设计师教程 软件设计师教程&#xff08;一&#xff09;计算机系统知识-计算机系统基础知识 软件设计师教程&#xff08;二&#xff09;计算机系统知识-计算机体系结构 软件设计师教程&#xff08;三&#xff09;计算机系统知识-计算机体系结构 软件设计师教程&#xff08;…...

链表OJ之 快慢指针法总结

欢迎来到 Claffic 的博客 &#x1f49e;&#x1f49e;&#x1f49e; 前言&#xff1a; 快慢指针指的是每次指针移动的步长&#xff0c;是解决链表相关的题目的一大利器&#xff0c;下面我将以例题的形式讲解快慢指针法。 目录 一. 链表的中间结点 思路&#xff1a; 代码实…...

C++STL详解(五)——list的介绍与使用

文章目录list的介绍list的使用list的定义方法list迭代器失效问题list插入和删除inserteraselist迭代器的使用begin&#xff0c;end 和 rbegin&#xff0c;rendlist元素访问front 和 backlist容量控制与数据清理resizeclearlist操作函数spliceremove 和 remove_ifuniquemergerev…...

进程和进程的调度

今天,为大家带来进程和进程的调度的学习 1.认识计算机 2.什么是操作系统 3.什么是进程 4.进程管理 5.进程的属性 6.进程的调度 7.进程调度的过程 8.内存分配 1.认识计算机 计算机的组成有五大部分 1.CPU(是计算机的大脑,负责逻辑运算和控制) 2.内存 3.外存 4.输入…...

TypeScript 深度剖析:TypeScript 的理解?与 JavaScript 的区别?

一、是什么 TypeScript 是 JavaScript 的类型的超集&#xff0c;支持ES6语法&#xff0c;支持面向对象编程的概念&#xff0c;如类、接口、继承、泛型等 超集&#xff0c;不得不说另外一个概念&#xff0c;子集&#xff0c;怎么理解这两个呢&#xff0c;举个例子&#xff0c;如…...

美颜SDK关键技术讲解——人脸识别与人脸美化

拍摄&#xff0c;自从智能手机普及之后就已经不再是小众爱好&#xff0c;使用手机拍摄记录生活几乎成了人们的日常。在巨量的需求下&#xff0c;美颜工具、美颜SDK已经被广泛应用于各大视频拍摄平台。虽然经常听到美颜SDK&#xff0c;但是大多数人并不了解它&#xff0c;下文小…...

Linux下C/C++ 网络扫描(主机扫描技术)

主机扫描是网络扫描的基础&#xff0c;通过对目标网络中主机IP地址的扫描&#xff0c;从一堆主机中扫描出存活的主机&#xff0c;然后以他们为目标进行后续的攻击。一般会借助于ICMP、TCP、UDP等协议的工作机制&#xff0c;检查打开的进程&#xff0c;开放的端口号等等。 主机…...

无法将“vue-cli-service”项识别为 cmdlet、函数、脚本文件或不是内部命令的原因和解决方案

经常有小伙伴问我说&#xff0c;为什么我们在开发vue项目的时候&#xff0c;需要在package.json的script对象中&#xff0c;去设置命令启动项目&#xff0c;而不是直接的通过"vue-cli-service serve"命令去把项目跑起来。带着这些疑问&#xff0c;小生在此总结了以下…...

逆流程 场景下 处理状态机变化的方案

背景&#xff1a; 针对某些业务场景下&#xff0c;存在逆流程。 比如场景的场景 正向流程如&#xff0c;发起某项申请->对某项申请进行审批。&#xff08;审批为通过/驳回&#xff09;。这样这个工作流程就算到最终态。 常见的状态机如&#xff0c; 申请未提交&#xff0…...

【剧前爆米花--爪哇岛寻宝】Java实现无头单向非循环链表和无头双向链表与相关题目

作者&#xff1a;困了电视剧 专栏&#xff1a;《数据结构--Java》 文章分布&#xff1a;这是关于数据结构链表的文章&#xff0c;包含了自己的无头单向非循环链表和无头双向链表实现简单实现&#xff0c;和相关题目&#xff0c;想对你有所帮助。 目录 无头单向非循环链表实现 …...

学习MvvmLight工具

最近学习了一下MvvmLight&#xff0c;觉得有些功能还是挺有特色的&#xff0c;所以记录一下 首先新建也给WPF程序 然后在Nuget里面安装MvvmLightLib 包&#xff0c;安装上面那个也可以&#xff0c;但是安装上面那个会自动在代码里面添加一些MvvmLight的demo &#xff0c;安装M…...

基于BiLSTM+CRF医学病例命名实体识别项目

研究背景 为通过项目实战增加对命名实体识别的认识&#xff0c;本文找到中科院软件所刘焕勇老师在github上的开源项目&#xff0c;中文电子病例命名实体识别项目MedicalNamedEntityRecognition。对其进行详细解读。 原项目地址&#xff1a;https://github.com/liuhuanyong/Med…...

05 C语言数据类型

05 C语言数据类型 1、数据类型 编程语言对数据类型分为两派&#xff1a;一种认为要注重&#xff0c;一种认为可以忽视。 C语言类型 1、整数 : char < short < int < long < long long &#xff0c;bool 2、浮点数&#xff1a;float < double < long doub…...

C++11:右值引用和移动语义

文章目录1. 左值和右值表达式1.1 概念1.2 左值和右值2. 左值引用和右值引用2.1 相互引用2.2 示例代码2.3 左值引用使用场景缺点2.4 右值引用和移动语义小结2.5 移动赋值2.6 右值引用的其他使用场景右值引用版本的插入函数3. 完美转发3.1 万能引用3.2 如何实现完美转发3.3 完美转…...

tcpdump网络抓包工具

tcpdump 是一个强大的网络抓包工具&#xff0c;在分析服务之间调用时非常有用。可以将网络中传送的数据包抓取下来进行分析。tcpdump 提供灵活的抓取策略&#xff0c;支持针对网络层、协议、主机、网络或端口的过滤&#xff0c;并提供 and、or、not 等逻辑语句来去掉不想要的信…...

MaxCompute SQL中的所有保留字与关键字如下

– MaxCompute SQL中的所有保留字与关键字如下 注意 命名表、列或分区时&#xff0c;不要使用保留字与关键字&#xff0c;否则可能会报错。 保留字不区分大小写。 在对表、列或是分区命名时如若使用关键字&#xff0c;需给关键字加符号进行转义&#xff0c;否则会报错。 % &am…...

Kafka 压缩算法

压缩 (compression) : 用时间换空间的思想 用较小的 CPU 开销获得磁盘少占用或网络 I/O 少传输 Kafka 消息分两层&#xff1a; 消息日志组成 : n 个消息集合消息集合 (message set) 组成 : n 条日志项 (record item)日志项封装了消息 (message)Kafka 在消息集合层上进行写入…...

关于React Hook(18)

useState&#xff08;&#xff09;&#xff1a;&#x1f449;详情 &#xff08;必须“有条件地调用”&#xff1b;注意避免冗余状态的产生&#xff09; 关于useState的两种使用方式的区别&#xff1a;&#x1f449;详情 关于batch机制&#xff1a;有条件地调用一些状态的set方…...

计算机网络:BGP协议

BGP协议 与其他AS的邻站BPG发言人交换信息。 交换的网络可达性信息&#xff0c;即要到达某一个网络所要经历的一系列AS 发生变化时&#xff0c;更新有变化的部分 BGP协议交换信息的过程&#xff1a;所交换的网络可达性信息就是要到达某一个网络所要经历的一系列AS&#xff…...

91. 解码方法 ——【Leetcode每日刷题】

91. 解码方法 一条包含字母 A-Z 的消息通过以下映射进行了 编码 &#xff1a; ‘A’ -> “1” ‘B’ -> “2” … ‘Z’ -> “26” 要 解码 已编码的消息&#xff0c;所有数字必须基于上述映射的方法&#xff0c;反向映射回字母&#xff08;可能有多种方法&#xff0…...

人体存在传感器成品方案,精准感知静止存在,实时智能化感控技术

随着现今智能时代的发展&#xff0c;酒店也越来越趋于智能化&#xff0c;也在不断地推行智慧酒店&#xff0c;这也给人们入住酒店提供了良好的体验。 人体存在感知是智能酒店中极其重要的一项应用技术&#xff0c;只有智能设备通过精准地感知人体存在&#xff0c;才能更好地做…...

mysql连接池的实现

目录 1 池化技术 2 什么是数据库连接池 3 为什么使用数据库连接池 3.1 不使用连接池 3.2 使用连接池 3.3 长连接和连接池的区别 4 数据库连接池运行机制 5 连接池和线程池的关系 6 线程池设计要点 6.1 连接池设计逻辑 构造函数 初始化 请求获取连接 归还连接 析…...

哪种类型蓝牙耳机佩戴最舒服?舒适度最好的蓝牙耳机推荐

如果您想在外出时听自己喜欢的音乐&#xff0c;您需要佩戴耳机&#xff0c;当前的耳机都足够小&#xff0c;可以将它们放在口袋里&#xff0c;即使它们在充电盒中也是如此&#xff0c;舒适度一直都是人们所追求的&#xff0c;舒适之余&#xff0c;佩戴同样稳固更加令人安心&…...