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

学习小记-一些Redis小知识

目录

虚拟内存

事务机制

Pipeline

Lua

乐观锁


虚拟内存

Redis 的虚拟内存(VM, Virtual Memory)是一种数据存储技术,它允许 Redis 在物理内存不足时,将部分数据临时存储到磁盘上。这项技术主要用于处理大量数据时减少内存的使用,以及提高数据的持久性。

但是:这种设计带来了一些问题:

  1. 性能开销::虚拟内存的使用增加了额外的磁盘I/O操作,这会显著降低Redis的性能,因为磁盘访问速度远不如内存访问速度。
  2. 复杂性::虚拟内存功能的管理增加了Redis运行的复杂性,尤其是在数据管理和性能调优方面。

Redis 4.0 以后的版本中,虚拟内存功能不再是默认启用的,因为现代服务器通常有足够的物理内存来存储所有数据。然而,如果你的应用程序需要处理大量数据,并且希望减少内存使用,你可以考虑手动启用虚拟内存功能。

事务机制

Redis 的事务机制是一种将多个命令打包执行的能力,确保这些命令要么全部执行,要么全部不执行,从而保持操作的原子性。事务在 Redis 中通过 MULTIEXECWATCH DISCARD 等命令实现。

缺点:

  1. 不支持回滚:如果事务执行过程中发生错误,Redis会继续执行剩余的命令而不是回滚整个事务。
  2. 不保证隔离性:即在事务执行期间,其他客户端可能可以读取到事务部分执行的结果。

相信有很多小伙伴到这里会问了:不支持回滚怎么保证原子性?其实你犯了一个错误,错误的将数据库ACID的原子性理解成了并发编程的原子性。数据库中事务是指“要么都执行,要么都回滚”。而并发并编程的原子性是指“操作不可拆分,不被中断”。

Pipeline

Redis 的 Pipeline(管道)是一种技术,它允许客户端将多个 Redis 命令打包在一起,然后一次性发送到服务器。使用 Pipeline 可以显著提高客户端和 Redis 服务器之间的通信效率,因为它减少了往返次数(即减少了网络延迟的影响)。

优点

  1. 减少网络往返:通过将多个命令一次性发送,而不是发送一个命令后等待响应再发送下一个命令,可以减少网络往返次数。

  2. 提高性能:Pipeline 可以显著提高执行多个命令的性能,因为它减少了等待时间。

  3. 原子性:在同一个 Pipeline 中发送的所有命令会作为一个整体一起执行,这意味着它们是原子性的。不过,请注意,这并不保证跨多个 Pipeline 的原子性。

  4. 脚本执行:Pipeline 可以用于执行 Lua 脚本,这可以进一步减少网络往返,因为 Lua 脚本可以包含多个命令。

缺点:

  1. 不保证原子性:他的多个命令都是独立执行的,Redis并不保证这些命令可以以不可分割的原子操作进行执行。这是Pipeline和Redis的事务的最大的区别。
  2. 你不能使用那些需要在命令执行前知道上一个命令结果的命令(如 WATCH 和事务命令)。

使用场景:

  • 当你需要执行多个键值操作,如 SETGETINCRLPUSH 等。
  • 当你需要批量获取或设置多个键的值。
  • 当你需要执行一系列命令,而这些命令可以一次性发送以提高效率。

使用Jedis可以实现Redis的事务和Pipeline

// ---------事务-----------
Jedis jedis = new Jedis("localhost", 6379)
// 开始事务
jedis.multi();// 在事务中执行多个命令
jedis.set("key1", "value1");
jedis.set("key2", "value2");
jedis.incr("counter"); // 假设 counter 是一个已经存在的计数器键// 执行事务,并获取所有命令的响应结果
List<Object> results = jedis.exec();
if (results != null) {
// 遍历结果for (Object result : results) {System.out.println(result);}
} else {// 如果事务因为某些原因被中断(如 Watch 失败),则结果将为 nullSystem.out.println("事务执行被中断");
}
// 关闭 Jedis 连接
jedis.close();// ---------Pipeline-----------
Jedis jedis = new Jedis("localhost", 6379); // 创建 Jedis 实例连接到 Redis
Pipeline pipeline = jedis.pipelined(); // 开启 Pipeline// 向 Pipeline 添加命令
pipeline.set("key1", "value1");
pipeline.get("key1");
pipeline.incr("counter");// 执行 Pipeline 并获取所有响应
List<Object> results = pipeline.syncAndReturnAll();// 处理结果
String value1 = (String) results.get(0); // key1 的值
String value2 = (String) results.get(1); // key1 的值(通过 get 命令获取)
Long counter = (Long) results.get(2); // counter 的新值// 关闭 Jedis 连接
jedis.close();// Redission也可以实现事务和pipeline
// 假设redissonClient已经创建并配置好连接
RedissonClient redisson = Redisson.create()
RTransaction transaction = redisson.getTransaction();
RPipeline pipeline = redisson.pipeline();

Lua

