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

4.15redis点评项目下

--->接redis点评项目上

Redis优化秒杀方案

下单流程为:用户请求nginx--->访问tomcat--->查询优惠券--->判断秒杀库存是否足够--->查询订单--->校验是否是一人一单--->扣减库存--->创建订单

以上流程如果要串行执行耗时会很多,所以想要进行异步操作。

想法一:开启多线程,每一个线程处理一个步骤再做统一返回。

缺点:访问人很多的情况下,线程池的线程就会不够。

想法二:可以利用消息队列,先返回能确定完成事务1的信号,然后再直接进行判断事务能否完成.事务1和事务2可以等到所有判断结束后再慢慢进行。

总体思路:将耗时较短的(比如判断库存是否大于0(是的话判断用户是否可以下单)--->在set集合中查找用户是否已有下单记录保证一人一单(否的话将userId和优惠卷存入到redis中,并且返回0))判断逻辑放入redis中,然后及时返回结果给前端,之后判断当前redis返回结果是否为0(是的话表示可以下单)--->把一些优惠劵,用户订单等信息存入异步queue(阻塞队列)中,交给tomcat处理其他的判断逻辑(利用独立线程异步下单)。

基于阻塞队列的异步秒杀存在问题有:内存限制;数据安全。

Redis消息队列

消息队列:存储和管理消息,也被称为消息代理(Message Broker)

最简单的消息队列模型:

生产者--->消息队列--->消费者

使用消息队列的好处是:解耦。

耦合:一个事务必须要等另一个事务空闲才能运行或者传递数据。

秒杀中的消息队列模型对应的是:redis校验下单条件--->消息队列(传递id信息)--->启动一个新线程完成下单。

有一些现成的消息队列如kafka,rabbitmq等,也有一些redis提供的mq方案。

Redis消息队列-基于List实现消息队列

Redis基于List的消息队列的常见指令:

LPUSH添加一个或多个元素插入到list的头部
LPOP从 list 中删除并返回第一个元素
RPUSH添加字符串元素到对应 list 的尾部
RPOP从list 的尾部删除元素,并返回删除元素
LLEN获取list的元素个数
LRANGE获取列表指定范围内的元素
LINDEX获取列表中指定位置的元素

但是当队列中没有消息时删除操作就会返回null,我们想要实现阻塞并等待消息的效果,就采用BRPOP(阻塞RPOP)或者BLPOP实现阻塞效果。

优点:基于Redis存储,不受限于JVM的内存上限;基于Redis的持久化机制,数据安全性有保证;可以满足消息有序性。

缺点:无法避免消息丢失;只支持单消费者。

小知识点:

Redis的持久化机制:为了保证突然宕机,内存数据不会全部丢失。

Redis提供了三种持久化机制:RDB、AOF和混合持久化。

RDB(Redis Database Snapshot)是通过创建内存数据的快照,将其保存到磁盘中。

AOF(Append Only File)通过记录每个写操作命令来实现持久化。每当执行一个会改变数据的命令时,Redis会将该命令写入AOF文件中。

混合持久化结合了RDB和AOF的优点。它首先以RDB格式保存当前数据状态,然后继续以AOF格式记录新的写操作。

Redis消息队列-基于PubSub的消息队列

消费者可以订阅一个或多个channel,生产者向对应channel发送消息后,所有订阅者都能收到相关消息。

SUBSCRIBE chan:订阅一个或多个频道。

PUBLISH chan msg:向一个频道发送信息。

PSUBSCRIBE pattern:订阅与pattern格式匹配的所有频道。

优点:采用发布订阅模式,支持多生产多消费。

缺点:不支持数据持久化;无法避免消息丢失;消息堆积有上限,超出时数据丢失。

Redis消息队列-基于Stream的消息队列

发送信息的命令:XADD

读取信息的方式之一:XREAD

XREAD特点:消息可回溯;一个消息可以被多个消费者读取;可以阻塞读取;有消息漏读的风险。

如何使用stream消息队列实现异步秒杀:

1.创建一个Stream类型的消息队列。

