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

【Gin-Web】Bluebell社区项目梳理5:投票功能分析与实现

本文目录

  • 一、投票功能
    • 投票流程
    • 实现代码
    • redis投票

一、投票功能

投票流程

首先我们要明确,就是 谁(哪个用户:userID)哪个帖子(postID) 投了 什么票(赞成票or反对票)。

赞成票越多,热度越高,就会越展示在前面。

在redis中可以用zset存储帖子,那么有两种存储方式。

一是根据帖子的发布时间存储帖子(根据时间戳来,时间越新,时间戳越大,越在前面),或者是按照评分来存储帖子。

在这里插入图片描述

然后还可以设计一个zset,用来存储给某个帖子投票用户。哪个用户投了赞成票就记为+1,投了反对票就记为-1。

在这里插入图片描述

所以总的来设计了一个帖子算法,投一张赞成票就加对应的分数,比如400分。

时间戳+赞成票*400分=评分,评分越高越放前面。

实现代码

首先我们封装了投票数据的结构体。

在这里插入图片描述

然后是controller层。

在这里插入图片描述
然后就是具体投票的业务逻辑实现部分Logic.VoteForPost

strconv.Itoa 是一个函数,用于将整数转换为字符串。它要求输入必须是 int 类型,因此这里使用了 int(userId) 将 userId 转换为 int。将用户 ID 转换为字符串格式,因为 Redis 的键通常是以字符串形式存储的。

在这里插入图片描述

redis投票

来看看投票的情况:

v=1时,有两种情况1.之前没投过票,现在要投赞成票		 --> 更新分数和投票记录	差值的绝对值:1	+4322.之前投过反对票,现在要改为赞成票	 --> 更新分数和投票记录	差值的绝对值:2	+432*2v=0时,有两种情况1.之前投过反对票,现在要取消			 --> 更新分数和投票记录	差值的绝对值:1	+4322.之前投过赞成票,现在要取消			 --> 更新分数和投票记录	差值的绝对值:1	-432v=-1时,有两种情况1.之前没投过票,现在要投反对票		 --> 更新分数和投票记录	差值的绝对值:1	-4322.之前投过赞成票,现在要改为反对票	 --> 更新分数和投票记录	差值的绝对值:2	-432*2

除此之外,我们还有对投票的限制:

每个帖子自发起之日起,一个星期之内允许用户投票,超过一个星期就不允许投票了。同时到期之后将redis中保存的赞成票数及反对票数存储到mysql表中。到期之后删除 KeyPostVotedZSetPrefix

这里的 KeyPostVotedZSetPrefix 就是记录用户及投票类型。

在这里插入图片描述

我们来看看redis.go的相关代码,其中client就是redis客户端。

在这里插入图片描述
service层中,设置了相关的逻辑代码,来看看处理流程。

首先我们需要去redis中获取帖子的发布时间,从client中拿即可。并检查当前时间与帖子发布时间的差值是否超过一周(OneWeekInSeconds)。如果超过一周,返回错误 ErrorVoteTimeExpire,表示投票已过期。

在这里插入图片描述

我们在redis的目录路径下,封装了error错误,声明了几个自定义错误变量。这些错误变量用于在 Redis 相关的操作中表示特定的错误情况。errors.New 是一个常用的error函数,用于创建一个新的错误对象。

通过定义全局的错误变量,为 Redis 相关的操作提供了一致的错误处理机制。使用 errors.New 创建的错误对象可以在整个包中复用,避免了重复创建相同的错误信息,提高了代码的可维护性和一致性。

比如当投票时间已经过期了,我们就需要返回投票过期的错误。
在这里插入图片描述


postTime := client.ZScore(KeyPostTimeZSet, postID).Val()

ZScore 方法查询帖子 ID 对应的分数(发布时间),并通过 Val() 方法获取该分数的实际值。返回的 postTime 是一个浮点数,表示帖子的发布时间(通常是 Unix 时间戳)。

