golang入门项目——打卡抽奖系统

news2024/11/23 15:51:11

功能介绍

用户加入群组之后,会在签到群组所设的签到地点进行签到和签退,并限制同一个设备只能签到一个用户,签到成功之后。会获取一定的限制在该群组使用的积分。该群组可以设置一些抽奖活动,用户可使用该群组内的积分来进行该群组的抽奖活动。

项目功能

前台的主要功能

功能项功能说明
基本的用户操作用户邮箱注册、登陆、修改头像、修改用户地址、修改用户密码
群组操作创建群组、用户加入群组、改变群组头像、获取群组成员、群组的解散
群组打卡用户签到、签退,获取用户和群组成员的打卡记录,打卡记录的生成,请假
打卡配置群组打卡地点的增加、删除,获取群组打卡位置,打卡ip限制
群组抽奖活动抽奖活动的增加、删除、更新,获取群组的抽奖活动。用户抽奖
群组抽奖奖品抽奖活动奖品的增加、删除、更新,获取活动的奖品列表
用户的抽奖记录用户抽奖记录的生成、获取

后台的主要功能

管理员操作管理员的登陆
用户管理用户列表的获取,用户的删除
群组管理群组的删除
活动管理活动列表的获取,活动的删除
用户订单管理用户订单的获取、删除
打卡管理获取群组和用户的打卡记录

项目实现

技术选型

技术选型
语言Go1.20
存储Redis、Mysql
rpc框架Kitex
http框架Hertz
orm框架Gorm、Gen
消息队列Rabbitmq
日志框架Logrus、File-rotatelogs
容器技术Docker
服务注册与发现Etcd

开发设计

1.JWT鉴权:

基于golang-jwt包实现了token的颁发与解析
token的自动续期

2.密码安全:

长度限制:为了保证密码的可记忆性以及安全性,限制密码长度为6~30
加密:使用md5加盐进行加密。

3.接口防刷:

基于Redis构建了一个通过检测用户IP地址限制统一IP多次刷赞的中间件,服务器可配置每分钟用户访问
点赞接口的上限量,当用户访问接口次数超过此上限时,将返回“操作频繁,请稍后重试”信息提醒。

4.Redis缓存:

对近期访问的信息进行缓存,对访问的不存在的数据也在redis当中缓存空值来防止缓存穿透。
对于数据更新操作,为了保证数据库与缓存的数据一致性,采用先更新数据库再更新缓存,然后延时双
删的策略

5.消息队列:

引入了消息队列来应对一些高并发场景下的并发安全问题
对服务之间进行解耦
对一些重要的存储失败的信息进行暂存再次尝试存储来避免重要数据的丢失

6.高并发设计

对于抽奖场景的高并发,先通过查缓存判断当前时间是否在活动时间内,活动奖品是否有剩余,用户的
积分是否够用。满足所有条件才会把这次抽奖请求放入到rabbitmq中。lottery服务处理完这次请求之后,	
通过redis异步返回抽奖的结果。
高并发下如果生成用户抽奖记录失败,会把这次订单存到rabbitmq中,再次尝试生成订单,这样保证了	
重要信息的不丢失。
对于发送邮件验证码,用户签到记录的生成这种可能需要高并发的场景,也采用了rabbitmq做中间缓存

7.Docker部署:

使用dokcer-compose整合项目依赖,快速部署所需要的依赖并根据init.sql文件建表。

8.OSS存储:

使用七牛云服务器进行OSS存储,来减少本地磁盘IO

架构设计

微服务设计

在这里插入图片描述

数据库设计

在这里插入图片描述
1.活动的奖品总数、群组的人数、奖品的数量、用户在群组的签到天数
2.每张表添加了deleted_at作软删除,并记录更新创建时间
3.索引:

1.查询时deleted_at常做条件使用,所有的deleted_at建立索引
2.对user表的email和deleted_at作联合唯一索引
3.对user_group表,对gid建立索引,对uid,gid,deleted_at建立联合唯一索引
4.对sign_month表,对gid建立索引,对uid,month,gid建立联合唯一索引
5.对sign_record表,对gid建立索引,对uid,gid,deleted_at建立联合唯一索引
6.对sign_group_pos表,对gid,name,longtitude,latitude,deleted_at建立联合唯一索引
7.对ask_leave表,对gid,uid,time,deleted_at建立联合唯一索引
8.对admin表,对name,password,deleted_at建立联合唯一索引
9.对activity表,对uid建立索引,对gid建立索引
10.对prize表,对aid建立索引
11.对user_order表,对uid,pid建立联合唯一索引

