Redis入门与实践

《Redis源码解析系列》系列技术文章整理收藏   《Redis源码解析系列》系列分享专栏 《Redis源码解析系列》已整理成PDF文档,点击可直接下载至本地查阅https://www.webfalse.com/read/207138.html 简介 Redis源码解析系列 文章 Redis源码解析:12AOF持久化 Redis源码解析:13Redis中的事件驱动机制 Redis源码解析:14Redis服务器与客户端间的交互 ... 阅读详情

今天继续更新austin项目,如果还没看过该系列的同学可以点开我的历史文章回顾下,在看的过程中不要忘记了点赞哟!建议不要漏了或者跳着看,不然这篇就看不懂了,之前写过的知识点和业务我就不再赘述啦。

今天要实现的是handler消费消息后,实现平台性去重的功能。

01、什么是去重和幂等

这个话题我之前在《对线面试官》系列就已经分享过了,这块面试也会经常问到,可以再跟大家一起复习下

「幂等」和「去重」的本质:「唯一Key」+「存储」

唯一Key如何构建以及选择用什么存储,都是业务决定的。「本地缓存」如果业务合适,可以作为「前置」筛选出一部分,把其他存储作为「后置」,用这种模式来提高性能。

今日要聊的Redis,它拥有着高性能读写,前置筛选和后置判断均可,austin项目的去重功能就是依赖着Redis而实现的。

02、安装Redis

先快速过一遍Redis的使用姿势吧(如果对此不感兴趣的可以直接跳到05讲解相关的业务和代码设计)

安装Redis的环境跟上次Kafka是一样的,为了方便我就继续用docker-compose的方式来进行啦。

环境:CentOS 7.6 64bit

首先,我们新建一个文件夹redis,然后在该目录下创建出data文件夹、redis.conf文件和docker-compose.yaml文件

redis.conf文件的内容如下(后面的配置可在这更改,比如requirepass 我指定的密码为austin)

protected-mode no
port 6379
timeout 0
save 900 1 
save 300 10
save 60 10000
rdbcompression yes
dbfilename dump.rdb
dir /data
appendonly yes
appendfsync everysec
requirepass austin

docker-compose.yaml的文件内容如下:

version: '3'
services:
  redis:
    image: redis:latest
    container_name: redis
    restart: always
    ports:
      - 6379:6379
    volumes:
      - ./redis.conf:/usr/local/etc/redis/redis.conf:rw
      - ./data:/data:rw
    command:
      /bin/bash -c "redis-server /usr/local/etc/redis/redis.conf "

配置的工作就完了,如果是云服务器,记得开redis端口6379

03、启动Redis

启动Redis跟之前安装Kafka的时候就差不多啦

docker-compose up -d

docker ps

docker exec -it redis redis-cli

进入redis客户端了之后,我们想看验证下是否正常。(在正式输入命令之前,我们需要通过密码校验,在配置文件下配置的密码是austin)

然后随意看看命令是不是正常就OK啦

04、Java中使用Redis

在SpringBoot环境下,使用Redis就非常简单了(再次体现出使用SpringBoot的好处)。我们只需要在pom文件下引入对应的依赖,并且在配置文件下配置host/port和password就搞掂了。

对于客户端,我们就直接使用RedisTemplate就好了,它是对客户端的高度封装,已经挺好使的了。

05、去重功能业务

任何的功能代码实现都离不开业务场景,在聊代码实现之前,先聊业务!平时在做需求的时候,我也一直信奉着:先搞懂业务要做什么,再实现功能。

去重该功能在austin项目里我是把它定位是:平台性功能。要理解这点很重要!不要想着把业务的各种的去重逻辑都在平台上做,这是不合理的。