ZScore 是 Redis 客户端提供的一个方法,用于从有序集合(ZSet)中获取某个成员的分数。它的签名通常是:

func (c *Client) ZScore(key string, member string) *FloatCmd

key:有序集合的键名(唯一标识:键名是 Redis 数据库中唯一标识有序集合的字符串。通过键名,你可以访问和操作特定的有序集合。)

member:有序集合中的成员(在这里是帖子的 ID)。

在刚刚我们有提到,const KeyPostTimeZSet = "bluebell:post:time",这是一个常量,定义了存储帖子发布时间的有序集合的键名。


然后就是更新帖子分数,注意更新帖子分数+记录用户为该帖子投票的数据 是要放在一个redis事务中完成的。

在 Redis 中,Pipeline(管道) 是一种用于将多个命令发送到服务器的技术,而 事务(Transaction) 是一种将多个命令打包并一次性执行的机制。在 Redis 的上下文中,Pipeline 和事务经常结合使用,以提高性能和确保操作的原子性

事务 是一种将多个命令打包,并一次性、顺序地执行的机制。Redis 的事务通过 MULTI、EXEC、DISCARD 和 WATCH 命令实现。事务的主要特点包括:事务中的所有命令要么全部执行,要么全部不执行。这确保了操作的原子性,避免了部分执行导致的数据不一致问题。事务中的命令会按照顺序执行,不会被其他客户端的命令打断。

在这里插入图片描述

KeyPostVotedZSetPrefix    = "bluebell:post:voted:" // zset;记录用户及投票类型;参数是post_id

刚刚我们定义了redis的常量,所以我们需要进行下面的操作:

	key := KeyPostVotedZSetPrefix + postIDov := client.ZScore(key, userID).Val()

也就是从 redis中获取 某个帖子 的 用户投票类型,根据用户ID来获取Val值。

也就是下面这个图所示:
在这里插入图片描述

	ov := client.ZScore(key, userID).Val()// 更新:如果这一次投票的值和之前保存的值一致,就提示不允许重复投票if v == ov {return ErrVoteRepested}var op float64if v > ov {op = 1} else {op = -1}diffAbs := math.Abs(ov - v)                                                        // 计算两次投票的差值pipeline := client.TxPipeline()                                                    // 事务操作_, err = pipeline.ZIncrBy(KeyPostScoreZSet, VoteScore*diffAbs*op, postID).Result() // 更新分数

通过Redis事务来更新分数。

TxPipeline() 是 Redis 客户端提供的一个方法,用于创建一个事务性 Pipeline。这个 Pipeline 允许将多个命令打包在一起,并作为一个事务发送到 Redis 服务器。