2.修改之前的秒杀Lua脚本,当用户拥有抢购资格之后(增加将用户id保存到队列id中,然后将优惠券,用户和队列id全部加到队列中)

3.开启一个新线程,获取消息队列中的订单信息,如果为空继续获取直到获取了信息开始解析数据,创建订单并确认信息;如果出现订单信息异常就重新获取、判断、解析、创建、确认信息。

消费者组?

达人探店功能

发布探店笔记

表主要有两部分:

探店笔记表:包含笔记中的标题、文字、图片等。

其他用户对该笔记的评价表。

查看探店笔记

点赞功能

基本要求:

一个用户只能点赞一次;

当用户已点赞,点赞按钮高亮显示;

当用户已点赞,再点一遍点赞按钮就实现取消点赞。

实现思路:采用一个set集合,当用户点赞时,就把用户id存入集合中,然后点赞数加一,如果用户取消点赞,就把用户id从该集合中移除,然后点赞数减一;下次再判断时,只需要判断set集合中有没有用户的id,就能判断该用户是否点赞过。

使用set集合的原因时:需要不重复的数据

点赞排行榜

之前用set是无法排序的,所以换成sortedset就可以实现。

然后只需要在已经排好序的sortset里找到id前五位就能实现点赞排行榜。

好友关注

关注和取消关注

创建一个关注表,粉丝为user_id;关注的博主为follow_user_id;

关注就新增数据,取关就从表中删除数据。

共同关注

实现思路:set集合中有交集并集补集的API,所以只需要把两个人关注的人分别放入两个set集合中,然后通过API查看两个set集合的交集数据。(intersect)

关注推送(feed流)

Feed流效果:系统分析用户想看什么,然后将内容推送给用户,使其节约时间,不用主动寻找。

Feed流的两种常见模式:

1,Timeline:不做内容筛选,简单的按照内容发布时间排序,常用于好友或关注。例如朋友圈。

2,智能排序:利用智能算法屏蔽掉违规的、用户不感兴趣的内容。推送用户感兴趣信息来吸引用户

 本项目采用Timeline模式,该模式有三种实现方案:

拉模式:(读扩散)在用户选择读信息时,将关注的人更新的内容全部拉取过来再排序,用户可以一次性看完之后清楚;但是缺点就是,如果用户关注的人太多信息太多,一次性拉取信息对服务器压力巨大。(多个关注的人在发件箱发的在一次读中全拉取过来到用户收件箱)

推模式:(写扩散)关注的人发一条消息这条消息就传递到粉丝收件箱中;时效快不用临时拉取但是如果粉丝太多就会有很多分数据到粉丝,内存压力大。

推拉结合模式:读写混合,兼具推和拉两种模式的优点。如果是粉丝量小的博主就采用推模式,如果是粉丝量大的博主,对于普通粉丝就采用拉模式,对于活跃度高的粉丝就采用推模式。

实现分页查询收邮箱:Feed流数据会不断更新,数据角标也会变化,比如一开始有十个数据,然后每次取固定数量5个数据(10-6),然后有新数据更新,变成了11个数据,然后再取第二页五个数据就变成6-2,而不是5-1.所以传统分页在Feed流中是不适用的。

为了实现分页操作,我们需要两个参数:用来记录上一次查询的最小时间戳lastid(作为下次分页的开始)和偏移量offset(每一页取几个数据)。

先从redis收件箱中按时间戳倒叙查询,跳过前offset个数据实现分页。获得数据之后判断是否为空,不为空更新时间戳,重置偏移量为确保下一次查询。

附近商户

可以采用GEO,先将商家按typeid分类,然后将type作为key,将所有的商家放入到一个GEO集合中。GEO在redis中就一个menber和一个经纬度,我们把x和y轴传入到redis做的经纬度位置去。然后调用GEO的相关函数就可以实现将商家按照距离排序,然后按照之前的方式进行分页,获得商户id,然后根据id拿到商家信息,进行结果的返回等操作。

用户签到

利用BitMap来实现签到,主体思路为:

