go-zero框架

gozero(又称go-zero)是一款由知名开发者kevwan设计的Golang微服务框架,专注于高性能、低延迟和易用性。其核心目标是简化分布式系统的开发,提供开箱即用的工具链,涵盖API网关、RPC服务、缓存管理、数据库操作等模块。

项目目录结构

zero_remake/
├── common/
│   ├── init_gorm.go
│   └── init_redis.go
├── shorturl_api/
│   ├── etc/
│   │   └── shorturl.yaml
│   ├── internal/
│   │   ├── config/
│   │   │   └── config.go
│   │   ├── handler/
│   │   │   ├── redirecthandler.go
│   │   │   └── ...
│   │   ├── logic/
│   │   │   ├── redirectlogic.go
│   │   │   └── ...
│   │   ├── svc/
│   │   │   └── servicecontext.go
│   │   └── types/
│   │       └── ...
│   └── main.go
├── shorturl_rpc/
│   ├── etc/
│   │   └── shorturl.yaml
│   ├── internal/
│   │   ├── config/
│   │   │   └── config.go
│   │   ├── logic/
│   │   │   └── ...
│   │   ├── svc/
│   │   │   └── servicecontext.go
│   │   └── types/
│   │       └── ...
│   └── main.go
└── go.mod
  • common/:公共初始化、工具等代码
  • shorturl_api/:API 网关服务
  • shorturl_rpc/:RPC 服务
  • 各自有 etc/ 配置、internal/ 业务代码、main.go 启动入口

配置文件(yaml)

Name: shorturl.rpc
ListenOn: 0.0.0.0:8888
Etcd:Hosts:- 127.0.0.1:2379Key: shorturl.rpcMysql:DbUser: rootDbPort: "3306"DbPass: wwy040609DbName: shorturlDbHost: localhostBizRedis:RedisHost: 127.0.0.1RedisPort: "6379"RedisPass: ""RedisDB: 0

Etcd用于定位RPC服务端口

Mysql用于永久存储

Redis用于缓存热点数据

接口文档

雪花算法

雪花算法的实现原理:

雪花算法是一种随时间变化的分布式全局唯一ID算法,其生成的ID可以看做是一个64位的正整数,除了最高位,将剩余的63位分别分为41位的时间戳,10位的机器ID以及12位的自增序列号。

我们不采用MySQL的主键自增ID和redsi的incr的自增ID,而是使用本地雪花算法的形式直接生成ID,这样性能更高。

Redis

将数据存储在内存上,查询速度极快,可以存放热点数据,减少数据库查询次数
redis的github地址https://github.com/redis/redis
redis-go的github地址https://github.com/redis/go-redis

Redis的几种数据结构

  1. 字符串:可以存储文本、序列化的对象等。例如,可以将用户的登录令牌存储为字符串,方便快速验证用户身份。
  2. 哈希:适合存储对象的多个属性。例如,可以存储用户信息,以用户 ID 为键,用户的各种属性(如姓名、年龄、地址等)作为哈希中的字段和值,方便快速查询和更新用户的单个属性。
  3. 列表:可用于实现消息队列、任务队列等应用场景。例如,将待处理的任务依次加入列表,多个消费者可以从列表中取出任务进行处理。
  4. 集合:存储不重复元素,可用于实现标签系统、好友列表、共同关注等功能。例如,将用户的关注用户列表存储为集合,方便进行集合运算,如求交集、并集等,以找出共同关注的用户。
  5. 有序集合:存储元素及其分数,可用于排行榜系统,根据分数对元素进行排序。例如,存储游戏玩家的分数,按分数对玩家进行排名。

本次项目中的Redis

  1. 本次Redis中的键值对都是以字符串形式进行存储的
  2. 本次Redis第一次可以自己设定时间,当Redis中的数据因为expiration设置到期而消失时,如果继续从数据库中可以获取时间,那么自动将其添加到缓存中从新设置为24h
