首页 > 数据库 >【Golang】使用gob格式存储数据到redis

【Golang】使用gob格式存储数据到redis

时间:2024-10-12 17:48:59浏览次数:8  
标签:编码 return string err redis gob Golang

目录

1、背景

之前在压测大数据量的业务场景时,通过pprof分析cpu耗时,发现主要耗时在json序列化和反序列化上,因此为了提高程序性能,考虑用gob编码代替json编码存储数据到redisgob是Go语言标准库中的编码库,用于将Go数据结构(如果结构体、数组、map等)编码为二进制格式,以便在网络传输或本地存储时高效传递数据。

2、gob和json对比

特性gobjson
速度
数据体积
可读性不可读(二进制格式)可读(文本格式)
语言支持仅Go多语言支持
调试难调试易于调试
用途Go内部通信跨语言通信

3、go库下载

redis使用的库为:https://github.com/redis/go-redis

下载:go get github.com/redis/go-redis/v9

4、代码示例

【1】redis初始化

package conn

import (
	"context"
	"sync"
	"time"

	"GoTest/comm/logger"

	"github.com/redis/go-redis/v9"
	"go.uber.org/zap"
)

var (
	redisDbIndexToConnMp map[int]*redis.Client //key为几号库,value为对应库的实例
	redisLock            sync.RWMutex //控制并发安全
)

func init() {
	redisDbIndexToConnMp = make(map[int]*redis.Client)
}

// GetRedisDB
//
//	@Description: 获取对应库的连接
//	@param dbIndex 对应库
//	@return *redis.Client 对应库的实例
func GetRedisDB(dbIndex int) *redis.Client {
	redisLock.RLock()
	if conn, ok := redisDbIndexToConnMp[int(dbIndex)]; ok {
		redisLock.RUnlock()
		return conn
	}
	redisLock.RUnlock()

	redisLock.Lock()
	defer redisLock.Unlock()

	rdb := redis.NewClient(&redis.Options{
		Addr:         "127.0.0.1:6379",
		Password:     "xxxxxx",
		DB:           dbIndex,
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 5 * time.Second,
		MinIdleConns: 10,
		PoolSize:     100,
	})

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := rdb.Ping(ctx).Err(); err != nil {
		logger.Error("redis ping error", zap.Error(err))
		return rdb
	}

	redisDbIndexToConnMp[dbIndex] = rdb

	return rdb
}

封装一个在使用redis操作时初始化实例的方法,只会初始化一次。

【2】封装gob编码和解码方法

package coder

import (
	"bytes"
	"encoding/gob"
)

// EncodeGob
//
//	@Description: gob编码
//	@param date 要编码的数据结构
//	@return []byte 编码之后的数据
//	@return error
func EncodeGob(date interface{}) ([]byte, error) {
	var buf bytes.Buffer

	if err := gob.NewEncoder(&buf).Encode(date); err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}

// DecodeGob
//
//	@Description: gob解码
//	@param gobBytes gob编码之后的数据
//	@param date 接受gob解码的数据结构
//	@return error
func DecodeGob(gobBytes []byte, date interface{}) error {
	buf := bytes.NewBuffer(gobBytes)

	if err := gob.NewDecoder(buf).Decode(date); err != nil {
		return err
	}

	return nil
}

封装之后使用起来和json的使用方法类似。

【3】定义gob编码和解码的数据结构

package types

import "encoding/gob"

// 注册未知类型
func init() {
	gob.Register(map[string]int{})
	gob.Register(map[string]string{})
}

type TestGob struct {
	A int
	B string
	C []int
	D []string
	E interface{} //等会使用map[string]int{}类型测试
	F interface{} //等会使用map[string]string{}类型测试
}

对于interface{}对应的未知类型,需要调用gob.Register()函数去注册,不然gob解码时会识别不出是什么类型,全局初始化一次就好。

【4】gob编码

//要gob编码的数据
	a := types.TestGob{
		A: 111,
		B: "bbb",
		C: []int{1, 2, 3},
		D: []string{"a", "b", "c"},
		E: map[string]string{"A": "a"},
		F: map[string]int{"A": 1},
	}

	//gob编码
	gobBytes, err := coder.EncodeGob(a)
	if err != nil {
		logger.Error("encode gob error", zap.Error(err))
		return
	}

	logger.Info("encode gob success")

	//将编码后的数据写入redis
	gobKey := "test_gob_key"

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err = conn.GetRedisDB(2).Set(ctx, gobKey, gobBytes, 0).Err(); err != nil {
		logger.Error("redis set error", zap.Error(err))
		return
	}

	logger.Info("redis set success", zap.String("key", gobKey), zap.Any("set_value", a))

上述伪代码的作用是将gob编码的数据以string类型存储到redis。代码执行控制台输出:

[2024-10-12 16:35:29.396] | INFO  | Goroutine:1  | [gob_demo/main.go:38]        | encode gob success
[2024-10-12 16:35:29.398] | INFO  | Goroutine:1  | [gob_demo/main.go:50]        | redis set success | {"key": "test_gob_key", "set_value": {"A":111,"B":"bbb","C":[1,2,3],"D":["a","b","c"],"E":{"A":"a"},"F":{"A":1}}}

【5】gob解码