BitMap(位图):把每一个bit位对应当月的每一天,形成了映射关系。用0和1标示业务状态(1表示已签到,0表示未签到),这种思路就称为位图(BitMap)。

Redis中是利用string类型数据结构实现BitMap,因此最大上限是512M,转换为bit则是 2^32个bit位。

可以将年月作为BitMap的key值,然后对应位置setBit实现签到。

连续签到天数:获得当前这个月的最后一次签到数据,定义一个计数器,然后不停的向前统计,直到获得第一个非0的数字即可,每得到一个非0的数字计数器+1,直到遍历完所有的数据,就可以获得当前月的签到总天数了。

怎么从后往前遍历每个bit位:因为BitMap返回的数据是十进制,让得到的十进制数字和1做与运算,因为1遇见1才是1(计数器++),其他数字都是0,结果数字每与一次就是将结果向右移动一次。

BitMap拓展:解决缓存穿透问题。

如果用户访问了一个数据库不存在并且redis中也不存在的数据,那就相当于进行了缓存穿透,对服务器来说相当于一次攻击。

我们解决方案是:将数据库中的数据所对应的id写入一个list中,用户访问时先在list中判断有没有Id数据,没有直接返回。

但是数据库主键id很长,我们可以采用哈希思想(查找某一个数据是否在里面)

具体思路是:我们创建一个利用string类型数据结构实现的BitMap;在BitMap找到索引为Id%bitmap.size位置,将其设置为1;用户将自己查询信息的id用相同的哈希算法计算,判断那个索引位置的数字是1还是0就可以判断出来数据到底在不在数据库里。

缺点:要考虑哈希冲突产生的误差。

以上内容来自于黑马程序员

后续会继续补一些内容

相关文章:

4.15redis点评项目下

--->接redis点评项目上 Redis优化秒杀方案 下单流程为:用户请求nginx--->访问tomcat--->查询优惠券--->判断秒杀库存是否足够--->查询订单--->校验是否是一人一单--->扣减库存--->创建订单 以上流程如果要串行执行耗时会很多&#xff0c…...

目标检测与分割:深度学习在视觉中的应用

