作者文章

fwq

FWQ
服务器教程
以Redis为例,详谈分布式系统缓存的细枝末节
以Redis为例,详谈分布式系统缓存的细枝末节 收藏 本篇文章主要是结合我之前面试的各种经历和实战开发中遇到的问题解决经验整理的,希望这篇《以Redis为例,详谈分布式系统缓存的细枝末节》对你有很大帮助!欢迎收藏,分享给更多的需要的朋友学习~  在分布式Web程序设计中,解决高并发以及内部解耦的关键技术离不开缓存和队列,而缓存角色类似计算机硬件中CPU的各级缓存。如今的业务规模稍大的互联网项目,即使在最初beta版的开发上,都会进行预留设计。但是在诸多应用场景里,也带来了某些高成本的技术问题,需要细致权衡。 本系列主要围绕分布式系统中服务端缓存相关技术,也会结合朋友间的探讨提及自己的思考细节。文中若有不妥之处,恳请指正。本文是本系列的第一篇,打算尽可能详细地谈谈缓存自身的基础设计应用,以及相关的操作细节等(具体应用主要以Redis举例)。 一、服务端数据缓存 1一种区分 缓存基于不同的条件有很多种划分方式,本地缓存(Local cache)和分布式缓存(Distributed cache)是一种常见分类,两者自身又包含很多细类。 本地并不是指程序所在本地服务器(从严格概念来说),而是更细粒度的指位于程序自身的内部存储空间,而分布式更多强调的是存储在进程之外的一个或者多个服务器上,彼此交互通信,在具体软件项目的设计和应用中,多数时候是混合一体。当然,个人认为对缓存本质的理解才是最重要的,至于概念上的分类只是一个不同理解下的划分而已。 2一些技术成本 在具体项目架构设计时,单纯使用前者(本地缓存)的开发成本毋庸置疑是极低的,主要考虑的是本机的内存负载或者极少量的磁盘I/O影响。而后者的设计初心是为了利于分布式程序之间缓存数据的高效共享和管理,除了考虑缓存所在服务器自身的内存负载,设计时更需要充分考虑网络I/O、CPU的负载,以及某些场景下的磁盘I/O的代价,同时还在具体设计时尽可能规避和权衡整体稳定性和效率,这些不仅仅只是作为缓存服务器的硬件成本和技术维护。需要谨慎考虑的底层问题包括缓存间通信、网络负载和延迟等各种需要权衡的细节。 其实如果理解了缓存本质就该知道,任何存储介质在适当的场景下都可以充当一个高效的缓存角色并进行项目集成和缓存间集群。常见主流的Memcached和Redis等均是属于后者范畴,甚至可以包括如基于NoSQL设计的MongoDB这类文档数据库(但这是从角色角度讲,而狭义划分上这是基于磁盘的存储库,需要注意,各有专攻)。 这些第三方缓存在进行项目集成和缓存间集群,也需要解决一些问题。甚至项目迭代到了后期阶段,往往还需要具备较高专业知识的运维同时参与,并且在开发中的逻辑设计和代码实现也会增加一定的工作量。所以有时候在具体项目的设计上,一方面要尽可能预留,一方面还得根据实际情况尽可能精简。 额外说下其他体会:在个人有限的技术学习和实践里,关于节点数据交互,尤其是服务间通信,是不存在完美的闭环的,理论上也都是在“当前阶段”面向“高一致”的权衡罢了(大概跟生活是一样的吧)。 二、缓存数据库结构的设计细节 由于目前个人工作中大多数情况应用的是Redis 3.x,以下若有特性关联,均是以此作为参照说明。 1实例(Instance) 根据业务场景,公共数据和业务耦合数据,一定分别使用不同的实例。如果是单实例,才可以考虑以DB划分。当你使用的是Redis,那么DB在Redis里是有数据隔离,但没有严格权限限制,所以划库只是一种选择。在Cluster集群里则是保持默认单个库,不过实际中我会尝试根据项目大小来调整,至于在哪个开发阶段则是作为预留设计。 额外需要注意的是,作为重度依赖服务器内存的缓存产品,如果开启了持久化(后面会提到),并且在为并发量极大的服务提供支持时,服务器硬件资源会出现大量抢占,请结合持久策略配置,考虑实例是否进行分盘存储。 持久化本质是将内存数据同步写入硬盘(刷盘),而磁盘I/O实在有限,被迫的写入阻塞除了造成线程阻塞和服务超时,还会导致额外异常甚至波及其他底层依赖服务。当然,我的建议是,如果条件允许,最好是在项目初期设计时就进行规划并确定。 2缓存“表”(Table) 一般缓存中并没有传统RDBMS中直观的表概念(往往以键值对“KV”形式存在),但从结构上来讲,键值对本身就可以组装为各种表结构。一般我会先生成数据库表关系图,然后分析什么时候存储字符串,什么时候存储对象,然后使用缓存键(KEY)进行表和字段(列)分割。 假定需要存储一个登录服务器表数据,包含字段(列):name、sign、addr,那么可以考虑将数据结构拆分为以下形式: { key : "server:name" , value : "xxxx" }  { key : "server:sign" , value : "yyyy" } …
2025-05-10 阅读全文 →
FWQ
服务器教程
Redis基本数据类型String常用操作命令
Redis基本数据类型String常用操作命令 收藏 在数据库实战开发的过程中,我们经常会遇到一些这样那样的问题,然后要卡好半天,等问题解决了才发现原来一些细节知识点还是没有掌握好。今天golang学习网就整理分享《Redis基本数据类型String常用操作命令》,聊聊String、操作命令、Redis数据类型,希望可以帮助到正在努力赚钱的你。 Redis数据类型String操作命令 一、append 追加字符串 append name 2222 二、strlen 获取key 字符串长度 strlen name 三、自增、自减 文章浏览量,点赞可以用这种实现。 incr agedecr age 注意这里得是数字才可以进行,所以重设置了一个key。 String类型除了可以存字符串也可以是数字。 如果要带步长: incrby age 5decrby age 8 四、字符串range…
2025-05-10 阅读全文 →
FWQ
服务器教程
Redis数组和链表深入详解
Redis数组和链表深入详解 收藏 本篇文章给大家分享《Redis数组和链表深入详解》,覆盖了数据库的常见基础知识,其实一个语言的全部知识点一篇文章是不可能说完的,但希望通过这些问题,让读者对自己的掌握程度有一定的认识(B 数),从而弥补自己的不足,更好的掌握它。 1.数组和链表基础知识 数组: 数组会在内存中开辟一块连续的空间存储数据,这种存储方式有利也有弊端。当获取数据的时候,直接通过下标值就可以获取到对应的元素,时间复杂度为O(1)。但是如果新增或者删除数据会移动大量的数据,时间复杂度为O(n)。数组的扩容机制是:如果数组空间不足,会先开辟一块新的空间地址,将原来的数组复制到新的数组中。 链表: 链表不需要开辟连续的内存空间,其通过指针将所有的数据连接起来。新增或者删除的时候只需要将指针指向的地址修改就行了,时间复杂度为O(1)。但是查询的时间复杂度为O(n)。 2、链表 2.1、双向链表 双向链表是各个节点之间的逻辑关系是双向的。 双向链表中节点的组成是:prior: 指向当前节点的前置节点,data:当前节点存储的数据。next:指向当前节点的后置节点。 2.2、压缩链表 压缩链表是为了节约内存开发的。 ziplist是一个特别的双向链表,没有维护双向指针prev next;反而是存储上一个entry的长度和当前entry长度,通过长度推算出下一个元素在什么地方。 牺牲读取的性能,获得高效的存储空间,因为存储指针比存储entry长度更费内存,这就是典型的时间换空间。 2.3、quicklist链表 官网介绍: A doubly linked list of ziplists A…
2025-05-10 阅读全文 →
FWQ
服务器教程
面试Redis的数据类型,我答了8种
面试Redis的数据类型,我答了8种 收藏 知识点掌握了,还需要不断练习才能熟练运用。下面golang学习网给大家带来一个数据库开发实战,手把手教大家学习《面试Redis的数据类型,我答了8种》,在实现功能的过程中也带大家重新温习相关知识点,温故而知新,回头看看说不定又有不一样的感悟! 面试官:小明呀,redis 有几种数据结构呀? 小明:8 种 面试官:那你说一下分别是什么? 小明:raw,int,ht,zipmap,linkedlist,ziplist,intset,skiplist,embstr 面试官:额,你在说什么? 小明:在回答你的问题呀,这个问题我可是有过研究的,不会错的 面试官:好吧,今天的面试先到这里,你回去等通知吧 小明:… 上面发生的对话,到底是面试官有问题,还是小明有问题呢?其实是都有问题的,面试官的提问不准确,小明的回答也不准确。 但可以看出,面试官的水平一般,因为听到这些名词并不知道小明说的是 redis 底层的编码类型,进而错失了深入挖掘小明技术潜力的机会。而小明也有些自作聪明,忽略了面试官想考察的知识点,把自己最近看的一些皮毛拿出来秀了秀,结果导致了一场误会。 就着上面这个引子,我们本篇文章就来聊聊,redis 中的数据结构那些事。 redis 源码选取的版本:3.0.0 本篇文章的目标:知道 redis 的编码类型这个概念,并按照源码级的深度去理解为什么要设置不同的编码类型,但不会过多展开各种底层数据结构的细节 redis 的对象类型与编码类型 redis 的对象类型,就是面试中常考的…
2025-05-10 阅读全文 →
FWQ
服务器教程
Redis的主从同步与读写分离机制
Redis的主从同步与读写分离机制 对于一个数据库开发者来说,牢固扎实的基础是十分重要的,golang学习网就来带大家一点点的掌握基础知识点。今天本篇文章带大家了解《Redis的主从同步与读写分离机制》,主要介绍了,希望对大家的知识积累有所帮助,快点收藏起来吧,否则需要时就找不到了! Redis作为一款高性能的内存数据库,在日常应用中会面临着高并发的场景。为了应对这些需求,Redis提供了主从同步与读写分离的两种机制,以提高Redis的性能和可用性。本文将详细介绍Redis的主从同步与读写分离原理与实现方式。 一、Redis的主从同步机制 Redis的主从同步机制可以将数据从一个Redis服务器同步到另一个Redis服务器,以实现数据备份、负载均衡、故障容错等需求。其中,一个Redis服务器是主节点,其它Redis服务器则是从节点,从节点会自动复制主节点的数据,并保持与主节点同步。 1.1 主节点的配置 在Redis中,如果需要将一个Redis服务器配置为主节点,需要在Redis的配置文件中增加如下配置: # 将当前节点配置为主节点 slaveof no one 添加该配置之后,Redis服务器将不再作为从节点,而成为一台独立的Redis主节点。 1.2 从节点的配置 从Redis 2.8版本开始,Redis已经内置了主从同步机制。当从节点需要与主节点建立同步连接时,仅需在Redis配置文件中增加如下配置即可: # 将当前节点配置为从节点,master_host为主节点IP地址,master_port为端口号 slaveof master_host master_port 上述配置中,master_host为主节点IP地址,master_port为主节点的端口号,从节点完成配置后,即可自动从主节点同步数据。 1.3 Redis主从同步的实现原理 在Redis主从同步的机制中,主节点将复制的数据发送给从节点,从而保持从节点与主节点的数据一致性。通常,Redis的主从同步的工作流程如下: 主节点将新的数据写入Redis数据库中,并将更新发送给从节点。…
2025-05-10 阅读全文 →
FWQ
服务器教程
Redis作为流式数据处理平台的实时计算能力对比
Redis作为流式数据处理平台的实时计算能力对比 在数据库实战开发的过程中,我们经常会遇到一些这样那样的问题,然后要卡好半天,等问题解决了才发现原来一些细节知识点还是没有掌握好。今天golang学习网就整理分享《Redis作为流式数据处理平台的实时计算能力对比》,聊聊,希望可以帮助到正在努力赚钱的你。 在当今的大数据时代,数据处理已成为各大企业和应用必备的重要环节。而在海量数据时代,如何才能更加高效地处理数据,成为所有企业和应用的共同难题。而流式数据处理在解决实时性强、数据量大的数据处理问题上发挥着重要作用。Redis作为流式数据处理平台之一,其实时计算能力备受关注。本文将与大家分享Redis作为流式数据处理平台实时计算能力的对比。 一、 Kafka Kafka是一个分布式流式数据平台,其本身提供了高效、可靠、可扩展的消息传递机制。Kafka通过将数据分布在不同的节点上实现水平扩展,具有很强的容错性与弹性,能够支持海量数据的处理。其中,Kafka提供的流数据处理平台可以高速地接收、处理和转发实时数据流,且拥有强大的容错能力。Kafka的实时计算能力可以通过应用其内置的Stream API来实现。 Kafka的实时计算性能与处理能力是非常出色的。其通过数据的存储和消费分别采用不同的方式,其中数据存储可采用Kafka自带的消息存储机制,而数据消费则可通过自定义ConsumerGroup来实现。基于以上特点,Kafka的实时计算能力非常高,能够在实时的情况下对数据进行复杂的计算。 二、Flink Flink是一个由Apache软件基金会孵化的分布式流处理框架,可实现低延迟、高吞吐量的流处理。Flink采用自行开发的分布式数据流处理引擎,能够在不降低数据处理速度的情况下增强数据处理的准确性。 Flink的实时计算能力成果十分显著。其通过采用独特的“连续数据流”处理方式,避免了对数据进行缓存的需求,从而保证了数据的实时性和准确性。同时,Flink采用了动态负载均衡及容错技术,在网络抖动、断电等灾难性情况下,能够实现数据的可靠性和即处理性。Flink的流式处理性能和实时计算能力分别是非常强的。 三、 Redis Redis是一种内存键值存储数据库,其具有高速读取、写入、删除和更新数据的能力。Redis采用数据在内存中的运行,对于读取、更新和写入数据速度非常快,支持典型用例的高并发访问。同时,Redis也具备大数据流式处理能力,在流数据处理方面多方面都有重要的应用。 Redis的流式数据处理在实现上采用订阅/发布模式,在流式数据的生产者和消费者之间进行消息传递。Redis提供的消息队列(Queue)可以支持海量数据集的高效读取、消费和处理,以满足数据实时性访问的需求。同时,Redis还支持复杂数据结构的处理和存储,为特定业务场景下的数据处理需求提供了多样化的选择。 四、对比与结论 综上所述,Redis的流式数据处理能力具备很强的实时性和高速度,但其与Kafka和Flink相比,在流式处理框架和组件丰富度上存在一定差距,不如Kafka和Flink那样完美。而相对于Kafka和Flink所需要的存储、计算资源更为庞大,在实际应用过程中需要慎重考虑。 总体来说,对于数据处理性能要求较高,且需要进行特定业务场景的复杂数据处理操作,Redis可以作为一个很好的流式数据处理平台被采用;而对于需要在流式处理框架和组件丰富度上更为丰富的项目,可以考虑选择Flink或Kafka等其他的流式数据处理平台。 基于Go语言的智能酒店控制系统设计与实现 使用Go语言编写高效的实时数据分析程序
2025-05-10 阅读全文 →
FWQ
服务器教程
详解缓存穿透击穿雪崩解决方案
详解缓存穿透击穿雪崩解决方案 收藏 在数据库实战开发的过程中,我们经常会遇到一些这样那样的问题,然后要卡好半天,等问题解决了才发现原来一些细节知识点还是没有掌握好。今天golang学习网就整理分享《详解缓存穿透击穿雪崩解决方案》,聊聊redis缓存、穿透、击穿、雪崩,希望可以帮助到正在努力赚钱的你。 一:前言 设计一个缓存系统,不得不要考虑的问题就是:缓存穿透、缓存击穿与失效时的雪崩效应。 二:缓存穿透 缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。在流量大时,可能DB就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。 三:解决方案 有很多种方法可以有效地解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。另外也有一个更为简单粗暴的方法(我们采用的就是这种),如果一个查询返回的数据为空(不管是数 据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。 四:缓存雪崩 缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。 五:解决方案 缓存失效时的雪崩效应对底层系统的冲击非常可怕。大多数系统设计者考虑用加锁或者队列的方式保证缓存的单线 程(进程)写,从而避免失效时大量的并发请求落到底层存储系统上。这里分享一个简单方案就时讲缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。 六:缓存击穿 对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据。这个时候,需要考虑一个问题:缓存被“击穿”的问题,这个和缓存雪崩的区别在于这里针对某一key缓存,前者则是很多key。 缓存在某个时间点过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。 七:解决方案 1、使用互斥锁(mutex key) 业界比较常用的做法,是使用mutex。简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。 SETNX,是「SET if…
2025-05-10 阅读全文 →
FWQ
服务器教程
如何使用Redis进行Python开发
如何使用Redis进行Python开发 在IT行业这个发展更新速度很快的行业,只有不停止的学习,才不会被行业所淘汰。如果你是数据库学习者,那么本文《如何使用Redis进行Python开发》就很适合你!本篇内容主要包括##content_title##,希望对大家的知识积累有所帮助,助力实战开发! 如何使用Redis进行Python开发 Redis是一款开源的内存数据存储系统,被广泛应用于缓存、消息队列、实时排行榜、计数器等场景。它支持多种数据结构,如字符串、列表、哈希表、集合和有序集合,具有快速、高效的特点。本文将介绍如何在Python开发中使用Redis,并提供一些代码示例。 安装Redis和Redis-Py 首先,需要安装Redis和Redis-Py库。Redis可以从官方网站(https://redis.io)下载并按照相关文档进行安装。而Redis-Py是Redis官方推荐的Python客户端库,可以通过pip安装: pip install redis 连接Redis 在开始使用Redis之前,首先需要与Redis建立连接。可以使用Redis-Py提供的Redis类来实现连接: import redis r = redis.Redis(host='localhost', port=6379, db=0) 上述代码中,我们通过实例化Redis类创建了一个Redis对象r。host参数指定了Redis服务器的地址,port参数指定了Redis服务器的端口,默认为6379。db参数指定了要使用的数据库,默认为0。 使用字符串 Redis可以存储和操作字符串。下面是一些常用的字符串操作示例: # 设置字符串键值对 r.set('name', 'Alice') # 获取字符串值 name…
2025-05-10 阅读全文 →
FWQ
服务器教程
dubbo服务使用redis注册中心的系列异常解决
dubbo服务使用redis注册中心的系列异常解决 收藏 对于一个数据库开发者来说,牢固扎实的基础是十分重要的,golang学习网就来带大家一点点的掌握基础知识点。今天本篇文章带大家了解《dubbo服务使用redis注册中心的系列异常解决》,主要介绍了异常、dubboredis,希望对大家的知识积累有所帮助,快点收藏起来吧,否则需要时就找不到了! 1.不支持带密码,设置indexdb的reids 2.5.6以及以前的会有这个问题,最新的版本已经解决了这个问题了,但是还是存在一个坑,就是必须得设置用户名(大家都知道redis验证不需要用户名),如URL的构造方法有如下判断 这会导致,如果只设置了密码,没有设置用户名,就会抛Invalid url, password without username的异常。 解决方法: 1.打开RedisRegistry.java,设置jedispool时判断下,如果设置密码,使用带密码,indexdb入参的构造方法,具体如下: if(StringUtils.isEmpty(url.getPassword())){ this.jedisPools.put(address, new JedisPool(config, host, port, url.getParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT),null,url.getParameter("db.index",0))); }else { this.jedisPools.put(address, new JedisPool(config, host, port, url.getParameter(Constants.TIMEOUT_KEY,…
2025-05-10 阅读全文 →
FWQ
服务器教程
深入理解跳表及其在Redis中的应用
深入理解跳表及其在Redis中的应用 收藏 本篇文章主要是结合我之前面试的各种经历和实战开发中遇到的问题解决经验整理的,希望这篇《深入理解跳表及其在Redis中的应用》对你有很大帮助!欢迎收藏,分享给更多的需要的朋友学习~ 前言 跳表可以达到和红黑树一样的时间复杂度 O(logN),且实现简单,Redis 中的有序集合对象的底层数据结构就使用了跳表。其作者威廉·普评价:跳跃链表是在很多应用中有可能替代平衡树的一种数据结构。本篇文章将对跳表的实现及在Redis中的应用进行学习。 一. 跳表的基础概念 跳表,即跳跃链表(Skip List),是基于并联的链表数据结构,操作效率可以达到O(logN),对并发友好,跳表的示意图如下所示。 跳表的特点,可以概括如下。 •跳表是多层(level)链表结构; •跳表中的每一层都是一个有序链表,并且按照元素升序(默认)排列; •跳表中的元素会在哪一层出现是随机决定的,但是只要元素出现在了第 k 层,那么 k 层以下的链表也会出现这个元素; •跳表的底层的链表包含所有元素; •跳表头节点和尾节点不存储元素,且头节点和尾节点的层数就是跳表的最大层数; •跳表中的节点包含两个指针,一个指针指向同层链表的后一节点,一个指针指向下层链表的同元素节点。 以上图中的跳表为例,如果要查找元素 71,那么查找流程如下图所示。 从顶层链表的头节点开始查找,查找到元素71的节点时,一共遍历了4个节点,但是如果按照传统链表的方式(即从跳表的底层链表的头节点开始向后查找),那么就需要遍历7个节点,所以跳表以空间换时间,缩短了操作跳表所需要花费的时间。跳跃列表的算法有同平衡树一样的渐进的预期时间边界,并且更简单、更快速和使用更少的空间。这种数据结构是由William Pugh(音译为威廉·普)发明的,最早出现于他在1990年发表的论文《Skip Lists: A…
2025-05-10 阅读全文 →