posts - 246,comments - 26,views - 74万

前提

项目业务开发已完成,开始着手准备多节点拓展方案。

项目使用go语言开发,gin框架。

项目中使用了go原生的进程锁 sync.Mutex ,用于防止高并发下,数据可能遭到重复修改的问题。

但是用了进程锁就无法支持集群部署架构,集群中每个单点都是一个进程,只能锁住自己的一部分,而操作的又是同一个DB,高并发下就会出现数据重复修改的问题。

 

因此需要引入分布式锁,用来保证多节点部署架构下,数据正常。

 

方案选择

有多种分布式锁的方案,ZooKeeper,基于数据库实现分布式锁(for update),redis等。

鉴于项目本身面对的用户量并不多,首期预计2000人,多节点方案也只是plan B,避免上线当天出现炸服的情况,有个方案可以及时拓展节点,提高承载量,

因此最终选用了redis,简单易用,而且项目本身也部署了redis,也不影响现有的架构,毕竟多引入一个中间件,就多了其他的风险。

 

redis分布式锁应用实例

redis分布式锁,用的是其Setnx(SET if Not Exists)函数, 指定的 key 不存在时,为 key 设置指定的值。

因为redis是单线程的,因此Setnx 100%是串行执行命令, 当多个请求进来时,即使同时调用Setnx,最终是按顺序返回值,达到了锁的效果。

项目中使用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func main() {
    key := consts.USER_UPDATE + id
    op := ExistKeyOrSet(key, consts.DB_OP_EXPIRES_TIME)
 
    if !op {
    // 已存在key,表示上一次操作未结束
    appG.Response(http.StatusBadRequest, e.FREQUENT_OPERATION, nil)
    return
    }
 
    // 程序执行结束后删除 redis 存储数据
    defer rdb.DelKey(key)
}
 
 
 
func ExistKeyOrSet(key string, expiresTime time.Duration) bool {
    timestamp := time.Now().UnixNano()
    // redis的setnx方法 key存在返回false, 不存在则设置锁并返回true
    return Client.SetNX(ctx, key, timestamp, expiresTime).Val()
}

  

 

posted on   Boom__Clap  阅读(162)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
· Manus爆火,是硬核还是营销?
历史上的今天:
2017-06-14 PS制作gif动图教程
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示