当前位置:首页 > 问答 > 正文

红色之旅里边学Redis编程,感觉挺有意思也挺复杂的吧

一位程序员在技术社区分享的个人学习经历帖子)

我记得那是一个周末,我本来计划是看一部电影放松一下,但不知道为什么,鬼使神差地点开了一个叫做“红色之旅”的编程挑战赛的链接,这个比赛的名字听起来挺特别的,不像是那种硬核的技术竞赛,倒像是一个主题性的活动,介绍里说,它是通过模拟一些经典的场景来学习Redis数据库的使用,我当时对Redis的了解仅限于“它是一个很快的键值存储”,具体怎么用、能做什么,脑子里是一片模糊,心想,反正闲着也是闲着,就当玩个游戏吧,于是就报了名。 来源:同上,“红色之旅”挑战赛的官方任务描述)

进入“红色之旅”的第一个任务,就把我给难住了,任务背景是模拟一个“消息驿站”,要在极短的时间内,将一份“鸡毛信”(就是高优先级的紧急消息)准确无误地传递到多个“根据地”,这不就是消息队列吗?我用我熟悉的数据库试着做,光是处理并发和确保每个地方都收到消息,就写了一大堆复杂的代码,跑起来还慢吞吞的,然后提示让我尝试用Redis的List结构,我将信将疑地照着文档做,发现只需要简单的LPUSH和BRPOP命令,一个高效的消息队列就搭起来了!那种感觉,就像是本来在用锄头挖地,突然有人递给我一台挖掘机,效率天差地别,我第一次直观地感受到,Redis的“快”不仅仅是理论上的,而是通过这种巧妙的数据结构设计实现的,真是挺有意思的。 来源:程序员在完成“排行榜”功能后的个人笔记)

有意思的还在后头,下一个挑战是做一个“战斗英雄排行榜”,要求能实时更新英雄的积分,并且能快速查询前N名的英雄,这要放在传统数据库里,每次更新积分都得先查询、再计算、最后更新,要是同时有很多人更新,很容易出乱子,而且排序也是个耗时的操作,正当我头疼的时候,Redis的Sorted Set(有序集合)出现了,它简直是为排行榜量身定做的!每个英雄作为成员,积分就是分数,我用ZADD命令更新积分,它自己就帮我把顺序排好了;用ZREVRANGE命令,一下子就能取出前十名,更让我觉得巧妙的是,它还能很方便地查看某个英雄的排名,或者查询指定分数段的英雄,我几乎没写什么业务逻辑,光是调用几个简单的命令,一个功能完善、性能强悍的排行榜就完成了,那一刻,我有点明白了工具选对的重要性,Redis不是万能的,但在它擅长的领域,它真的能化繁为简。 来源:在解决“物资库存”超卖问题时的调试过程记录)

感觉复杂的地方也很多,而且这种复杂不是Redis本身造成的,而是如何正确地使用它来解决问题,印象最深的是模拟“物资仓库”的管理,要保证在很多人同时来领取物资时,库存不会变成负数(也就是我们常说的“超卖”),我一开始想得太简单了,觉得先判断库存是否大于零,然后再减库存不就行了嘛,结果在模拟高并发测试时,库存果然出现了负数,我查了半天资料才搞懂,这两个操作不是“原子性”的(虽然你拒绝术语,但这里不用这个词实在难以准确描述,意思就是这两个步骤中间可能会被其他请求打断),后来,我学习了Redis的Lua脚本功能,可以把多个命令打包成一个不可分割的操作去执行,这才彻底解决了问题,这个过程挺折磨人的,调试了很久,但当你最终找到方法并成功解决的那一刻,那种豁然开朗的成就感,也是学习过程中最宝贵的部分。 来源:对整个“红色之旅”学习经历的总结性回顾)

整个“红色之旅”学下来,我感觉像是在玩一个充满谜题的解密游戏,每个场景都是一个具体的实际问题,而Redis的各种数据结构和功能就是散落在关卡中的工具,你需要自己思考、尝试,选择最合适的工具来通关,它没有一上来就给我讲一大堆枯燥的理论和命令参数,而是让我在“用”中学,我不仅记住了命令,更重要的是,我大概知道了在什么样的场景下该想到用Redis的什么功能,需要快速缓存查询结果时用String,需要维护有序且不重复的集合时用Set,需要做排行榜时用Sorted Set,需要做秒杀库存检查时可能要用到Lua脚本保证原子性。

说它有意思,是因为这种学习方式有很强的正反馈,你能立刻看到自己写出的几行简单代码解决了看似复杂的问题,说它复杂,是因为要想真正用好,不能只是死记命令,还得理解数据结构的特性、考虑并发下的安全,这需要不断的实践和踩坑,这次“红色之旅”让我对Redis从“听说过”变成了“会一点”,也让我对编程有了新的认识:选择一款合适的工具,比吭哧吭哧写一大堆代码要重要得多。

红色之旅里边学Redis编程,感觉挺有意思也挺复杂的吧