从内到外:深入选课系统的全面性能优化

能学到什么

  • 优化角度

  • redis的bitMap的使用

如何优化

这期我们主要对选课/退课业务逻辑进行优化与封装,至于其他优化请见后期。

  1. 优化一

在前期的话我们都是通过加锁从数据库读取用户的flag字段和读取课程的时间段,虽然这样的话不会出现什么问题,如果涉及到同一个用户并发的访问和修改flag字段时这就会涉及到锁的互斥了。其实我们只是想通过flag字段去记录某个用户某个时间段的选课记录。这么想一下创建用户的课程都能放入到redis里去操作,那修改用户的flag字段是不是也可以在redis进行操作呢?

 

go

复制代码

if err := database.Client.WithContext(ctx).Transaction(func(tx *gorm.DB) error { // 1. 获取课程的week和duration,这里完全可以通过map读取的。从而进一步减数少对db的访问 var course models.Course if err := tx.Model(&models.Course{}).Preload("Schedule").First(&course, req.CourseID).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return err } return err } // 2. 获取用户的flag字段 var user models.User // if err := tx.Clauses(clause.Locking{Strength: "SHARE"}).Where("id = ?", req.UserID).First(&user).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return err } return err } offset := int(course.Schedule.Week*3) + int(course.Schedule.Duration) if user.Flag.TestBit(offset) { resp.Fail(ctx, code.Fail, code.CourseSelected, code.CourseSelectedMsg) return errors.New("用户已经选过该课程") } // 4. 修改用户flag user.Flag.SetBit(offset) if err := tx.Save(&user).Error; err != nil { return err } return nil })

方案一

我们可以把每个课程的时间段分别放入到对应时间段的时间里,如果选的课程对应的集合和用户已选的课程存在交集的话,那么就存在时间冲突了,这样的话我们无需通过修改user表的flag字段也能进行操作,避免了直接对数据库层操作,而是内存层面上的计算。

暂时无法在飞书文档外展示此内容

image.png

 虽

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值