这里只能是把共性的去重功能给做掉,跟业务强挂钩应由业务方自行实现。所以,我目前在这里实现的是:

  • 5分钟内相同用户如果收到相同的内容,则应该被过滤掉。实现理由:很有可能由于MQ重复消费又或是业务方不谨慎调用,导致相同的消息在短时间内被austin消费,进而发送给用户。有了该去重,我们可以在一定程度下减少事故的发生。
  • 一天内相同的用户如果已经收到某渠道内容5次,则应该被过滤掉。实现理由:在运营或者业务推送下,有可能某些用户在一天内会多次收到推送消息。避免对用户带来过多的打扰,从总体定下规则一天内用户只能收到N条消息。

不排除随着业务的发展,还有些需要我们去做的去重功能,但还是要记住,我们这里不跟业务强挂钩。

当我们的核心功能依赖其他中间件的时候,我们尽可能避免由于中间件的异常导致我们核心的功能无法正常使用。比如,redis如果挂了,也不应该影响我们正常消息的下发,它只能影响到去重的功能。

06、去重功能代码总览

在之前,我们已经从Kafka拉取消息后,然后把消息放到各自的线程池进行处理了,去重的功能我们只需要在发送之前就好了。

我将去重的逻辑统一抽象为:在X时间段内达到了Y阈值。去重实现的步骤可以简单分为:

  • 从Redis获取记录
  • 判断Redis存在的记录是否符合条件
  • 符合条件的则去重,不符合条件的则重新塞进Redis

这里我使用的是模板方法模式,deduplication方法已经定义好了定位,当有新的去重逻辑需要接入的时候,只需要继承AbstractDeduplicationService来实现deduplicationSingleKey方法即可。

比如,我以相同内容发送给同一个用户的去重逻辑为例:

07、去重代码具体实现

在这场景下,我使用Redis都是用批量操作来减少请求Redis的次数的,这对于我们这种业务场景(在消费的时候需要大量请求Redis,使用批量操作提升还是很大的)

由于我觉得使用的场景还是蛮多的,所以我封装了个RedisUtils工具类,并且可以发现的是:我对操作Redis的地方都用try catch来包住。即便是Redis出了故障,我的核心业务也不会受到影响。

08、你的代码有Bug!

不知道看完上面的代码你们有没有看出问题,有喜欢点赞的帅逼就很直接看出两个问题:

  • 你的去重功能为什么是在发送消息之前就做了?万一你发送消息失败了怎么办?
  • 你的去重功能存在并发的问题吧?假设我有两条一样的消息,消费的线程有多个,然后该两条线程同时查询Redis,发现都不在Redis内,那这不就有并发的问题吗

没错,上面这两个问题都是存在的。但是,我这边都不会去解决。

先来看第一个问题:

对于这个问题,我能扯出的理由有两个:

  • 假设我发送消息失败了,在该系统也不会通过回溯MQ的方式去重新发送消息(回溯MQ重新消费影响太大了)。我们完全可以把发送失败的userId给记录下来(后面会把相关的日志系统给完善),有了userId以后,我们手动批量重新发就好了。这里手动也不需要业务方调用接口,直接通过类似excel的方式导入就好了。

  • 在业务上,很多发送消息的场景即便真的丢了几条数据,都不会被发现。有的消息很重要,但有更多的消息并没那么重要,并且我们即便在调用接口才把数据写入Redis,但很多渠道的消息其实在调用接口后,也不知道是否真正发送到用户上了。

再来看第二个问题:

如果我们要仅靠Redis来实现去重的功能,想要完全没有并发的问题,那得上lua脚本,但上lua脚本是需要成本的。去重的实现需要依赖两个操作:查询和插入。查询后如果没有,则需要添加。那查询和插入需要保持原子性才能避免并发的问题

再把视角拉回到我们为什么要实现去重功能:

当存在事故的时候,我们去重能一定保障到绝大多数的消息不会重复下发。对于整体性的规则,并发消息发送而导致规则被破坏的概率是非常的低。

09、总结

这篇文章简要讲述了Redis的安装以及在SpringBoot中如何使用Redis,主要说明了为什么要实现去重的功能以及代码的设计和功能的具体实现。

