作者文章

fwq

FWQ
服务器教程
Redis中过期策略是怎么样的
Redis中过期策略是怎么样的 收藏 最近发现不少小伙伴都对数据库很感兴趣,所以今天继续给大家介绍数据库相关的知识,本文《Redis中过期策略是怎么样的》主要内容涉及到等等知识点,希望能帮到你!当然如果阅读本文时存在不同想法,可以在评论中表达,但是请勿使用过激的措辞~ 保存过期时间 Redis可以为每个key设置过期时间,会将每个设置了过期时间的key放入一个独立的字典中。【相关推荐:Redis视频教程】 typedef struct redisDb {  int id; //id是数据库序号,为0-15(默认Redis有16个数据库)  long avg_ttl; //存储的数据库对象的平均ttl(time to live),用于统计  dict *dict; //存储数据库所有的key-value  dict *expires; //存储key的过期时间  dict *blocking_keys;//blpop 存储阻塞key和客户端对象  dict *ready_keys;//阻塞后push 响应阻塞客户端 存储阻塞后push的key和客户端对象 dict *watched_keys;//存储watch监控的的key和客户端对象  } redisDb; dict 用来维护一个 Redis 数据库中包含的所有 Key-Value 键值对,expires则用于维护一个 Redis 数据库中设置了失效时间的键(即key与失效时间的映射)。注意这里的失效时间是用毫秒的时间戳表示的,比如2022-01-02 22:45:02过期则value为1641134702000 当我们使用expire命令设置一个key的失效时间时,Redis 首先到 dict 这个字典表中查找要设置的key是否存在,如果存在就将这个key和失效时间添加到 expires 这个字典表。…
2025-05-10 阅读全文 →
FWQ
服务器教程
如何使用Redis和PHP实现分布式消息系统
如何使用Redis和PHP实现分布式消息系统 亲爱的编程学习爱好者,如果你点开了这篇文章,说明你对《如何使用Redis和PHP实现分布式消息系统》很感兴趣。本篇文章就来给大家详细解析一下,主要介绍一下,希望所有认真读完的童鞋们,都有实质性的提高。 如何使用Redis和PHP实现分布式消息系统 随着互联网规模的不断扩大和业务的发展,分布式系统成为了很多企业的首选。在分布式系统中,消息传递的可靠性和高效性是非常重要的,因此实现一个可靠且高效的分布式消息系统是至关重要的。Redis是一个高性能的键值存储系统,它的特点是快速、稳定、可靠,并且有着丰富的数据结构和功能特性,因此可以与PHP结合来构建一个分布式消息系统。 在本文中,我将介绍如何使用Redis和PHP来实现一个简单的分布式消息系统。主要包括以下几个方面的内容:如何建立Redis连接、如何发送和接收消息、如何处理消息确认和重试、以及如何优化系统性能。 首先,我们需要在PHP中建立与Redis的连接。PHP提供了Redis扩展,我们可以使用它来连接Redis服务器。在建立连接前,我们需要先安装Redis扩展并开启Redis服务器。下面是一个简单的PHP代码示例: <?php $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $redis->auth('password'); // 如果设置了密码,需要验证密码 接下来,我们需要实现消息的发送和接收功能。在Redis中,我们可以使用列表(List)来充当消息队列的角色。发送消息即将消息插入到列表的尾部,接收消息即从列表的头部获取消息。下面是一个简单的PHP代码示例: // 发送消息 $message = 'Hello, World!'; $redis->rpush('message_queue', $message); // 接收消息 $message…
2025-05-10 阅读全文 →
FWQ
服务器教程
Redis中一个String类型引发的惨案
Redis中一个String类型引发的惨案 收藏 本篇文章向大家介绍《Redis中一个String类型引发的惨案》,主要包括类型、redisstring,具有一定的参考价值,需要的朋友可以参考一下。 ​ 曾经看到这么一个案例,有一个团队需要开发一个图片存储系统,要求这个系统能快速记录图片ID和图片存储对象ID,同时还需要能够根据图片的ID快速找到图片存储对象ID。我们假设用10位数来表示图片ID和图片存储对象ID,例如图片的ID为1101021043,它所对应的图片存储对象的ID为2301010051,可以看到图片ID和图片存储ID正好是一一对应的,是典型的key-value形式,所以首先会想到直接使用String类型来保存数据。把图片ID和图片存储ID分别作为键值对的key和value来保存。但是随着存储的数据量越来越大,Redis的内存的使用量也快速上升,结果遇到了大内存Redis实例因为生成RDB而响应变慢的问题。很显然String类型并不是一种好的选择, 那有什么办法可以降低内存消耗吗? String类型的数据结构 首先我们得先了解为什么String保存数据时所消耗的内存空间较大。在刚才的案例中,由于图片ID和图片存储对象ID都是10位数,我们可以用两个8字节的Long类型来表示这两个ID。所以一组图片ID及其存储对象ID的记录,实际只需要16字节就可以了。但是通过对Redis内存分析,一组图片ID及其存储对象ID却占用了64字节,那为什么String类型会用64字节呢。其实,除了要记录实际的数据,String类型还需要额外的内存空间来记录数据的长度、空间使用信息等,这些信息也叫做元数据。当实际保存的数据较小时,元数据的空间开销就显的比较大了。我们先来看一下String类型是如何保存数据的。当你保存64位有符号的整数时,String类型会把它保存为一个8字节的Long类型整数,这种保存方式通常也叫作int编码方式。但是,当你保存的数据中包含字符时,String类型就会用简单动态字符串结构体(SDS)来保存。如下图所示: len:4个字节,表示buf的已用长度。 alloc:4个字节,表示buf分配的长度,一般大于len。 buf:字节数组,保存实际数据。为了表示数组的结尾,Redis会自动在数组最后添加一个”\0″。 可以看到,在SDS结构体中,除了有保存实际数据的buf,还有len和alloc的额外元数据的开销。另外对于String类型来说,除了SDS的额外开销外,还有一个叫做RedisObject结构体的开销。因为Redis的数据类型有很多,不同的数据类型都有相同的元数据要记录(例如最后一次访问时间),所以Redis会采用一个叫做RedisObject结构体来统一记录这些元数据。一个RedisObject包含了一个8字节的元数据和一个8字节的指针,这个指针指向具体数据所在,例如String类型的SDS结构体所在的内存地址。如下图所示: 为了节省内存空间,Redis对Long类型整数和SDS的内存布局做了专门的设计。一方面,当保存的是 Long 类型整数时,RedisObject 中的指针就直接赋值为整数数据了,这样就不用额外的指针再指向整数了,节省了指针的空间开销。另一方面,当保存的是字符串数据,并且字符串小于等于 44 字节时,RedisObject 中的元数据、指针和 SDS 是一块连续的内存区域,这样就可以避免内存碎片。这种布局方式也被称为 embstr 编码方式。当字符串大于44字节时,SDS的数据量就开始变多了,Redis 就不再把SDS 和 RedisObject 布局在一起了,而是会给 SDS…
2025-05-10 阅读全文 →
FWQ
服务器教程
Redis分布式锁解决秒杀超卖问题
Redis分布式锁解决秒杀超卖问题 收藏 本篇文章向大家介绍《Redis分布式锁解决秒杀超卖问题》,主要包括Redis秒杀超卖,具有一定的参考价值,需要的朋友可以参考一下。 分布式锁应用场景 秒杀环境下:订单服务从库存中心拿到库存数,如果库存总数大于0,则进行库存扣减,并创建订单订单服务负责创建订单库存服务负责扣减库存 模拟用户访问库存 多线程并发访问,出现超卖问题,线程不安全。没有保证原子性 单体锁的分类 单体应用锁指的是只能在 一个JVM 进程内有效的锁。我们把这种锁叫做单体应用锁 synchronized锁ReentrantLock锁一个 Tomcat 可以看作是一个JVM进程,当大量请求并发到系统时,所有的请求都落在这唯一的一个Tomcat上,如果某些请求方法是需要加锁的,比如:秒杀扣减库存,是可以满足需求的,但是随着访问量的增加,导致一个tomcat 难以支撑,这时我们必然就是集群部署Tomcat ,使用多个 Tomcat 共同支撑整个系统。 我们看到系统中存在两个Tomcat,我们加的锁是JDK提供的锁,这种锁只能在 一个JVM 下起到作用,也就是在一个Tomcat内是没有问题的。当存在两个或两个以上的Tomcat时,大量的并发请求分散到不同的Tomcat上,在每一个Tomcat中都可以防止并发的产生,但是在多个Tomcat之间,每个Tomcat中获得锁的这个请求,又产生了并发,从而产生超卖现象。这也就是单体应用锁的局限性了,它只能在一个JVM内加锁,所以单体锁只能锁住单体环境,是锁不住分布式环境或集群环境的。 分布式锁核心逻辑 分布式锁的核心逻辑就是在多个服务中设置一个公共的资源,在公共资源中设置锁,供多个服务去同时抢夺锁资源,一旦其中一个线程抢夺成功,其他线程就进入自旋状态,不同的尝试访问获取锁资源,在获取锁资源的线程执行完相应的逻辑以后就会释放锁资源,其他线程就可以获取锁资源。 分布式锁实现的问题——死锁和解决 死锁:如果某个线程在执行锁逻辑过程中宕机,导致没有删除锁解决: 添加过期时间 因为是非原子性添加过期时间,可能导致在添加过期时间之前就出现宕机现象,此时依旧进入死锁状态。原子性添加过期时间 Redis解决删除别人锁的问题…
2025-05-10 阅读全文 →
FWQ
服务器教程
Redis如何实现分布式事务的一致性
Redis如何实现分布式事务的一致性 对于一个数据库开发者来说,牢固扎实的基础是十分重要的,golang学习网就来带大家一点点的掌握基础知识点。今天本篇文章带大家了解《Redis如何实现分布式事务的一致性》,主要介绍了,希望对大家的知识积累有所帮助,快点收藏起来吧,否则需要时就找不到了! Redis是一个高性能、分布式内存数据库,被广泛应用在分布式系统中。在分布式系统中,如何实现事务的一致性一直是一个难题,而Redis提供的事务机制可以帮助开发者解决这个问题。本文将介绍Redis如何实现分布式事务的一致性,并展示代码示例。 一、Redis事务机制简介 Redis在2.0版本中就提供了事务机制,该机制通过MULTI、EXEC、WATCH、DISCARD和UNWATCH五个命令来实现。事务中的操作会被顺序记录在一个队列中,并在EXEC命令被调用时批量执行。如果整个事务以成功提交,那么记录队列中的所有操作将被依次执行;如果一个操作失败,那么整个事务将被回滚。多个客户端可以同时开启自己的事务,由于面向操作记录队列执行,所以事务之间是相互独立的。 二、Redis分布式事务实现原理 在Redis单机事务中,每个客户端都是由同一个进程处理,而在分布式情况下,每个客户端可能对应不同的Redis实例,这就需要实现分布式事务一致性来保证数据的正确性。 Redis实现分布式事务的关键在于WATCH和UNWATCH命令。每个客户端可以通过WATCH命令在Redis中标记一些关键的数据,当这些数据被其他客户端修改时,这个客户端的事务就会被终止。通过UNWATCH命令可以解除这个标记。这样做的原因是当用户开启事务时,如果与其它客服端存在相同的写入竞争,则事务会回滚,并设置一个事务失败的信号。在这个过程中,客户端需要将其所有需要被监控的关键数据唯一标识,当发生冲突时,客户端会根据这些标识判定是否需要回滚事务。如果需要回滚,客户端会重新尝试执行该事务。 三、代码示例 下面我们用Python实现一个简单的分布式事务,模拟两个客户端分别在不同的Redis实例上执行事务,实现转账操作,要求转账必须成功,使用WATCH/UNWATCH命令实现一致性控制。 Prerequisites: Python 3.x Redis-py 代码如下: import redis # 新建两个 Redis 实例 redis1 = redis.StrictRedis(host="localhost", port=6379, db=0) redis2 =…
2025-05-10 阅读全文 →
FWQ
服务器教程
Redis删除策略的三种方法及逐出算法
Redis删除策略的三种方法及逐出算法 收藏 对于一个数据库开发者来说,牢固扎实的基础是十分重要的,golang学习网就来带大家一点点的掌握基础知识点。今天本篇文章带大家了解《Redis删除策略的三种方法及逐出算法》,主要介绍了算法、策略、Redis删除、逐出,希望对大家的知识积累有所帮助,快点收藏起来吧,否则需要时就找不到了! 一、前言 在文章开始之前,我先问大家一个问题:当我们使用指令:expire key second给一个key设置过期时间,过期时间一到,这个key对应的过期数据真的被服务器立即删除了吗?答案是并不会立即删除。知道了这个答案,就来看看Redis中如何处理过期的数据。 二、Redis中的数据特征 Redis是一种内存级数据库,所有数据均存放在内存中,内存中的数据可以通过TTL指令获取其状态,有三种状态:  指令结果 状态 XX 具有时效性的数据 -1 永久有效的数据 -2 已经过期的数据 或 被删除的数据 或 未定义的数据 三、时效性数据储存结构 当我们用指令设置过期数据后,数据对应的地址会放在expires空间中,存储方式是哈希,存储的value是过期时间。 四、数据删除策略 数据删除策略目标:在内存占用与CPU占用之间寻找一种平衡,顾此失彼都会造成整体redis性能的下降,甚至引发服务器宕机或内存泄露 1、定时删除 创建一个定时器,当key设置有过期时间,且过期时间到达时,由定时器任务立即执行对键的删除操作 优点:节约内存,到时就删除,快速释放掉不必要的内存占用 缺点:CPU压力很大,无论CPU此时负载量多高,均占用CPU,会影响redis服务器响应时间和指令吞吐量…
2025-05-10 阅读全文 →
FWQ
服务器教程
浅谈Redis的异步机制
浅谈Redis的异步机制 收藏 IT行业相对于一般传统行业,发展更新速度更快,一旦停止了学习,很快就会被行业所淘汰。所以我们需要踏踏实实的不断学习,精进自己的技术,尤其是初学者。今天golang学习网给大家整理了《浅谈Redis的异步机制》,聊聊Redis异步,我们一起来看看吧! Redis 内部的阻塞式操作: CPU 核和 NUMA 架构的影响; Redis 关键系统配置; Redis 内存碎片; Redis 缓冲区。 一、Redis 的阻塞点 和 Redis 实例交互的对象,以及交互时会发生的操作: 客户端:网络 IO,键值对增删改查操作,数据库操作; 磁盘:生成 RDB 快照,记录 AOF 日志,AOF 日志重写;…
2025-05-10 阅读全文 →
FWQ
服务器教程
Redis实现分布式日志处理的方法与应用实例
Redis实现分布式日志处理的方法与应用实例 本篇文章主要是结合我之前面试的各种经历和实战开发中遇到的问题解决经验整理的,希望这篇《Redis实现分布式日志处理的方法与应用实例》对你有很大帮助!欢迎收藏,分享给更多的需要的朋友学习~ 随着云计算和大数据的不断发展,在业务系统中产生的日志数量也越来越庞大,如何高效处理这些日志数据成为了一个亟待解决的问题。在这个背景下,分布式日志处理显得尤为重要。Redis是目前比较常用的一种NoSQL数据库,本文将介绍Redis如何实现分布式日志处理,同时结合一个应用实例说明其应用场景。 一、为什么选择Redis Redis是一个基于内存的数据存储系统,具有高性能、高可用性、高并发等优点。它支持多种数据结构,如字符串、哈希、列表、集合等,能够满足业务系统中各种数据存储需求。此外,Redis还支持主从复制、哨兵机制、集群等特性,保证了数据的可靠性和高可用性。 在日志处理中,Redis的内存存储优势尤为明显。基于内存的存储可以快速处理数据,同时能够支持高并发场景,为分布式日志处理提供了很好的支持。 二、Redis实现分布式日志处理 Redis可以通过发布/订阅模式(Pub/Sub)实现分布式日志处理。Pub/Sub模式是一种消息分发机制,支持消息的广播和订阅,可以将消息发送到多个消费者,实现分布式处理。下面,我们详细介绍如何使用Redis实现分布式日志处理。 定义消息格式 在使用Pub/Sub模式时,需要规定消息格式。通常使用json格式作为消息体,类似于以下结构: { "log_id": "1234", "log_time": "2022-01-01 00:00:00", "log_level": "INFO", "log_content": "Hello World!" } 其中,log_id是唯一标识符,log_time是日志产生时间,log_level是日志级别,log_content是日志内容。 发布日志 在产生日志时,将日志消息发布到Redis中。代码如下: import redis import…
2025-05-10 阅读全文 →
FWQ
服务器教程
Redis链表底层实现及生产实战
Redis链表底层实现及生产实战 收藏 哈喽!今天心血来潮给大家带来了《Redis链表底层实现及生产实战》,想必大家应该对数据库都不陌生吧,那么阅读本文就都不会很困难,以下内容主要涉及到redis链表,若是你正在学习数据库,千万别错过这篇文章~希望能帮助到你! Redis 的 List 是一个双向链表,链表中的每个节点都包含了一个字符串。是redis中最常用的数据结构之一,下面跟大家分享下redis链表的底层实现以及生产实战。 底层实现 Redis的list数据结构底层实现是基于双向链表实现的。双向链表是一种常见的数据结构,它由一系列节点组成,每个节点都由一个listNode结构表示,其中包含了一个指向前一个节点的指针prev、一个指向后一个节点的指针next和一个存储值的指针value。在Redis中,每个节点代表一个元素,节点之间通过指针连接起来,形成一个双向链表。 双向链表的好处是可以快速地在头部和尾部进行插入和删除操作。在Redis中,当一个新的元素被插入到List的头部或者尾部时,只需要修改新节点的prev和next指针以及原来头部或尾部节点的prev或next指针即可完成插入操作,时间复杂度为O(1)。同样的,当一个元素被删除时,只需要修改前一个节点的next指针或者后一个节点的prev指针即可完成删除操作,时间复杂度也为O(1)。 除了双向链表,Redis还使用了一些其他的技术来优化List数据结构的性能。例如,当List中的元素数量超过一定阈值时,Redis会将List转换为压缩列表(zip list),这样可以减少内存的使用和提高访问速度。在对List进行迭代操作时,Redis使用了迭代器(iterator)来遍历List中的元素,这样可以避免在遍历过程中对List进行修改而导致的错误。 Redis的list数据结构支持在头部或尾部插入或删除元素,以及在指定位置插入或删除元素。这些操作都可以在常数时间内完成,因为Redis的双向链表实现支持快速访问头部和尾部节点,以及在指定位置插入和删除节点。 下面是一些常见的Redis list操作及其时间复杂度: LPUSH:在头部插入元素,时间复杂度为O(1)。 RPUSH:在尾部插入元素,时间复杂度为O(1)。 LPOP:删除头部元素,时间复杂度为O(1)。 RPOP:删除尾部元素,时间复杂度为O(1)。 LINDEX:访问指定位置的元素,时间复杂度为O(n)。 LINSERT:在指定位置插入元素,时间复杂度为O(n)。 LREM:删除指定元素,时间复杂度为O(n)。 以上图片转载至黄建宏的《Redis设计与实战》pdf。 源码实现 Redis List数据结构的底层代码实现demo,使用C语言实现: typedef struct…
2025-05-10 阅读全文 →
FWQ
服务器教程
单线程Redis很快?带你看看原因
单线程Redis很快?带你看看原因 收藏 在IT行业这个发展更新速度很快的行业,只有不停止的学习,才不会被行业所淘汰。如果你是数据库学习者,那么本文《单线程Redis很快?带你看看原因》就很适合你!本篇内容主要包括单线程Redis很快?带你看看原因,希望对大家的知识积累有所帮助,助力实战开发!  Redis 作为一种 KV 缓存服务器,有着极高的性能,相对于 Memcache,Redis 支持更多种数据类型,因此在业界应用广泛。 记得刚毕业那会参加面试,面试官会问我 Redis 为什么快,由于当时技术水平有限,我只能回答出如下两点: 数据是存储在内存中的。 Redis 是单线程的。 当然,将数据存储在内存中,读取的时候不需要进行磁盘的 IO,单线程也保证了系统没有线程的上下文切换。 但这两点只是 Redis 高性能原因的很小一部分,下面从数据存储层面上为大家分析 Redis 性能为何如此高。 Redis性能如此高的原因,我总结了如下几点: 纯内存操作 单线程 高效的数据结构 合理的数据编码 其他方面的优化…
2025-05-10 阅读全文 →