if err := l.svcCtx.Redis.Rdb.Set(l.svcCtx.Redis.Ctx, shortCode, in.Url, expireDuration).Err(); err != nil {return &shortUrl.GenerateShortUrlResponse{Code:      errmsg.ERROR_FAILED_SAVE_TO_REDIS,Shortcode: "",}, errors.New("Fail to save to redis")}

布隆过滤器

Bloom Filter:short-url/zero_remake/shorturl_rpc/internal/logic/repository/BoomFilter.go

作用

  1. 布隆过滤过滤器通过hash存储可以快速判断数据是否已经存在
  2. 如果出现缓存和数据库中都没有的数据,那么可以通过布隆过滤器快速判断数据不存在,减少数据库查询次数(缓存穿透)

hash 算法

布隆过滤器的hash算法

布隆过滤器的优缺点

优点
  1. 时间复杂度低,增加和查询元素的时间复杂为O(N),(N为哈希函数的个数,通常情况比较小)
  2. 保密性强,布隆过滤器不存储元素本身
  3. 存储空间小,如果允许存在一定的误判,布隆过滤器是非常节省空间的(相比其他数据结构如Set、Map集合)
缺点
  1. 有点一定的误判率,但是可以通过调整参数来降低
  2. 无法获取元素本身
  3. 很难删除元素

short-url\server\server.go 服务层

GenerateShortURL(发送长链接并生成短链接)

工作流程
  1. 检查URL是否为空:如果URL为空,返回错误。
  2. 检查布隆过滤器和数据库:先用布隆过滤器快速检查URL是否已存在,若可能存在则进一步查询数据库确认。
  3. 生成短链:使用MD5哈希和Base64编码生成短链。
  4. 解析过期时间:如果提供了过期时间,则解析并验证其格式。
  5. 存储短链信息:将短链信息存储到MySQL,并将短链和原始URL存储到Redis中,同时设置过期时间。
  6. 更新布隆过滤器:将原始URL添加到布隆过滤器。

HandlerURL(获取短链接并跳转)

工作流程
  1. 清除超时数据:调用 DeleteWithTime() 函数清除Redis中过期的数据。
  2. 查找原始URL : * 首先从Redis中查找短链接对应的原始URL。 * 如果Redis中不存在,则去数据库中查找。
  3. 处理结果: 1. 如果在Redis或数据库中找到原始URL,返回成功并重定向到原始URL。 2. 如果未找到或出现错误,返回相应的错误码。 

特殊的

对于存在超过一个月的数据,会自动在数据库中删除

func (l *HandleShortLogic) DeleteWithTime() error {err := l.svcCtx.DB.Where("created_at < ?", time.Now().Add(-time.Hour*24*30)).Delete(&models.Shorturl{}).Errorif err != nil {return err}return nil
}

server中的InDb函数

这个函数其实可以不用写的,因为每次重启程序布隆过滤器会重置,所以会重复查询添加,如果后端一直开着就不会出现这种问题