缓存设计

keyvalue相关操作
user:{uid}hash类型存储用户的基本信息
{email}:{code}string类型存储用户注册时的验证码
group:{gid}hash类型存储群组的基本信息
sign:user:start:{gid}set类型存储群组中签到的用户的id
sign:user:end:{gid}set类型存储群组中签退的用户的id
sign:month:{gid}:{uid}setbit类型存储群组用户的月签到信息
sign:ip:{ip}string类型存储操作请求的ip地址和用户的的映射
sign:location:{gid}geo类型存储群组签到的地理位置
record:{uid}hash类型存储用户的签到记录
activity:{aid}hash类型存储活动的信息
prize:{pid}hash类型存储奖品的信息
prize:aid:{aid}set类型存储活动的所有奖品id
order:user:{uid}:{offset}:{limit}set类型存储用户奖品单页的订单id列表
order:{oid}hash类型存储用户奖品单的信息
email:return:{email}string类型从rabbitmq读取email并发送邮寄后的异步返回处理结果的code
sign:return:{uid}:{gid}string类型从rabbitmq读取签到请求信息后异步返回处理结果的code
choose:return:{uid}:{gid}string类型从rabbitmq读取抽奖请求信息后异步返回处理结果的code
ip:count:{ip}string类型用于存储ip地址在2分钟内的请求次数
token:{token}string类型存储初始token指向的真实token

消息队列设计

在这里插入图片描述

代码目录

├── cmd
│   ├── api
│   │   └── biz
│   │       ├── handler
│   │       │   ├── api
│   │       │   │   ├── base
│   │       │   │   │   ├── admin.go
│   │       │   │   │   ├── group.go
│   │       │   │   │   └── user.go
│   │       │   │   ├── lottery
│   │       │   │   │   ├── activity.go
│   │       │   │   │   ├── choose.go
│   │       │   │   │   ├── prize.go
│   │       │   │   │   └── record.go
│   │       │   │   └── sign
│   │       │   │       ├── record.go
│   │       │   │       ├── sign.go
│   │       │   │       └── signPos.go
│   │       │   ├── common
│   │       │   │   └── handle_biz.go
│   │       │   └── ping.go
│   │       ├── middleware
│   │       │   ├── auth.go
│   │       │   └── ipLimit.go
│   │       ├── model
│   │       │   ├── api
│   │       │   │   └── api.go
│   │       │   ├── lottery
│   │       │   │   └── lottery.go
│   │       │   ├── sign
│   │       │   │   └── sign.go
│   │       │   └── user
│   │       │       └── base.go
│   │       └── router
│   │           ├── api
│   │           │   ├── api.go
│   │           │   └── middleware.go
│   │           └── register.go
│   ├── generate
│   │   └── main.go
│   ├── main
│   │   └── main.go
│   └── rpc
│       ├── base
│       │   └── base.go
│       ├── lottery
│       │   └── lottery.go
│       └── sign
│           └── sign.go
├── dao
│   ├── cache
│   │   ├── activity.go
│   │   ├── group.go
│   │   ├── handlerErr.go
│   │   ├── init.go
│   │   ├── ip.go
│   │   ├── order.go
│   │   ├── prize.go
│   │   ├── sign.go
│   │   └── user.go
│   └── db
│       ├── activity.go
│       ├── admin.go
│       ├── group.go
│       ├── init.go
│       ├── model
│       │   ├── activity.gen.go
│       │   ├── admin.gen.go
│       │   ├── ask_leave.gen.go
│       │   ├── prize.gen.go
│       │   ├── sign_group.gen.go
│       │   ├── sign_group_pos.gen.go
│       │   ├── sign_list.gen.go
│       │   ├── sign_month.gen.go
│       │   ├── sign_record.gen.go
│       │   ├── user.gen.go
│       │   ├── user_group.gen.go
│       │   └── user_order.gen.go
│       ├── order.go
│       ├── prize.go
│       ├── record.go
│       ├── sign.go
│       └── user.go
├── docker-compose.yml
├── go.mod
├── go.sum
├── idl
│   ├── api.thrift
│   ├── base.thrift
│   ├── lottery.thrift
│   └── sign.thrift
├── kitex_gen
│   ├── lottery
│   │   ├── k-consts.go
│   │   ├── k-lottery.go
│   │   ├── lottery.go
│   │   └── lotteryservice
│   │       ├── client.go
│   │       ├── invoker.go
│   │       ├── lotteryservice.go
│   │       └── server.go
│   ├── sign
│   │   ├── k-consts.go
│   │   ├── k-sign.go
│   │   ├── sign.go
│   │   └── signservice
│   │       ├── client.go
│   │       ├── invoker.go
│   │       ├── server.go
│   │       └── signservice.go
│   └── user
│       ├── base.go
│       ├── baseservice
│       │   ├── baseservice.go
│       │   ├── client.go
│       │   ├── invoker.go
│       │   └── server.go
│       ├── k-base.go
│       └── k-consts.go
├── pkg
│   ├── config
│   │   └── mysql
│   │       └── init.sql
│   ├── constants
│   │   └── const.go
│   ├── errmsg
│   │   └── error.go
│   ├── jwt
│   │   └── jwt.go
│   └── log
│       ├── log.go
│       └── logs
├── rabbitmq
│   ├── comm
│   │   └── comm.go
│   ├── consumer
│   │   ├── chooseConsumer.go
│   │   ├── emailConsumer.go
│   │   ├── init.go
│   │   ├── orderConsumer.go
│   │   ├── recordConsumer.go
│   │   ├── regularConsumer.go
│   │   └── signConsumer.go
│   ├── model
│   │   ├── choose.go
│   │   ├── order.go
│   │   ├── record.go
│   │   └── sign.go
│   └── producer
│       ├── chooseProducer.go
│       ├── emailProducer.go
│       ├── init.go
│       ├── orderProducer.go
│       ├── recordProducer.go
│       ├── regularProducer.go
│       └── signProducer.go
├── script
│   └── bootstrap.sh
├── service
│   ├── base
│       ├── pos.go
│       ├── record.go
│       └── sign.go
└── utils
    ├── email.go
    └── rand.go

