• 项目中使用进程内缓存的一些经验及注意事项


    前言

      对于项目中一些比较简单的功能,比如在项目启动的时候将简单的userId与configId的对应关系存放的缓存从而减少RDS中的IO操作,这种简单的应用场景我们可以使用进程缓存来代替redis达到同样的效果。

      本文分享一下进程内缓存的使用以及存在的问题分析。

    直接使用全局变量的方法

      使用进程内缓存最简单的方式就是定义一个全局的变量,在项目启动的生命周期内将数据存放在这个全局变量下即可:

    var globalMap map[string]interface{}

    并发情况下使用sync.Map

      在并发情况下,多个goroutine同时操作golang原生的map会出现竞争条件(race condition)问题。

      如果需求是要将进程内缓存存放在一个map中,并且项目会遇到多个goroutine同时操作这个map的情况,最简单的可以使用golang内置的sync.Map去替代原生的map,可以避免race condition问题。

      关于sync.Map的操作可以参考这篇文章:go sync.Map使用和介绍

    使用go-cache第三方包

      有一个很好用的第三方包go-cache它也实现了进程内缓存,并且使用加锁的方式确保了多goroutine下的并发安全(看一下源码就知道了,对外暴露的方法都有加锁的操作)。

      项目地址如下:patrickmn/go-cache

      说明文档如下:go-cache包说明文档

      自己做了一下简单的练习:

    package test1
    
    import (
        "fmt"
        "github.com/patrickmn/go-cache"
        "testing"
    )
    
    func TestInnerProcessCache(t *testing.T) {
        // 永久生效,除非重启服务
        cacheBaby := cache.New(0, 0)
        cacheBaby.Set("name", "whw", 0)
    
        if name, ok := cacheBaby.Get("name"); ok {
            fmt.Println("name: ", name)
        } else {
            fmt.Println("nothing...")
        }
    
    }

    进程缓存存在的问题

      这里先引用一下上面介绍的go-cache包的一个介绍(这个作者还是十分严谨的):

    多台机器做负载均衡存在的缓存同步问题    

      设想一下,如果我们的项目部署在了多台服务器上做负载均衡,像下面这样:

      那么问题就来了,项目启动时在后面2台EC2中分别存了一份缓存数据,如果其中一个EC2的缓存数据更新了,对于数据实时性要求特别高的服务来说如何“瞬间”将这个改动同步到另外一台机器上是一个很棘手的问题(即时使用MQ这样的订阅功能也会存在网络传输的时延)。  

      所以对于数据实时性要求特别高的服务,并且服务器也做了负载均衡,如果业务中有需要对缓存更新的操作的话,笔者不建议使用进程内缓存作为缓存数据的方式,推荐使用像redis这样的第三方服务去做。

      当然如果只是将一些固定的数据作为缓存的话,并且数据的更新依赖于项目重启,那么这种场景下使用进程内缓存还是十分方便的。

    进程缓存的其他使用场景

      之前在做项目的时候有用到一个自定制的LRU cache的包,挺不错的:使用golang实现一个LRU进程缓存模块

    参考文章

    go-cache包说明文档 

    go sync.Map使用和介绍

    进程内缓存,究竟怎么玩?

  • 相关阅读:
    navicat设置唯一
    H5图片防盗链处理
    jar包更新
    微信小程序开发工具“当前系统代理不是安全代理”
    Set和Map
    OSS先后上传相同地址的图片
    js遍历删除数组中不符合条件的元素
    SSL配置
    关于socket.io获取客户端真实IP地址
    请在微信客户端打开链接 html
  • 原文地址:https://www.cnblogs.com/paulwhw/p/14639979.html
Copyright © 2020-2023  润新知