Lua是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放。Redis 的 Lua 脚本是一种在 Redis 服务器上执行 Lua 代码的能力。Redis 从 2.6 版本开始内置了对 Lua 脚本的支持。使用 Lua 脚本,你可以实现以下目标:

  1. 原子性:Lua 脚本作为一个单独的命令执行,保证了脚本中的命令序列是原子性的。这意味着脚本中的所有命令要么全部执行,要么全部不执行,中间不会有其他命令插入。(也就是说,Redis保证以原子方式执行Lua脚本,但是不保证脚本中所有操作要么都执行或者都回滚。)

Lua脚本可以保证原子性,因为Redis会将Lua脚本封装成一个单独的事务,而这个单独的事务会在Redis客户端运行时,由Redis服务器自行处理并完成整个事务,如果在这个进程中有其他客户端请求的时候,Redis将会把它暂存起来,等到 Lua 脚本处理完毕后,才会再把被暂存的请求恢复。

  1. 减少网络开销:通过将多个命令打包在 Lua 脚本中一次性发送到服务器,可以减少客户端和服务器之间的网络往返次数。

  2. 复用性:客户端发送的 Lua 脚本会被缓存在 Redis 中,其他客户端可以复用这一脚本而不需要重新发送相同的逻辑代码。

  3. 执行复杂逻辑:Lua 脚本允许在 Redis 服务器上执行复杂的业务逻辑,而不需要在客户端进行多重逻辑处理。

Lua与事务的区别:Redis的事务在执行过程中,如果有某一个命令失败了,是不影响后续命令的执行的;而Lua脚本中,如果执行过程中某个命令执行失败了,是会影响后续命令执行的。

乐观锁

用WATCH命令可以实现乐观锁:这个命令一旦运行,他会确保只有在 WATCH 监视的键在调用 EXEC 之前没有改变时,后续的事务才会执行。

WATCH cainiao
GET cainiao
MULTI
set cainiao <从GET获得的值 + 任务增量>
EXEC

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 《警世贤文》摘抄:处人篇、受恩篇、宽人篇、听劝篇、劝善篇(多读书、多看报、少吃零食多睡觉)
  • 公司想无偿裁员,同事赖着不走
  • HTML+CSS+JS井字棋(来自动下棋)
  • 408数据结构-图的应用2-最短路径 自学知识点整理
  • RuntimeError: cuDNN error: CUDNN_STATUS_NOT_SUPPORTED.
  • 「Pytorch」roLabelImg 图像异常旋转 bug
  • 详解C#委托与事件
  • docker inspect 如何提取容器的ip和端口 网络信息?
  • 【JavaScript】聊一聊js中的浅拷贝与深拷贝与手写实现
  • 【vue教程】二. Vue特性原理详解
  • 漏洞挖掘 | EDU拿敏感信息的骚思路
  • 如何构建全生命周期的安全体系架构来确保容器的安全?
  • ARM功耗管理之功耗数据与功耗收益评估
  • FastAPI 学习之路(四十九)WebSockets(五)修复接口测试中的问题
  • ScrapySharp框架:小红书视频数据采集的API集成与应用
  • 【Leetcode】101. 对称二叉树
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • CSS 提示工具(Tooltip)
  • input的行数自动增减
  • jquery ajax学习笔记
  • OSS Web直传 (文件图片)
  • Otto开发初探——微服务依赖管理新利器
  • PHP 的 SAPI 是个什么东西
  • SpiderData 2019年2月13日 DApp数据排行榜
  • 从tcpdump抓包看TCP/IP协议
  • 干货 | 以太坊Mist负责人教你建立无服务器应用
  • 官方新出的 Kotlin 扩展库 KTX,到底帮你干了什么?
  • 基于Vue2全家桶的移动端AppDEMO实现
  • 将回调地狱按在地上摩擦的Promise
  • 使用agvtool更改app version/build
  • 听说你叫Java(二)–Servlet请求
  • 译自由幺半群
  • 看到一个关于网页设计的文章分享过来!大家看看!
  • UI设计初学者应该如何入门?
  • #define 用法
  • #pragma multi_compile #pragma shader_feature
  • #stm32驱动外设模块总结w5500模块
  • #Z0458. 树的中心2
  • $(this) 和 this 关键字在 jQuery 中有何不同?
  • (仿QQ聊天消息列表加载)wp7 listbox 列表项逐一加载的一种实现方式,以及加入渐显动画...
  • (附源码)springboot青少年公共卫生教育平台 毕业设计 643214
  • (回溯) LeetCode 46. 全排列
  • (剑指Offer)面试题41:和为s的连续正数序列
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (十一)手动添加用户和文件的特殊权限
  • (四)库存超卖案例实战——优化redis分布式锁
  • (五)Python 垃圾回收机制
  • ?.的用法
  • @Bean, @Component, @Configuration简析
  • @Transactional事务注解内含乾坤?
  • @Value读取properties中文乱码解决方案
  • [ C++ ] STL---string类的模拟实现
  • [Angularjs]asp.net mvc+angularjs+web api单页应用
  • [AutoSar]状态管理(五)Dcm与BswM、EcuM的复位实现
  • [BT]小迪安全2023学习笔记(第29天:Web攻防-SQL注入)