分享
  1. 首页
  2. 文章

GoLang Redis存储结构体方式对比

wp_nine · · 9483 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

Redis 作为一个非关系数据库,以key-value 的方式存储数据,在后台开发时常被用于处理缓存。在golang 中的结构体的存储也是经常需要接触到,以下是几种结构体存储的方式的对比。

1.hash类型方式


func DoHashStore(conn redis.Conn) {
 //以hash类型保存
 conn.Do("hmset",redis.Args{"struct1"}.AddFlat(testStruct)...)
 //获取缓存
 value, _ := redis.Values(conn.Do("hgetall", "struct1"))
 //将values转成结构体
 object := &TestStruct{}
 redis.ScanStruct(value, object)
}

利用redis库自带的Args 和 AddFlat对结构体进行转换。然后以hash类型存储。该方式实现简单,但存在最大的问题是不支持复杂结构(如:结构体中内嵌结构体、数组等)。

2.Gob Encoding方式

 func DoGobEncodingStore(conn redis.Conn) {
 //将数据进行gob序列化
 var buffer bytes.Buffer
 ecoder := gob.NewEncoder(&buffer)
 ecoder.Encode(testStruct)
 //reids缓存数据
 conn.Do("set","struct2",buffer.Bytes())
 //redis读取缓存
 rebytes,_ := redis.Bytes(conn.Do("get","struct2"))
 //进行gob序列化
 reader := bytes.NewReader(rebytes)
 dec := gob.NewDecoder(reader)
 object := &TestStruct{}
 dec.Decode(object)
}

该方式利用gob.NewEncoder 对结构体进行,该方式可支持复杂的数据结构,但实现相对比在代码实现上稍微复杂。

3.JSON Encoding 方式

func DoJsonEncodingStore(conn redis.Conn) {
 //json序列化
 datas,_ := json.Marshal(testStruct)
 //缓存数据
 conn.Do("set","struct3",datas)
 //读取数据
 rebytes,_ := redis.Bytes(conn.Do("get","struct3"))
 //json反序列化
 object := &TestStruct{}
 json.Unmarshal(rebytes,object)
}

该方式同gob差不多,区别是将结构体转换成json格式,实现也相对简单。另外采用json序列化,在后台开发提供数据时,不一定要对数据进行json反序列化,可直接以json格式传递到前端。

测试数据


type TestStruct struct{
 Id int `redis:"id" json:"id"`
 Name string `redis:"name" json:"name"`
 Sex string `redis:"sex" json:"sex"`
 Desc string `redis:"desc" json:"desc"`
 Desc1 string `redis:"desc1" json:"desc1"`
 Desc2 string `redis:"desc2" json:"desc2"`
 Desc3 string `redis:"desc3" json:"desc3"`
 Desc4 string `redis:"desc4" json:"desc4"`
 Desc5 string `redis:"desc5" json:"desc5"`
 Desc6 string `redis:"desc6" json:"desc6"`
 Desc7 string `redis:"desc7" json:"desc7"`
 Desc8 string `redis:"desc8" json:"desc8"`
}
var testStruct = &TestStruct{
 Id:111111,
 Name:"测试姓名",
 Sex:"男",
 Desc:"描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述",
 Desc1:"描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述",
 Desc2:"描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述",
 Desc3:"描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述",
 Desc4:"描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述",
 Desc5:"描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述",
 Desc6:"描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述",
 Desc7:"描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述",
 Desc8:"描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述描述",
}

当前采用简单的结构来测试3种方式的性能,对数据进行数据以下的性能测试,代码如下:

package main
import (
 "testing"
)
var conn = ConnectRedis()
const COUNT = 10000
func BenchmarkDoHash(t *testing.B) {
 for i:=0;i<COUNT;i++{
 DoHashStore(conn)
 }
}
func BenchmarkDoEncodingStore(t *testing.B) {
 for i:=0;i<COUNT;i++ {
 DoGobEncodingStore(conn)
 }
}
func BenchmarkDoJsonEncodingStore(t *testing.B) {
 for i:=0;i<COUNT;i++ {
 DoGobEncodingStore(conn)
 }
}
/**测试服务连接
 */
func ConnectRedis() redis.Conn{
 conn,err := redis.Dial("tcp", "192.168.11.66:6379")
 if err != nil{
 fmt.Println("连接失败",err)
 return nil
 }
 return conn
}

每个方法各执行 10000次,以下是执行结果对比:

xxx$ go test -bench=. -cpu=2 -benchmem
goos: darwin
goarch: amd64
pkg: GoTest/redis
BenchmarkDoHash-2 1 10016069672 ns/op 54082696 B/op 940061 allocs/op
BenchmarkDoEncodingStore-2 1 11201448993 ns/op 190100712 B/op 3010222 allocs/op
BenchmarkDoJsonEncodingStore-2 1 11202429766 ns/op 190088256 B/op 3010040 allocs/op
PASS
ok GoTest/redis 32.430s
xxx$ go test -bench=. -cpu=2 -benchmem
goos: darwin
goarch: amd64
pkg: GoTest/redis
BenchmarkDoHash-2 1 10049184810 ns/op 54082616 B/op 940060 allocs/op
BenchmarkDoEncodingStore-2 1 11251807376 ns/op 190099496 B/op 3010218 allocs/op
BenchmarkDoJsonEncodingStore-2 1 11216203746 ns/op 190090304 B/op 3010052 allocs/op
PASS
ok GoTest/redis 32.528s
xxx$ go test -bench=. -cpu=2 -benchmem
goos: darwin
goarch: amd64
pkg: GoTest/redis
BenchmarkDoHash-2 1 10292153489 ns/op 54082616 B/op 940060 allocs/op
BenchmarkDoEncodingStore-2 1 11233160600 ns/op 190100648 B/op 3010222 allocs/op
BenchmarkDoJsonEncodingStore-2 1 11028977805 ns/op 190086304 B/op 3010031 allocs/op
PASS
ok GoTest/redis 32.567s

对比上很明显,采用hash存储方式的效率上比其它两种方式稍微快一些,并且在内存的占用上远远比两种序列化方式少很多。而其他两种序列化方式在性能上差不多。

总结:

1.hash存储方式效率最高,尤其在内存的占用上
2.hash存储方式不支持复杂结构,gob和json可直接序列化
3.gob和json序列化性能差不多,但个人推荐使用json,业务处理中json不一定需要反序列化处理,可直接传递给前端。


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:wp_nine

查看原文:GoLang Redis存储结构体方式对比

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
9483 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