美文网首页
基于亿条数据的内存,redis两种聚合GO计算的实战思考

基于亿条数据的内存,redis两种聚合GO计算的实战思考

作者: hugoren | 来源:发表于2020-11-13 19:51 被阅读0次

总结:

(1) go 的 map读,写是线程不安全的
(2) sync.map 用空间换时间的思想,适合读多写少的场景,读,写是线程安全,但遍历是线程不安全的,运行几个小时以后,出现性能巨降的情况。刚开始18w条/分,后来1w条/分;
(3) orcaman/concurrent-map的思路是把大内存的map划分为若干小内存map
(4)后面redis替换内存后,13w条/分,开了四个goroutine

image.png

每天亿条的数据量


image.png

背景

数据经过filebeat ---->logstash--->kafka--->按一定维度聚合计算------>写入mysql---->grafana展示

聚合计算的数据结构

k, v的map内存存储
计算的数据:
最小,最大,平均,总数,成功,失败, 耗时........

内存版本

go 的 map 不加锁

type dataStruct struct {
    cost int64
}

var mapData = make(map[string]dataStruct)

func write(){
    fmt.Println("write")
    //if mapData["cost"].cost != 0 {
    //  fmt.Println("exit")
    //}
    mapData["cost"]=dataStruct{10}
}
func read(){
    fmt.Println("read")
    v := mapData["cost"]
    fmt.Println(v)
}

运行结果:死锁,说明map读,写线程是不安全的


image.png

go map 加锁

type simpleLock struct {
    mu sync.Mutex
    mapData map[string]string

}

var l simpleLock

func write(){
    fmt.Println("write")
    l.mapData = make(map[string]string)
    l.mu.Lock()
    l.mapData["cat"] = "hobb"
    l.mu.Unlock()
}
func read(){
    l.mapData = make(map[string]string)
    fmt.Println("read")
    l.mu.Lock()
    v := l.mapData["cost"]
    l.mu.Unlock()
    fmt.Println(v)

或者这样的写法

var counter = struct{
    sync.RWMutex
    m map[string]int
}{m: make(map[string]int)}

counter.RLock()
n := counter.m["some_key"]
counter.RUnlock()
fmt.Println("some_key:", n)

counter.Lock()
counter.m["some_key"]++
counter.Unlock()

运行的结果


image.png

sync.map

ar syncMap sync.Map

func write(){
    fmt.Println("write")
    syncMap.Store("hugo", "boss")
}
func read(){
    v, _ := syncMap.Load("hugo")
    fmt.Println(v)
}

运行结果


image.png

以上总结

上面的写法,适合,量少,读多写少的场景

大量的读写,还得看redis, mq

通过实践,用redis替代内存后,每分钟的数据由原来的2w条/分达到了 12w条/s。
这性能还可以再优化,通过跟踪,时间有三分之二耗在了消费kafka数据,1条/3ms


image.png
image.png

实践的结果

积压的3亿条数据经过一天的消费,只剩下条4000w数据


image.png

参考

深度解密 Go 语言之 sync.map

Golang:一文解决Map并发问题
https://cloud.tencent.com/developer/article/1539049
go 分段锁ConcurrentMap,map+读写锁,sync.map的效率测试
https://blog.csdn.net/yzf279533105/article/details/98636679

相关文章

  • 基于亿条数据的内存,redis两种聚合GO计算的实战思考

    总结: (1) go 的 map读,写是线程不安全的(2) sync.map 用空间换时间的思想,适合读多写少的场...

  • Redis-Memcached

    Redis的作者Salvatore Sanfilippo曾经对这两种基于内存的数据存储系统进行过比较: Redis...

  • Redis和Memcached的区别

    Redis的作者Salvatore Sanfilippo曾经对这两种基于内存的数据存储系统进行过比较: Redis...

  • Redis-认识

    什么是Redis 基于键值对的内存数据库。 Redis 的优势 基于内存,所以数据读写快。所有数据都存放在内存中底...

  • Redis持久化之RDB和AOF

    Redis是基于内存的数据库,为了保证数据的可用性Redis提供了两种数据持久化机制:RDB和AOF。这里来介绍一...

  • Spring Security结合Redis实现缓存功能

    Redis Redis是一个开源的,基于内存的数据结构存储,可用作于数据库、缓存、消息中间件。 Redis基于内存...

  • redis

    redis数据库,完全基于内存,且其内部数据类型丰富,性能也非常出色redis中的集合插入分zet和set两种,z...

  • 2018-04-19redis

    初始redis:redis是远程的redis是基于内存的(数据+结构)redis是非关系型数据库redis的应用场...

  • 【redis】Redis 分析工具 redis-rdb-tool

    一、简介 redis是基于内存的kv数据库,内存作为存储介质,关注内存的使用情况是一个重要的指标。 解析内存有两种...

  • Spark简介以及架构

    Spark是什么?Spark是基于内存计算的大数据并行计算框架.Spark基于内存计算,提高了在大数据环境下数据处...

网友评论

      本文标题:基于亿条数据的内存,redis两种聚合GO计算的实战思考

      本文链接:https://www.haomeiwen.com/subject/ankybktx.html