//从redis中取出gob编码的数据
	gobKey := "test_gob_key"

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	val, err := conn.GetRedisDB(2).Get(ctx, gobKey).Bytes()
	if err != nil {
		logger.Error("redis get error", zap.Error(err))
		return
	}

	logger.Info("redis get success", zap.String("key", gobKey))

	//gob解码
	var b types.TestGob
	if err = coder.DecodeGob(val, &b); err != nil {
		logger.Error("decode gob error", zap.Error(err))
		return
	}

	logger.Info("decode gob success", zap.Any("data", b))
}

上述伪代码的作用就是从redis中取出gob编码的数据,然后进行gob界面并打印。代码执行控制台输出:

[2024-10-12 16:35:31.968] | INFO  | Goroutine:1  | [gob_demo/main.go:65]        | redis get success | {"key": "test_gob_key"}
[2024-10-12 16:35:31.968] | INFO  | Goroutine:1  | [gob_demo/main.go:74]        | decode gob success | {"data": {"A":111,"B":"bbb","C":[1,2,3],"D":["a","b","c"],"E":{"A":"a"},"F":{"A":1}}}

5、总结

在工作中修改gob编码方式存储在redis之后,在数据量比较大的时候,相比json可以节省1/3的内存,序列化和反序列化速度更快,能提高程序性能。

标签:编码,return,string,err,redis,gob,Golang
From: https://blog.csdn.net/qq_45795794/article/details/142881869

相关文章

  • zinx-Golang轻量级TCP服务器框架学习记录
    目录背景介绍学习资料源代码背景介绍由于工作需要,需要开发高并发的golang服务器。作为一个golang小白,选择一个好的框架既是对项目的负责,也是一个学习的过程。之所以选择Zinx框架,是因为其完整的文档和视频讲解,这对一个初学者来说是非常友好的学习资料Golang轻量级并发服务......
  • python redis使用教程
    文章目录安装Redispython安装redis库使用Python连接Redis使用Redis实现缓存Redis中的常用缓存操作Redis缓存策略发布与订阅事务安装RedisRedisWindows最新安装教程(2024.10.10)python安装redis库pipinstallredisE:\Redis-x64-3.2.......
  • 【力扣150&Golang】分发糖果
    题目:分发糖果n个孩子站成一排。给你一个整数数组ratings表示每个孩子的评分。你需要按照以下要求,给这些孩子分发糖果:每个孩子至少分配到1个糖果。相邻两个孩子评分更高的孩子会获得更多的糖果。请你给每个孩子分发糖果,计算并返回需要准备的最少糖果数目。示例......
  • 【力扣150&Golang】加油站
    题目:加油站在一条环路上有n个加油站,其中第i个加油站有汽油gas[i]升。你有一辆油箱容量无限的的汽车,从第i个加油站开往第i+1个加油站需要消耗汽油cost[i]升。你从其中的一个加油站出发,开始时油箱为空。给定两个整数数组gas和cost,如果你可以按顺序绕环路行......
  • Redis 单线程模型
    Redis是单线程的,但仍然非常快,主要得益于以下几个因素:I/O多路复用:Redis使用I/O多路复用技术(比如epoll),使它能够高效处理大量连接,即便是单线程内存操作:Redis的大部分操作都是内存级别的,避免了磁盘I/O的瓶颈避免上下文切换:由于是单线程,Redis不需要频繁地在线程之间切换,......
  • Redis可视化工具Redis Desktop Manager(附安装包)
    前言redis工具,我相信每个开发都需要,如果每次查都去client执行指令,我怕查完之后,老大就要发版咯。我之前一直用的Redis可视化工具RedisDesktopManager,总觉得差点意思,直到同事推荐了个新的,突然2眼发光!!先上链接:Redis可视化工具(含我之前用的简约版,跟同事发我的新版)RedisDes......
  • Redis工具可视化工具Redis Desktop Manager(附安装包)
    前言redis工具,我相信每个开发都需要,如果每次查都去client执行指令,我怕查完之后,老大就要发版咯。我之前一直用的Redis可视化工具RedisDesktopManager,总觉得差点意思,直到同事推荐了个新的,突然2眼发光!!先上链接:Redis可视化工具RedisDesktopManager(旧版):AnotherRedisDesktopMan......
  • Redis原理篇 之数据结构
    Redis原理篇之数据结构文章目录Redis原理篇之数据结构1动态字符串SDS1.1SDS介绍1.2SDS扩容1.3SDS优点2IntSet2.1IntSet介绍2.2IntSet升级2.3总结3Dict3.1Dict的原理3.2Dict的扩容3.3Dict的收缩3.4Dict的rehash3.5总结4ZipList4.1ZipList原理4.2Zi......
  • SpringBoot集成Redis
    Redis简介:是一个开源的、使用C语言编写的、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库主要特点速度快,Redis将数据存储在内存中,因此读写速度非常快,可以达到每秒数万次甚至更高的读写操作。这使得它非常适合处理高并发的场景,如缓存、实时排行榜等。数据类......
  • 一文搞懂redis的所有知识点
    简介:整理自黑马程序员苍穹外卖项目p50-p62Redis简介Redis的下载与安装Redis安装包的目录结构redis.window.conf配置文件修改密码:Redis服务的启动也可直接双击redis-server.exe文件启动Redis客户端连接服务端Redis图形化界面三款图形化界面工具下载地址1、A......