技术是离不开业务的,有可能我们设计或实现的代码对于强一致性是有疏漏的,但如果系统的整体是更简单和高效,且业务可接受的时候,这不是不可以的。

这是一种trade-off权衡,要保证数据不丢失和不重复一般情况是需要编写更多的代码和损耗系统性能等才能换来的。我可以在消费消息的时候实现at least once语义,保证数据不丢失。我可以在消费消息的时候,实现真正的幂等,下游调用的时候不会重复。

但这些都是有条件的,要实现at least once语义,需要手动ack。要实现幂等,需要用redis lua或者把记录写入MySQL构建唯一key并把该key设置唯一索引。在订单类的场景是必须的,但在一个核心发消息的系统里,可能并没那么重要。

原文地址:https://www.cnblogs.com/Java3y/p/15921480.html 

Redis基础与实践:入门到高级应用 在现代IT架构中,数据库的选择对于系统的性能和可扩展性至关重要。数据库根据数据模型可以分为关系型数据库和非关系型数据库。关系型数据库如MySQL、PostgreSQL,擅长处理复杂的查询和事务,非关系型数据库如Redis、MongoDB,更注重高可用性和水平扩展性。在选择数据库时,应考虑应用场景、数据结构复杂度、读写频率以及成本等因素。 阅读详情

相关推荐

Redis超级简单入门代码,绝对能快速上手。

绝对超级简单的入门级代码。你看一眼马上就能秒懂的Demo。

Redis入门与实践(附源码)

今天继续更新austin项目,如果还没看过该系列的同学可以点开我的历史文章回顾下,在看的过程中不要忘记了点赞哟!建议不要漏了或者跳着看,不然这篇就看不懂了,之前写过的知识点和业务我就不再赘述啦。编程学习资料点击免费领取 今天要实现的是handler消费消息后,实现平台性去重的功能。 01、什么是去重和幂等 这个话题我之前在《对线面试官》系列就已经分享过了,这块面试也会经常问到,可以再跟大家一起复习下 「幂等」和「去重」的本质:「唯一Key」+「存储」 唯一Key如何构建以及选择用...

m0_63171455的博客 1188

Redis源代码分析.pdf

Redis源代码分析.pdf

Redis基础-快速入门|基本数据类型指令

【代码】Redis基础-快速入门|基本数据类型指令

u011005040的博客 213

Allegro模块复用:从原理图到PCB的完整流程与关键细节

本文详细介绍了Allegro模块复用从原理图到PCB的完整流程与关键细节,包括DSN和MDD文件的创建、模块调用的实战技巧以及双向同步与版本控制方法。通过标准化处理和高级复用技巧,能显著提升PCB设计效率,减少重复工作时间。适用于智能硬件和工业控制等领域的工程师。

weixin_30252709的博客 332

SAP公司间采购后台配置及前台操作详解

公司间采购后台配置及前台操作详解 SAP 实施中公司间交易几乎每个项目都会有此业务需求,比如内地很多公司都会在香港设置贸易型子公司。通过香港公司接单,然后转内地公司生产,或内地公司通过香港公司采购进口原材料,这些业务必然会涉及到公司间交易,下面我将详细说明下SAP是如何实现这种业务场景的,供大家参考。 配置前必须前台先创建公司间供应商主数据和客户主数据 1. 创建相应的客户主数据 功能说明 公司间...

weixin_40672823的博客 1万+

《Docker技术入门与实战》电子书pdf下载

《Docker技术入门与实战》 http://pan.baidu.com/s/1kTxgrzx 更多运维学习资料 http://dou.bz/35ODPo

swifttrain的专栏 1万+

数据结构实验1 集合的交、并、差