func InDb(url string) bool {var shortURL model.Shorturlif err := model.Db.Where("url =?", url).First(&shortURL).Error; err == nil {// 已经生成过,直接返回短链return true}return false
}
if Bloom.MightContain(url) {// 可能已经生成过,进行精确检查var shortURL model.Shorturlif err := model.Db.Where("url =?", url).First(&shortURL).Error; err == nil {// 已经生成过,直接返回短链log.Println("已经生成过,直接返回短链")return errmsg.SUCCESS, shortURL.Shorturl}}

你会发现布隆过滤器的判断和这个函数如出一辙

例子: https://www.google.com/search?q=%E7%89%9B%E5%AE%A2%E8%B0%83%E6%95%B4%E7%AE%80%E5%8E%86%E5%90%84%E4%B8%AA%E6%A8%A1%E5%9D%97%E7%9A%84%E9%A1%BA%E5%BA%8F

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux-修改线上MariaDB服务端口号

准备工作&#xff08;很重要&#xff01;&#xff01;&#xff01;&#xff09;&#xff1a; 提前做好Linux服务器快照 提前做好数据库数据备份 1. 修改配置文件 首先&#xff0c;我们需要找到MariaDB的配置文件。通常情况下&#xff0c;这个文件位于以下位置&#xff1a;…

Spring Cloud 微服务(负载均衡策略深度解析)

&#x1f4cc; 摘要 在微服务架构中&#xff0c;负载均衡是实现高可用、高性能服务调用的关键机制之一。Spring Cloud 提供了基于客户端的负载均衡组件 Ribbon&#xff0c;结合 Feign 和 OpenFeign&#xff0c;实现了服务间的智能路由与流量分配。 本文将深入讲解 Spring Clo…

HTML/CSS基础

1.html:超文本标记语言。它是一种标识性的语言&#xff0c;非编程语言&#xff0c;不能使用逻辑运算。通过标签将网络上的文本格式进行统一&#xff0c;使用分散网络资源链接为一个逻辑整体&#xff0c;属于标记语言。 超文本&#xff1a;就是指页面内可以包含图片&#xff0…

C# 事件驱动编程的核心:深度解析发布者_订阅者模式

适用场景&#xff1a;GUI交互、消息队列、微服务通信等需要解耦事件生产与消费的系统 &#x1f9e9; 模式核心组件解析 发布者&#xff08;Publisher&#xff09; 作用&#xff1a;定义事件并管理订阅者列表关键行为&#xff1a; 提供和-运算符注册/注销订阅者通过Invoke()方…

华为云Flexus+DeepSeek征文 | 从零开始搭建Dify-LLM应用开发平台:华为云全流程单机部署实战教程

华为云FlexusDeepSeek征文 | 从零开始搭建Dify-LLM应用开发平台&#xff1a;华为云全流程单机部署实战教程 前言一、华为云Dify-LLM平台介绍1. Dify-LLM解决方案简介2. Dify-LLM解决方案地址3. Dify-LLM单机架构介绍4. 预估成本说明 二、华为云Maas平台介绍1. 华为云ModelArts …

oracle集合三嵌套表(Nested Table)学习

嵌套表 嵌套表(Nested Table)是Oracle中的一种集合数据类型&#xff0c;它允许在表中存储多值属性&#xff0c;类似于在表中嵌套另一个表。 嵌套表具有以下特点&#xff1a; 是Oracle对象关系特性的一部分 可以看作是一维数组&#xff0c;没有最大元素数量限制 存储在单独…

Python学习之——单例模式

Python学习之——单例模式 参考1 利用__metaclass__实现单例super的用法class Singleton(type)元类 2 重载__new__方法实现单例模式3 利用装饰器实现单例考虑一个类如果继承一个单例类的问题 参考 python之metaclasssingleton&#xff08;一&#xff09; python之metaclasssin…

【Linux】U-boot常用命令总结

U-Boot 是嵌入式系统中常用的引导加载程序&#xff08;bootloader&#xff09;&#xff0c;它提供了一套命令行接口&#xff0c;用于调试、加载操作系统镜像以及进行硬件测试等操作。 1、变量操作命令 这些命令用于管理 U-Boot 的环境变量。 命令功能说明setenv name value设…

【Linux】不小心又创建了一个root权限账户,怎么将它删除?!

一.前言 今天在学习linux提权的时候&#xff0c;把新建的一个普通账户权限提升成了root&#xff0c; 当我练习完提权&#xff0c;想要把这个账户删掉的时候。 发现… 好家伙&#xff0c;这个根本删不掉 随后试了各种各样的方法&#xff0c;都不行&#xff0c;后来突然想到是否…

数据结构:数组(Array)

目录 什么是数组&#xff08;Array&#xff09;&#xff1f; &#x1f50d;为什么数组的下标要从 0 开始&#xff1f; 一、内存地址与偏移量的关系&#xff1a;从 0 开始是最自然的映射 二、指针的起点就是第 0 个元素的地址 三、历史原因&#xff1a;BCPL → B → C → …

视频内存太大怎么压缩变小一点?视频压缩的常用方法

视频传生活或者工作中很常见&#xff0c;如发送视频邮件、在线视频播放、视频上传下载等。未压缩的大内存视频文件传输时&#xff0c;不仅会消耗大量的网络带宽资源&#xff0c;还会使传输时间大幅增加。在网速有限的情况下&#xff0c;发送一个几 GB 的未压缩视频可能需要数小…

性能测试包括哪些方面?要掌握哪些知识

性能测试是软件测试中的一个重要方面&#xff0c;它主要关注软件在不同条件下的稳定性、可靠性和性能表现。性能测试包括多个方面&#xff0c;需要掌握的知识也相对广泛。以下是对性能测试包括的方面以及需要掌握的知识分析&#xff1a; 一、性能测试包括的方面 响应时间&…

windows的vscode无法通过ssh连接ubuntu的解决办法

现象&#xff1a; 最近在windows本地通过vscode登录ssh时发现不得劲&#xff0c;总是报错无法与”192.168.1.129“建立连接&#xff0c;如下图&#xff1a; 但是这种报错以及在输出端的信息并没有提供具体错误原因&#xff0c;于是换poweshell来登录&#xff0c;报错如下图&am…

第2章,[标签 Win32] :Windows 的字符串函数

专栏导航 上一篇&#xff1a;第2章 &#xff1a;兼容 ASCII 字符与宽字符的 Windows 函数调用 回到目录 下一篇&#xff1a;无 本节前言 在下面的文章链接里面&#xff0c;我们谈到过&#xff0c;使用兼容版的字符串处理函数的知识。 第2章 &#xff1a;编写兼容多字节字…

Java的SpringAI+Deepseek大模型实战-会话记忆【三】

文章目录 背景项目环境实现步骤第一步、定义会话存储方式方式一、定义记忆存储ChatMemory方式二、注入记忆存储ChatMemory 第二步、配置会话记忆方式一、老版本实现方式二、新版本实现 第三步、添加会话ID 异常处理1、InMemoryChatMemory 无法解析 背景 前两期搭建起大模型对话…

Python3完全新手小白的学习手册 10 文件和异常

文章目录 读取文件读取文件的全部内容 相对路径和绝对路径访问文件中的各行使用文件的内容包含100万位的大型文件圆周率值中包含你的生日吗&#xff1f; 写入文件写入一行写入多行 异常处理ZeroDivisionError异常使用try-except代码块else代码块处理FileNotFoundError异常分析文…

VC Spyglass:工具简介

相关阅读 VC Spyglasshttps://blog.csdn.net/weixin_45791458/category_12828932.html?spm1001.2014.3001.5482 传统上&#xff0c;基于仿真的动态验证技术一直是功能验证的核心方式。随着现代SoC设计日益复杂&#xff0c;静态验证技术的引入变得愈发重要。 Synopsys的 VC Sp…

AWS RDS Aurora全局数据库转区域数据库实战指南:无缝迁移零停机

Aurora全局数据库是AWS提供的跨区域高可用解决方案,但在某些场景下,我们需要将其转换为普通区域数据库。本文将详细介绍这一转换过程,并分享关键技术要点和实战经验。 一、全局数据库与区域数据库概述 AWS RDS Aurora全局数据库是一种跨区域部署的数据库架构,主要用于灾备…

C++之路:函数重载与运算符重载

目录 函数重载运算符重载C运算符重载范围对照表注意事项 运算符重载语法全局运算符重载类内运算符重载下面以一个一元运算符为例&#xff0c;介绍特性1&#xff1a;下面介绍特性3&#xff1a;&#xff08;必须类内重载的运算符‌&#xff09; 函数重载 函数重载是指同一个作用域…

七、SpringCloud 项目迁移至 K8s

七、SpringCloud 项目迁移至 K8s 文章目录 七、SpringCloud 项目迁移至 K8s1、环境准备1.1 集群规划1.2 SpringCloud 项目架构及迁移需求分析 2、迁移 Eureka 集群2.1 构建及容器化2.2 部署至 K8s2.3 创建通信Service 3、迁移网关服务3.1 构建及容器化3.2 部署至 K8s3.3 创建Se…