源码地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/450338.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python+mysql+php搭建另类免费代理池

文章目录 前言:思路:开干:php连接MySQL取ip和端口:效果图: 最后调用代理池:总结: 前言: 为什么说另类的,因为我完全是按照我自己的想法来的,比较鸡肋,但是能用&#xff…

短视频app开发:如何提高视频播放稳定性

简介 如今,短视频已经成为人们日常生活中不可或缺的一部分,而短视频app的开发也日益成为了人们热议的话题。在短视频app开发的过程中,如何提高视频播放稳定性是一个非常重要的问题。本文将从短视频源码角度出发,分享提高短视频ap…

如何优化语音交友app开发的搜索和匹配算法

语音交友app开发的挑战 在当今社交媒体行业中,语音交友app开发已经成为一个热门的领域。越来越多的人开始使用语音交友app来寻找新的朋友,这也为开发者们带来了许多机会。然而,这个领域也面临着一些挑战。其中一个最大的挑战是如何优化搜索和…

掏空腰包,日子难过,机缘转岗软件测试,这100个日夜的心酸只有自己知道...

我今年27岁,原本从事着土木工程相关的工作,19年开始有了转行的想法... 大学刚毕业那年,我由于学的是土木工程专业,自然而然的从事了和土木工程相关的工作,房贷、车贷,在经济的高压下,当代社会许…

大数据题目测试(一)

目录 一、环境要求 二、提交结果要求 三、数据描述 四、功能要求 1.数据准备 2.使用 Spark,加载 HDFS 文件系统 meituan_waimai_meishi.csv 文件,并分别使用 RDD和 Spark SQL 完成以下分析(不用考虑数据去重)。 (1)配置环境…

Java设计模式-day01