姓名:Far_Rainbow 学号: 202505000X 专业: 软件工程 年级:2020级 实验名称:实验1 集合的交、并、差 实验内容: (1)实验目的 通过该实验,让学生复习巩固C语言中的循环结构、循环控制条件、分支结构和数组/链表、函数的调用等有关内容,体会到用数组存储集合时,需要记录集合元素的个数,否则输出结果会出现数据越界现象。 (2)实验内容 通过键盘,分别输入两个数据元素类型为正整数的集合A和B,以负数输入为结束条件,输出两个集合的交、并、差。 (3)实验要求 从程序完善性上考虑,集合元

Far_Rainbow的博客 2176

Redis 基础入门与实践指南

本文梳理 Redis 的发展历史、Ubuntu 环境下的多种安装方式、核心文件职责、redis-cli 基本使用及 典型应用场景,帮助初学者快速建立 Redis 全局认知。

2401_88513741的博客 247

相机通用类之海康相机,软触发硬触发(飞拍),并输出halcon格式对象

如何显示图像:可以访问我文章开头的博客,通过编写相机通用类即可,程序中是有继承通用类,通过访问相机通用的获取图像数据,从而传输图像数据。具体可以查看相机通用类。整体过程其实比较简单,由于海康相机没有像一些品牌相机一样可以直接使用序列号开启相机,所以我们需要通过对相机信息进行索引,根据索引到的相机序列号来开启相机。

m0_51559565的博客 7619

MQTT与物联网平台(一):基础知识和设备接入物联网平台的实现(以华为云为例)

本文简单介绍了MQTT的基础知识和使用方法,以蓝牙WIFI双模芯片W801作为硬件设备,接入到华为云。

weixin_50622833的博客 1万+

Redis 入门与实践

Redis是一个高性能的内存键值数据库,支持多种数据结构(字符串、哈希、列表等)和持久化(RDB/AOF)。与SQL相比,Redis采用简洁的命令操作,如SET/GET/DEL等。它常与PostgreSQL等数据库配合使用,用Redis存储会话状态,持久化数据库存储核心数据。Redis还支持事务、发布订阅、消息流(Streams)和集群功能,适用于高并发、分布式场景。通过内存存储和丰富特性,Redis在缓存、会话管理和消息队列等场景中表现优异。

分享前端工程化、AI 应用、Agent 开发与大模型实践! 1094

无人驾驶之车辆控制(1)纯跟踪(Pure Pursuit)算法与Stanley算法

目录引言1 Pure Pursuit纯几何跟踪算法1.1 车辆运动学自行车模型1.2 算法原理1.3 仿真测试2 Stanley算法2.1 算法原理2.2 仿真测试3 总结 引言 本文对Pure Pursuit以及Stanley control两种算法进行了调研以及初步的性能摸底。 1 Pure Pursuit纯几何跟踪算法 1.1 车辆运动学自行车模型 运动学是从几何学的角度研究物体的运动规律,...

zxxxxxxy的博客 2万+

Redis 从入门到实践:Python操作指南与核心概念解析

Redis是一款高性能内存键值数据库,支持字符串、哈希、列表、集合等数据结构,适用于缓存、消息队列等场景。文章介绍了Redis的安装配置、键管理、五大数据类型(String/Hash/List/Set/SortedSet)及其典型应用,如计数器、分布式锁、排行榜等。重点讲解了缓存雪崩/穿透/击穿问题的解决方案,以及主从复制配置。最后总结了使用规范:合理设置过期时间、使用批量操作、避免大Key、连接池优化等。通过"字符串最简单,哈希存对象;列表做队列,集合保唯一"等口诀帮助记忆核心知识点。

m0_73938881的博客 416

ORCA(动态避障)算法

A物体沿着向量v1和v2移动,刚好能和B擦肩而过,不会发生碰撞;若V1和V2的夹角再小一点的话就一定会发生碰撞。A的速度为V1,B的速度为V2,A对于B的相对速度(也就是我们把B看做静止,A的速度)就是V1-V2。,那么怎么判定A的速度向量是不是在碰撞区域内呢?这就需要用A相对于B的速度来判定。红线画出来的锥形区域就是A相对于B的。

u012861978的专栏 4768