ZIncrBy 是 Redis 的一个命令,用于在有序集合(ZSet)中增加某个成员的分数。

	if v == 0 {_, err = client.ZRem(key, userID).Result()} else {pipeline.ZAdd(key, redis.Z{ // 记录已投票Score:  v, // 赞成票还是反对票Member: userID,})}_, err = pipeline.Exec()  //执行pipeline中的所有命令

如果v=0,那么从有序集合中移除指定的成员。

client.ZRem:Redis 客户端提供的方法,用于从有序集合中移除指定的成员。

pipeline.ZAdd:Redis 客户端提供的方法,用于将一个成员及其分数添加到有序集合中。这里使用了事务性 Pipeline,确保操作的原子性。

redis.Z:一个结构体,包含成员(Member)和分数(Score)。
Score:用户的投票值(v),表示赞成票(1)或反对票(-1)。
Member:用户的唯一标识符(userID)。


在 Redis 中,有序集合(ZSet)相关的命令都以 Z 开头,例如 ZADD、ZSCORE、ZINCRBY、ZREM 等。

Redis 的有序集合命令都以 Z 开头,例如:
ZADD:将一个或多个成员及其分数添加到有序集合中。
ZSCORE:获取有序集合中成员的分数。
ZINCRBY:增加有序集合中成员的分数。
ZREM:从有序集合中移除成员。


可以看到,再投出一票之后,在原先的redis基础上加了432分。

在这里插入图片描述

相关文章:

【Gin-Web】Bluebell社区项目梳理5:投票功能分析与实现

本文目录 一、投票功能投票流程实现代码redis投票 一、投票功能 投票流程 首先我们要明确,就是 谁(哪个用户:userID) 给 哪个帖子(postID) 投了 什么票(赞成票or反对票)。 赞成票…...

多人协同创作gitea

多人协同创作gitea 在多台设备上协同使用Gitea,主要是通过网络访问Gitea服务器上的仓库来进行代码管理和协作。以下是一些关键步骤和建议,帮助你在多台设备上高效地使用Gitea进行协作: 1. 确保Gitea服务可访问 首先,你需要确保…...

Java 大视界 -- Java 大数据未来十年的技术蓝图与发展愿景(95)

💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...

idea连接gitee完整教程

文章目录 idea连接gitee(使用idea远程兼容gitee) 使用idea远程兼容gitee并反向创建仓库和分支...

问卷数据分析|SPSS实操之相关分析

皮尔逊还是斯皮尔曼的选取主要看数据的分布 当数据满足正态分布且具有线性关系时,用皮尔逊相关系数 当有一个不满住时,用斯皮尔曼相关系数 1. 选择分析--相关--双变量 2. 将Z1-Y2加入到变量中,选择皮尔逊 3. 此处为结果,可看我案…...

汽配出库软件助力企业数字化转型,佳易王汽配出入库管理系统操作教程

一、概述 本实例以佳易王汽配出入库管理系统V17.1版本为例说明,其他版本可参考本实例。试用版软件资源可到文章最后了解,下载的文件为压缩包文件,请使用免费版的解压工具解压即可试用。 软件特点: 1、软件为绿色免安装版&#…...

二叉树(中等题)

1、先序,中序遍历确定二叉树 105 方法一、 前提 ① 必须不能有重复元素② 只有先序+中序和后序+中序才能实现唯一树 思考要点: 不要想着用for循环,递归一定更好解决输入是vector,递归就得考虑传入索…...

Versal - 基础6(Linux 开发 AIE-ML + 自动化脚本解析)

目录 1. 简介 2. 步骤解析 2.1 概览 2.1.1 步骤依赖关系 2.1.2 总目录结构 2.2 Vitis XPFM 2.2.1 Dir 2.2.2 Makefile 2.2.3 vitis_pfm.py 2.3 Kernels 2.3.1 Dir 2.3.2 Makefile 2.3.3 config 文件 2.4 AIE_app 2.4.1 Dir 2.4.2 Makefile 2.4.3 aie 要点 2.…...

什么是矩阵账号?如何高效运营tiktok矩阵账号

‍‌​​‌‌​‌​‍‌​​​‌‌​​‍‌​​​‌​‌​‍‌​​‌​​‌​‍‌​‌‌​‌‌‌‍‌​‌​‌​​​‍‌​​‌​‌‌​‍‌​​​​‌‌​‍‌​‌​​‌‌‌‍‌​​‌‌​‌​‍‌​‌​​‌‌‌‍‌​‌‌‌​​‌‍‌‌​​‌‌‌​‍‌‌​​‌‌​​‍‌…...

tortoiseSVN 如何克隆项目到本地

导入项目成功,如下图:...

趣解PostGet请求的原理、应用场景及区别

趣解Post&Get请求的原理、应用场景及区别 POST 和 GET 的「身份之谜」:快递员与侦探的终极对决 一、角色设定:快递员(POST) vs 侦探(GET) GET(侦探): 任务&#xff…...

在PHP Web开发中,实现异步处理有几种常见方式的优缺点,以及最佳实践推荐方法

1. 消息队列 使用消息队列(如RabbitMQ、Beanstalkd、Redis)将任务放入队列,由后台进程异步处理。 优点: 任务持久化,系统崩溃后任务不丢失。 支持分布式处理,扩展性强。 实现步骤: 安装消息…...

深入解析过滤器模式:数据筛选与处理的高效工具

过滤器模式:数据筛选与处理的高效工具 在软件开发的复杂领域中,数据的筛选与处理是常见的任务。过滤器模式作为一种实用的设计模式,为解决这类问题提供了有效的解决方案。它允许开发者根据不同的标准对一组对象进行过滤操作,从而…...

DeepSeek R1/V3满血版——在线体验与API调用

前言:在人工智能的大模型发展进程中,每一次新模型的亮相都宛如一颗投入湖面的石子,激起层层波澜。如今,DeepSeek R1/V3 满血版强势登场,为大模型应用领域带来了全新的活力与变革。 本文不但介绍在线体验 DeepSeek R1/…...

排序链表--字节跳动

少年的书桌上没有虚度的光阴 题目描述 请你对链表进行排序 思路分析 核心思想:归并排序 有三个部分 链表排序实现 1. merge 函数 21.见 合并两个有序链表, 首先创建一个虚拟头节点 newhead,并使用指针 tail 来构建合并后的链表。 通过…...

Python爬虫-批量爬取股票数据猫各股票代码

前言 本文是该专栏的第47篇,后面会持续分享python爬虫干货知识,记得关注。 本文笔者以股票数据猫为例子,基于Python爬虫,批量获取各股票代码数据。 具体实现思路和详细逻辑,笔者将在正文结合完整代码进行详细介绍。废话不多说,下面跟着笔者直接往下看正文详细内容。(附…...

打开Firefox自动打开hao360.hjttif.com标签解决方案

现象 打开Firefox自动打开hao360.hjttif.com标签,同时用户自己设置的主页也会在一个新标签打开。点击hjttif这个标签,就会跳转到hao.360.com 打开Edge不会出现上述现象。搜遍全网都找不到解决方法。博客园上有一篇文章2025-02-14.防流氓软件篡改主页提到…...

【爬虫基础】第一部分 网络通讯-编程 P3/3

上节内容回顾:【爬虫基础】第一部分 网络通讯 P1/3-CSDN博客 【爬虫基础】第一部分 网络通讯-Socket套接字 P2/3-CSDN博客 相关文档,希望互相学习,共同进步 风123456789~-CSDN博客 前言 1.知识点碎片化:每个网站实现…...

Ubuntu 下 nginx-1.24.0 源码分析 - ngx_atoi 函数

ngx_atoi 声明在 src/core/ngx_string.h ngx_int_t ngx_atoi(u_char *line, size_t n); 定义在 src/core/ngx_string.c ngx_int_t ngx_atoi(u_char *line, size_t n) {ngx_int_t value, cutoff, cutlim;if (n 0) {return NGX_ERROR;}cutoff NGX_MAX_INT_T_VALUE / 10;cutlim…...

PG:ERROR: cannot freeze committed xmax

目录 原因**问题原因****PostgreSQL 底层逻辑** 解决方案1**问题分析****排查步骤****1. 检查长时间运行的事务****2. 检查未提交的事务****3. 检查 autovacuum 配置****4. 检查事务 ID 使用情况****5. 检查表的 relfrozenxid** **解决方法****1. 手动运行 VACUUM FREEZE****2.…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层&#xf…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...

数据库分批入库

今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...

土建施工员考试:建筑施工技术重点知识有哪些?

《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目,核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容,附学习方向和应试技巧: 一、施工组织与进度管理 核心目标: 规…...

【若依】框架项目部署笔记

参考【SpringBoot】【Vue】项目部署_no main manifest attribute, in springboot-0.0.1-sn-CSDN博客 多一个redis安装 准备工作: 压缩包下载:http://download.redis.io/releases 1. 上传压缩包,并进入压缩包所在目录,解压到目标…...

ThreadLocal 源码

ThreadLocal 源码 此类提供线程局部变量。这些变量不同于它们的普通对应物,因为每个访问一个线程局部变量的线程(通过其 get 或 set 方法)都有自己独立初始化的变量副本。ThreadLocal 实例通常是类中的私有静态字段,这些类希望将…...