1,设计模式概述 1.1 软件设计模式的产生背景 "设计模式"最初并不是出现在软件设计中,而是被用于建筑领域的设计中。 1977年美国著名建筑大师、加利福尼亚大学伯克利分校环境结构中心主任克里斯托夫亚历山大(Christopher Alexand…

React Native iOS打包详细步骤

一、在自己项目的iOS文件夹下新建一个文件夹取名bundle 二、将打包命令写到项目package.json文件里,终端执行 npm run bundle-ios 先添加如下(注意:这里写的路径"./ios/bundle"就是上面bundle创建的文件夹)&#xff1a…

C51单片机介绍

本文为学习51单片机的学习的基础,先介绍单片机是什么。所使用的单片机有什么资源。每一个功能的作用是什么。本文使用的是STC89C52RC 40I-PDIO40,故以此为基础研究学习。 C51单片机介绍 单片机的概述单片机的组成部分中央处理器程序存储器数据存储器定时…

图神经网络能做什么?

从概念上讲,我们可以将图神经网络的基本学习任务分为 5 个不同的方向: (1)图神 经网络方法; (2)图神经网络的理论理解; (3)图神经网络的可扩展性&#xff1b…

Git的进阶使用(二)

本篇文章旨在分享本人在学习Git时的随笔记🤩 文章目录 概述1、Git 分支1.1 主干分支1.2 其他分支1.2.1 创建分支1.2.2 查看分支1.2.3 切换分支1.2.4 删除分支 2、Git 合并2.1 主干分支2.2 其他分支2.3 合并分支 3、Git 冲突3.1 主干分支3.2 其他分支3.3 切换分支 -B…

Replika:AI智能聊天机器人

【产品介绍】 Replika,这个名字可能有点拗口,但如果你知道这是复制品Replica的同音变体,你即刻能明白这个产品的定位了。官方Luka公司定义它是你的AI朋友,默默学习你,最终成为你的复制品。它不像现在市面上各大厂的AI助…

《ChatGPT开发应用指南》,Datawhale开源了!

Datawhale发布 开源教程:HuggingLLM,Datawhale团队 随着ChatGPT的爆火,我们相信未来会有越来越多的大模型及类似OpenAI提供的服务出现,AI 正在逐渐平民化,将来每个人都可以利用大模型轻松地做出自己的AI产品。 Huggin…

【历史上的今天】3 月 23 日:网景创始人出生;FORMAC 语言的开发者诞生;PRMan 非商业版发布

整理 | 王启隆 透过「历史上的今天」,从过去看未来,从现在亦可以改变未来。 今天是 2023 年 3 月 23 日,在 141 年前的今天,1882 年 3 月 23 日,抽象代数之母艾米诺特(Emmy Noether)诞生。她的…

JUC-多线程(12. AQS-周阳)学习笔记

文章目录 1. 可重入锁1.1. 概述1.2. 可重入锁类型1.3. Synchronized 可重入实现机理 2. LockSupport2.1. LockSupport 是什么2.2. 3种线程等待唤醒的方法2.2.1 Object 的等待与唤醒2.2.2. Condition接口中的等待与唤醒2.2.3. 传统的 synchronized 和 Lock 实现等待唤醒通知的约…

本地搭建属于自己的ChatGPT:基于PyTorch+ChatGLM-6b+Streamlit+QDrant+DuckDuckGo

本地部署chatglm及缓解时效性问题的思路: 模型使用chatglm-6b 4bit,推理使用hugging face,前端应用使用streamlit或者gradio。 微调对显存要求较高,还没试验。可以结合LoRA进行微调。 缓解时效性问题:通过本地数据库…

YOLOv7如何提高目标检测的速度和精度,基于模型结构提高目标检测速度

目录 一、目标检测二、目标检测的速度和精度的权衡1、速度和精度的概念和定义2、如何评估目标检测算法的速度和精度3、速度和精度之间的权衡 三、基于模型结构提高目标检测速度1、Backbone网络的选择2、特征金字塔网络的设计3、通道注意力机制4、混合精度训练 一、目标检测 目…

光纤网卡传输速率和它的应用领域有哪些呢?通常会用到哪些型号网络变压器呢?

Hqst盈盛(华强盛)电子导读:常有客户问起光纤网卡该如何选用到合适的产品,选用时要注意到哪些事项,这节将结合配合到的网络变压器和大家一起探讨,希望对大家有些帮助。 1.光纤网卡传输速率与网络…

【教程】一文读懂 ChatGPT API 接入指南

ChatGPT 是一个基于自然语言处理技术的 API,它能够根据用户的输入,生成智能回复。结合当前最先进的AI技术,AP智能续写&承接上下文;可以回答各种问题,例如:历史,科学,文化&#x…

【越早知道越好】的道理——能够提高效率的【快捷键】

文章目录 1️⃣虚拟桌面⚜️第一步:打开任务视图⚜️第二步:创建桌面⚜️第三步:桌面切换⚜️第四步:桌面删除 2️⃣窗口切换3️⃣桌面分屏⚜️如何分屏 前言🧑‍🎤:作为程序员👨‍&…

15天学习MySQL计划-多表联查(基础篇)第四天

15天学习MySQL计划(多表联查)第四天 1.多表查询 1.1概述 ​ 指从多张表中查询数据 ​ 在项目开发中,在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,分析并设计表结构,由于业务之间相互…