分类归档

服务器教程

服务器知识、操作系统教程、服务器常用软件等

FWQ
服务器教程
Redis如何实现分布式事务的可靠性
Redis如何实现分布式事务的可靠性 收藏 目前golang学习网上已经有很多关于数据库的文章了,自己在初次阅读这些文章中,也见识到了很多学习思路;那么本文《Redis如何实现分布式事务的可靠性》,也希望能帮助到大家,如果阅读完后真的对你学习数据库有帮助,欢迎动动手指,评论留言并分享~ Redis是一种快速、可靠的内存数据库,广泛应用于分布式系统中。在分布式系统中,事务的处理是一项关键的挑战。本文将介绍Redis是如何实现分布式事务的可靠性,并提供一些具体的代码示例。 Redis通过MULTI、EXEC、DISCARD和WATCH四个命令来实现分布式事务。MULTI命令用于开启一个事务,EXEC命令用于执行事务中的所有命令,DISCARD命令用于取消当前事务,而WATCH命令用于监视一个或多个键,如果在事务执行期间所监视的键被修改,则事务被取消。 下面是一个简单的示例,展示了如何使用Redis进行分布式事务处理的代码: import redis def transfer_money(from_account, to_account, amount): # 连接到Redis服务器 r = redis.StrictRedis(host='localhost', port=6379, db=0) # 开启事务 pipe = r.pipeline() try: # 监视from_account和to_account两个键 pipe.watch(from_account,…
2024-12-01 阅读全文 →
FWQ
服务器教程
Redis中统计各种数据大小的方法
Redis中统计各种数据大小的方法 0浏览 收藏 在数据库实战开发的过程中,我们经常会遇到一些这样那样的问题,然后要卡好半天,等问题解决了才发现原来一些细节知识点还是没有掌握好。今天golang学习网就整理分享《Redis中统计各种数据大小的方法》,聊聊Redis统计、数据大小,希望可以帮助到正在努力赚钱的你。 如果 MySQL 数据库比较大的话,我们很容易就能查出是哪些表占用的空间;不过如果 Redis 内存比较大的话,我们就不太容易查出是哪些(种)键占用的空间了。 有一些工具能够提供必要的帮助,比如 可以直接分析 RDB 文件来生成报告,可惜它不能百分百实现我的需求,而我也不想在它的基础上二次开发。实际上开发一个专用工具非常简单,利用 和 等命令,没多少行代码就能实现:: 代码如下: shell> /path/to/redis-cli monitor |        awk -F ‘”‘ ‘$2 ~ “ADD|SET|STORE|PUSH” {print…
2024-12-01 阅读全文 →
FWQ
服务器教程
Redis序列化转换类型报错的解决
Redis序列化转换类型报错的解决 0浏览 收藏 本篇文章主要是结合我之前面试的各种经历和实战开发中遇到的问题解决经验整理的,希望这篇《Redis序列化转换类型报错的解决》对你有很大帮助!欢迎收藏,分享给更多的需要的朋友学习~ Cannot convert value of type ‘org.springframework.data.redis.core.convert.MappingRedisConverter’ to required type ‘org.springframework.data.redis.core.mapping.RedisMappingContext’: no matching editors or conversion strategy found 在setValue的序列化方式的时候报错,原来是用的RedisSerializer.json()方法,但是报错, template.setConnectionFactory(factory); // key序列化方式 template.setKeySerializer(RedisSerializer.string()); // value序列化方式…
2024-12-01 阅读全文 →
FWQ
服务器教程
Redis分布式锁解决秒杀超卖问题
Redis分布式锁解决秒杀超卖问题 0浏览 收藏 本篇文章向大家介绍《Redis分布式锁解决秒杀超卖问题》,主要包括Redis秒杀超卖,具有一定的参考价值,需要的朋友可以参考一下。 分布式锁应用场景 秒杀环境下:订单服务从库存中心拿到库存数,如果库存总数大于0,则进行库存扣减,并创建订单订单服务负责创建订单库存服务负责扣减库存 模拟用户访问库存 多线程并发访问,出现超卖问题,线程不安全。没有保证原子性 单体锁的分类 单体应用锁指的是只能在 一个JVM 进程内有效的锁。我们把这种锁叫做单体应用锁 synchronized锁ReentrantLock锁一个 Tomcat 可以看作是一个JVM进程,当大量请求并发到系统时,所有的请求都落在这唯一的一个Tomcat上,如果某些请求方法是需要加锁的,比如:秒杀扣减库存,是可以满足需求的,但是随着访问量的增加,导致一个tomcat 难以支撑,这时我们必然就是集群部署Tomcat ,使用多个 Tomcat 共同支撑整个系统。 我们看到系统中存在两个Tomcat,我们加的锁是JDK提供的锁,这种锁只能在 一个JVM 下起到作用,也就是在一个Tomcat内是没有问题的。当存在两个或两个以上的Tomcat时,大量的并发请求分散到不同的Tomcat上,在每一个Tomcat中都可以防止并发的产生,但是在多个Tomcat之间,每个Tomcat中获得锁的这个请求,又产生了并发,从而产生超卖现象。这也就是单体应用锁的局限性了,它只能在一个JVM内加锁,所以单体锁只能锁住单体环境,是锁不住分布式环境或集群环境的。 分布式锁核心逻辑 分布式锁的核心逻辑就是在多个服务中设置一个公共的资源,在公共资源中设置锁,供多个服务去同时抢夺锁资源,一旦其中一个线程抢夺成功,其他线程就进入自旋状态,不同的尝试访问获取锁资源,在获取锁资源的线程执行完相应的逻辑以后就会释放锁资源,其他线程就可以获取锁资源。 分布式锁实现的问题——死锁和解决 死锁:如果某个线程在执行锁逻辑过程中宕机,导致没有删除锁解决: 添加过期时间 因为是非原子性添加过期时间,可能导致在添加过期时间之前就出现宕机现象,此时依旧进入死锁状态。原子性添加过期时间…
2024-12-01 阅读全文 →
FWQ
服务器教程
基于Spring Cache如何实现Caffeine+Redis二级缓存
基于Spring Cache如何实现Caffeine+Redis二级缓存 0浏览 收藏 一分耕耘,一分收获!既然打开了这篇文章《基于Spring Cache如何实现Caffeine+Redis二级缓存》,就坚持看下去吧!文中内容包含等等知识点…希望你能在阅读本文后,能真真实实学到知识或者帮你解决心中的疑惑,也欢迎大佬或者新人朋友们多留言评论,多给建议!谢谢! 具体如下: 一、聊聊什么是硬编码使用缓存? 在学习Spring Cache之前,笔者经常会硬编码的方式使用缓存。 我们来举个实际中的例子,为了提升用户信息的查询效率,我们对用户信息使用了缓存,示例代码如下:     @Autowire     private UserMapper userMapper;     @Autowire     private RedisCache redisCache;     //查询用户     public User getUserById(Long userId) {         //定义缓存key         String cacheKey = "userId_" + userId;         //先查询redis缓存         User user = redisCache.get(cacheKey);         //如果缓存中有就直接返回,不再查询数据库         if (user != null) {             return user;         }         //没有再查询数据库         user = userMapper.getUserById(userId);         //数据存入缓存,这样下次查询就能到缓存中获取         if (user != null) {             stringCommand.set(cacheKey, user);…
2024-12-01 阅读全文 →
FWQ
服务器教程
Redis在容器化部署中的应用实践
Redis在容器化部署中的应用实践 收藏 大家好,今天本人给大家带来文章《Redis在容器化部署中的应用实践》,文中内容主要涉及到,如果你对数据库方面的知识点感兴趣,那就请各位朋友继续看下去吧~希望能真正帮到你们,谢谢! Redis是目前应用广泛、性能卓越的内存数据存储系统。随着容器化部署的不断普及,如何将Redis运用于容器化部署成为了许多企业和开发者所关心的热门话题。本文将重点探讨Redis在容器化部署中的应用实践。 一、Redis与容器化部署的结合 Redis的快速响应和高并发能力,使得它成为了众多网站和应用程序中存储和缓存数据的领先选择。然而,对于传统的Redis部署方式,可能会存在以下缺点: 部署难度大。传统Redis需要在服务器上提前准备好环境,并安装相关组件等,过程较为繁琐。 数据备份和恢复难度大。传统Redis需要手动备份数据,如果数据量较大,备份和恢复操作会比较耗时。 资源利用率低。传统Redis的资源利用率可能不够高效,没有充分发挥云计算的优势。 而正是这些缺点,使得Redis和容器化部署结合变得极其有价值。容器化部署可以将Redis应用程式打包成一个独立的容器,将Redis及其相关应用和组件打包在一起,通过容器编排工具实现快速部署、数据备份和恢复等功能。 二、Redis容器化部署的流程 Redis在容器化部署中的流程简单明了,其中包括以下几个步骤: 编写Dockerfile文件。Dockerfile中定义了Redis容器的配置和组件信息,可以指定Redis版本、端口和数据挂载路径等。 使用Docker Compose编排容器。Docker Compose是一个用于多容器应用程序定义和运行的工具,通过YAML文件描述服务之间的依赖关系和简单的配置。 启动Redis容器。通过docker-compose up命令启动Redis容器。 对Redis进行访问测试。使用Redis命令行或客户端访问Redis容器,测试Redis是否正确被部署。 实现数据备份和恢复功能。通过将Redis数据文件挂载到宿主机器上,可以实现对Redis数据的备份和恢复操作,确保数据的安全性。 三、Redis容器化部署的优势 Redis容器化部署有许多显著的优势: 方便部署。Redis容器化部署,可以直接通过Docker Compose命令快速实现部署,大大节约了部署时间和成本。 数据备份和恢复方便。Redis容器化部署,可以将Redis数据文件挂载到宿主机器上,方便进行数据备份和恢复操作,提高了数据的安全性和可靠性。 满足高可用性需求。通过在不同的容器上部署Redis,可以增加Redis的可用性,防止单点故障和数据丢失。 支持集群和性能优化。Redis容器化部署支持集群模式,可以通过增加实例数实现Redis的水平扩展,在高并发环境下提高性能。 四、Redis容器化部署所需注意的问题…
2024-12-01 阅读全文 →
FWQ
服务器教程
Redis链表底层实现及生产实战
Redis链表底层实现及生产实战 0浏览 收藏 哈喽!今天心血来潮给大家带来了《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…
2024-12-01 阅读全文 →
FWQ
服务器教程
redis禁止几个危险命令的方法
redis禁止几个危险命令的方法 0浏览 收藏 IT行业相对于一般传统行业,发展更新速度更快,一旦停止了学习,很快就会被行业所淘汰。所以我们需要踏踏实实的不断学习,精进自己的技术,尤其是初学者。今天golang学习网给大家整理了《redis禁止几个危险命令的方法》,聊聊禁止、redis危险命令,我们一起来看看吧! 这几天客户一直给我反映一个问题,那就是他的缓存服务器redis每天会清理库,很纳闷,我配置的redis一般保持的默认,不应该会每天去清理库的,感觉应该还是他的程序上有点问题吧。 不过,不管程序问题还是配置问题,我想到就是可以吧清库的命令禁掉,这样即使他程序要去清理也是没办法的,于是就百度了一下,看到所有相关的文档都是一个人写的,就是在redis.conf中使用rename-conmand rename-command FLUSHALL "" rename-command FLUSHDB "" rename-command KEYS "" 完了,之后我就去重启redis,以为OK了,仔细看了redis的日志,发现有问题。 Unknown command ‘flushall‘ reading the append only file 这是啥问题,直接百度,根本没有这个问题的解答,仔细看append only这个,感觉在哪见过,于是到redis.conf文件中找,果然在里面,又到官网看了这个参数的意思。 ############################## APPEND…
2024-12-01 阅读全文 →
FWQ
服务器教程
Redis数组和链表深入详解
Redis数组和链表深入详解 0浏览 收藏 本篇文章给大家分享《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…
2024-12-01 阅读全文 →
FWQ
服务器教程
如何利用Redis和C++开发发布-订阅功能
如何利用Redis和C++开发发布-订阅功能 收藏 今天golang学习网给大家带来了《如何利用Redis和C++开发发布-订阅功能》,其中涉及到的知识点包括等等,无论你是小白还是老手,都适合看一看哦~有好的建议也欢迎大家在评论留言,若是看完有所收获,也希望大家能多多点赞支持呀!一起加油学习~ 如何利用Redis和C++开发发布-订阅功能 在开发大规模实时系统时,发布-订阅模式被广泛应用于消息传递和事件驱动机制中。Redis是一个高性能的键值存储系统,通过其提供的发布-订阅功能,可以方便地实现实时通信和数据传递。本文将介绍如何利用Redis和C++开发发布-订阅功能,并提供具体的代码示例。 Redis的发布-订阅模式概述Redis的发布-订阅模式是一种基于消息传递的模式,它可以实现多个订阅者同时接收到相同的消息。在该模式中,发布者负责发送消息,而订阅者则通过订阅频道来接收消息。 Redis发布-订阅功能的实现要使用Redis的发布-订阅功能,首先需要安装和配置Redis服务器。然后,在C++代码中使用Redis的C++客户端库进行操作。 以下是一个基本的示例,演示了如何使用Redis C++客户端库实现发布-订阅功能。 #include <iostream> #include <string> #include <thread> #include <hiredis/hiredis.h> void subscribeThread() { // 创建Redis上下文 redisContext* context = redisConnect("127.0.0.1", 6379); if…
2024-12-01 阅读全文 →