🔍 PART 1:目标检测(Object Detection) 1️⃣ 什么是目标检测? 目标检测是计算机视觉中的一个任务,目标是让模型“在图像中找到物体”,并且判断: 它是什么类别(classif…...

SpringBoot 与 Vue3 实现前后端互联全解析

在当前的互联网时代,前后端分离架构已经成为构建高效、可维护且易于扩展应用系统的主流方式。本文将详细介绍如何利用 SpringBoot 与 Vue3 构建一个前后端分离的项目,展示两者如何通过 RESTful API 实现无缝通信,让读者了解从环境搭建、代码实…...

HEIF、HEIC、JPG 和 PNG是什么?

1. HEIF (High Efficiency Image Format) 定义:HEIF 是一种用于存储单张图像和图像序列(如连拍照片)的图像文件格式。优势:相比传统的图像格式,HEIF 提供了更高的压缩效率和更好的图像质量。压缩算法:HEI…...

第一层、第二层与第三层隧道协议

(本文由deepseek生成,特此声明) 隧道协议是网络通信中用于在不同网络间安全传输数据的关键技术,其工作层次决定了封装方式、功能特性及应用场景。本文将详细介绍物理层(第一层)、数据链路层(第…...

部署qwen2.5-VL-7B

简单串行执行 from transformers import Qwen2_5_VLForConditionalGeneration, AutoProcessor from qwen_vl_utils import process_vision_info import torch, time, threadingdef llm(model_path,promptNone,imageNone,videoNone,imagesNone,videosNone,max_new_tokens2048,t…...

记录jdk8->jdk17 遇到的坑和解决方案

最近项目在升级jdk8->jdk17 springboot2->springboot3 顺序先升级业务服务,后升级组件服务。跟随迭代开发一起验证功能。 1. 使用parent pom 版本管理 spring相关组件的版本。 组件依赖低版本parent不变。 业务服务依赖高版本parent。 2. 修改maven jdk…...

vue3 uniapp vite 配置之定义指令

动态引入指令 // src/directives/index.js import trim from ./trim;const directives {trim, };export default {install(app) {console.log([✔] 自定义指令插件 install 触发了!);Object.entries(directives).forEach(([key, directive]) > {app.directive(…...

杰弗里·辛顿:深度学习教父

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 杰弗里辛顿:当坚持遇见突破,AI迎来新纪元 一、人物简介 杰弗…...

STM32蓝牙连接Android实现云端数据通信(电机控制-开源)

引言 基于 STM32F103C8T6 最小系统板完成电机控制。这个小项目采用 HAL 库方法实现,通过 CubeMAX 配置相关引脚,步进电机使用 28BYJ-48 (四相五线式步进电机),程序通过蓝牙连接手机 APP 端进行数据收发, OL…...

第一个Qt开发的OpenCV程序

OpenCV计算机视觉开发实践:基于Qt C - 商品搜索 - 京东 下载安装Qt:https://download.qt.io/archive/qt/5.14/5.14.2/qt-opensource-windows-x86-5.14.2.exe 下载安装OpenCV:https://opencv.org/releases/ 下载安装CMake:Downl…...

如何编写爬取网络上的视频文件

网络爬虫程序,可以爬取某些网站上的视频,音频,图片或其它文件,然后保存到本地电脑上; 有时在工作中非常有用,那在技术上如何进行爬取文件和保存到本地呢?下面以python语言为例,讲解p…...

TCP 如何在网络 “江湖” 立威建交?

一、特点: (一)面向连接 在进行数据传输之前,TCP 需要在发送方和接收方之间建立一条逻辑连接。这一过程类似于打电话,双方在通话前需要先拨号建立连接。建立连接的过程通过三次握手来完成,确保通信双方都…...

【小白训练日记——2025/4/15】

变化检测常用的性能指标 变化检测(Change Detection)的性能评估依赖于多种指标,每种指标从不同角度衡量模型的准确性。以下是常用的性能指标及其含义: 1. 混淆矩阵(Confusion Matrix) 定义:统…...

交叉熵在机器学习中的应用解析

文章目录 核心概念香农信息量(自信息)熵(Entropy)KL散度(Kullback-Leibler Divergence)交叉熵 在机器学习中的应用作为损失函数对于二分类(Binary Classification):对于多…...

ARM Cortex汇编指令

在ARM架构的MCU开发中,汇编指令集是底层编程的核心。以下是针对Cortex-M系列(如M0/M3/M4/M7/M85)的指令集体系、分类及查询方法的详细说明: 一、指令集体系与核心差异 1. 架构版本与指令集特性 处理器架构指令集特点典型应用场…...

数据结构——二叉树(中)

接上一篇,上一篇主要讲解了关于二叉树的基本知识,也是为了接下来讲解关于堆结构和链式二叉树结构打基础,其实无论是堆结构还是链式二叉树结构,都是二叉树的存储结构,那么今天这一篇主要讲解关于堆结构的实现与应用 堆…...

InnoDB的MVCC实现原理?MVCC如何实现不同事务隔离级别?MVCC优缺点?

概念 InnoDB的MVCC(Multi-Version Concurrency Control)即多版本并发控制,是一种用于处理并发事务的机制。它通过保存数据在不同时间点的多个版本,让不同事务在同一时刻可以看到不同版本的数据,以此来减少锁竞争&…...

UDP目标IP不存在时的发送行为分析

当网络程序使用UDP协议发送数据时,如果目标IP不存在,发送程序的行为取决于网络环境和操作系统的处理机制。以下是详细分析: 1. UDP的无连接特性 UDP是无连接的传输协议,发送方不会预先建立连接,也不会收到对方是否存在…...

WHAT - 动态导入模块遇到版本更新解决方案

文章目录 一、动态导入模块二、常见原因与解决方案1. 模块 URL 错误2. 开发人员发版用户停留在旧页面问题背景解决方案思路1. 监听错误,提示用户刷新2. 使用缓存控制策略:强制刷新3. 动态模块加载失败时兜底4. 使用 import.meta.glob() 或 webpack 的 __…...

02-MySQL 面试题-mk

文章目录 1.mysql 有哪些存储引擎、区别是什么?1.如何定位慢查询?2.SQL语句执行很慢,如何分析?3.索引概念以及索引底层的数据结构4.什么是聚簇索引什么是非聚簇索引?5.知道什么叫覆盖索引嘛 ?6.索引创建原则有哪些?7.什么情况下索引会失效 ?8.谈一谈你对sql的优化的经验…...

#include<bits/stdc++.h>

#include<bits/stdc.h> 是 C 中一个特殊的头文件&#xff0c;其作用如下&#xff1a; 核心作用 ​​包含所有标准库头文件​​ 该头文件会自动引入 C 标准库中的几乎全部头文件&#xff08;如 <iostream>、<vector>、<algorithm> 等&#xff09;&…...

PostgreSQL:逻辑复制与物理复制

🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c=1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编程,高并发设计,Springboot和微服务,熟悉Linux,ESXI虚拟化以及云原生Docker和K8s,热衷于探…...

在企业级部署中如何优化NVIDIA GPU和容器环境配置:最佳实践与常见误区20250414

在企业级部署中如何优化NVIDIA GPU和容器环境配置&#xff1a;最佳实践与常见误区 引言 随着AI和深度学习技术的迅速发展&#xff0c;企业对GPU加速计算的需求愈加迫切。在此过程中&#xff0c;如何高效地配置宿主机与容器化环境&#xff0c;特别是利用NVIDIA GPU和相关工具&…...

iphone各个机型尺寸

以下是苹果&#xff08;Apple&#xff09;历代 iPhone 机型 的屏幕尺寸、分辨率及其他关键参数汇总&#xff08;截至 2023年10月&#xff0c;数据基于官方发布信息&#xff09;&#xff1a; 一、标准屏 iPhone&#xff08;非Pro系列&#xff09; 机型屏幕尺寸&#xff08;英寸…...

栈的学习笔记

使用数组实现一个栈 #include <stdio.h>#define MAX_SIZE 101int A[MAX_SIZE]; int top -1; //栈顶指针&#xff0c;初始为-1&#xff0c;表示栈为空 void push(int x) {if (top MAX_SIZE - 1){printf("栈已满&#xff0c;无法入栈\n");return;}A[top] x;…...

Spring Boot 项目三种打印日志的方法详解。Logger,log,logger 解读。

目录 一. 打印日志的常见三种方法&#xff1f; 1.1 手动创建 Logger 对象&#xff08;基于SLF4J API&#xff09; 1.2 使用 Lombok 插件的 Slf4j 注解 1.3 使用 Spring 的 Log 接口&#xff08;使用频率较低&#xff09; 二. 常见的 Logger&#xff0c;logger&#xff0c;…...

按键精灵安卓/ios脚本辅助工具开发教程:如何把界面配置保存到服务器

在使用按键精灵工具辅助的时候&#xff0c;多配置的情况下&#xff0c;如果保存现有的配置&#xff0c;并且读取&#xff0c;尤其是游戏中多种任务并行情况下&#xff0c;更是需要界面进行保存&#xff0c;简单分享来自紫猫插件的配置保存服务器写法。 界面例子&#xff1a; …...

[react]Next.js之自适应布局和高清屏幕适配解决方案

序言 阅读前首先了解即将要用到的两个包的作用 1.postcss-pxtorem 自动将 CSS 中的 px 单位转换为 rem 单位按照设计稿尺寸直接写 px 值&#xff0c;由插件自动计算 rem 值 2.amfe-flexible 动态设置根元素的 font-size&#xff08;即 1rem 的值&#xff09;根据设备屏幕宽度和…...

STM32H503CB升级BootLoader

首先&#xff0c;使用SWD接口&#xff0c;ST-LINK连接电脑和板子。 安装SetupSTM32CubeProgrammer_win64 版本2.19。 以下是接线和软件操作截图。...