Python全栈入门到实战【基础篇 22】生成器与迭代器:底层逻辑与实战场景

Python迭代器与生成器:惰性求值的高效实践 摘要:本文深入解析Python中迭代器和生成器的核心机制与应用场景。迭代器通过实现__iter__()和__next__()方法实现惰性求值,适合处理大数据集和无限序列。生成器作为迭代器的简化实现,通过yield关键字自动实现迭代器协议,代码更简洁。文章详细对比了可迭代对象与迭代器的区别,演示了自定义迭代器和生成器函数的实现方式,并介绍了生成器表达式这一高效替代列表推导式的方案。通过斐波那契数列等实例,展示了惰性求值在内存优化方面的优势,以及生成器在流式数据处

那些看似不起波澜的日复一日,会在某天让你看到坚持的意义 3260

Redis技术入门与实践指南

【代码】Redis技术入门与实践指南。

m0_59344541的博客 1070

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Redis 基础入门与部署实践指南

Redis是一款开源的、高性能的键值对(Key-Value)NoSQL 数据库。Redis 凭借独特的技术特性,成为当前最主流的内存数据库之一,显著区别于传统 Key-Value 缓存产品核心优势体现在以下三方面:Redis 支持数据的持久化,可以将内存中的数据保存在磁盘中,当服务重启时,可以再次加载进行使用,保障了数据的可靠性,避免因服务重启导致数据全部丢失。

Myqianyin的博客 1272

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Redis入门与实践--Redis初识(一)

Redis 入门到实践 甚赞Redis 高性能Key-Value服务器 多中数据结构 丰富的功能 高可用分布式支持 Redis 目标 Redis 初始 API的理解和使用 Redis 客户端的使用 Redis 持久化的取舍和选择 Redis 复制的原理和优化 Rdeis Sentinel(高可用) Redis Cluster (分布式) 课程目标 全面了解Redis单机的相关功能 全面了...

Jason World 573

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Redis客户端Rueidis的入门与实践指南

Rueidis 是一个高度优化的 Redis 客户端库,专为追求高性能而设计。它基于 C# 开发,利用了.NET平台的优势,提供简洁的API来实现与Redis服务器的有效通信。Rueedis 强调速度与效率,同时保持对 Redis 协议的完整支持,非常适合用于构建高负载、低延迟的应用场景。 ## 项目快速启动 要快速开始使用 Rueedis,首先确保你的开发环境已经安装了 .NET 环境。接下

gitblog_01116的博客 628

Go-Redis 入门与实践从连接到可观测,一站式掌握 go-redis v9**

在 Go 生态中,**go-redis** 几乎是连接 Redis 的事实标准。本文将围绕 v9 版本,带你从零开始完成安装、连接、常见数据结构操作,并进一步介绍 OpenTelemetry 的接入方法与生产环境最佳实践。希望读完后,你不仅能“连上 Redis”,还能写出 **稳定、可观测且易于维护** 的业务代码。

hello.reader 1001

刘瑜《NoSQL数据库入门与实践 基于MongoDB、Redis》PDF下载

NoSQL数据库入门与实践 基于MongoDB、Redis 【作 者】刘瑜,刘胜松著 【形态项】 483 【出版项】 北京:中国水利水电出版社 , 2018.03 【ISBN号】978-7-5170-6084-0 【中图法分类号】TP311.138SQ 【原书定价】89.80 【主题词】数据库系统 【参考文献格式】 刘瑜,刘胜松著. NoSQL数据库入门与实践 基于MongoDB、Redis. 北...

weixin_44946306的博客 2755

Redis 入门与实践:从基础到 Stream 消息队列

Redis是一个高性能内存数据库,支持字符串、哈希、列表等数据结构。5.0版本新增Stream类型,提供消息队列功能,支持消费者组和消息确认。

weixin_48389642的博客 845
上一篇: 干了三年外包的普通程序员还能社招进阿里吗?
Java架构师小森
博客等级 码龄5年 23粉丝 32原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值