Mysql有序集合实现的数据结构_redis的有序集合实现一个高效订单排队后台

假设我们手上有这么一个需求:

* 接受用户的订单数据,但因为订单处理需要一定的时间,所以只能后台先保存订单数据,对用户进行排队操作。当然这个排队操作,用户是不透明的,某些用户的请求可能被优先处理。

* 用户很关心自己订单目前的处理进度,即类似去银行排队拿号的时候,小票上显示“你前面还有多少人在排队”。所以后台要能告知用户目前他的订单进度。

* 能给用户或者产品经理显示目前正在排队的订单数有多少。这样才能让用户知道我们的业务多么的有市场。

## 一、需求分析

* 需求1可以理解为写操作,需要后端存储数据。

* 需求2,需求3可以理解为读操作,而且可以预见这个读操作应该比写操作频繁。如果用户很关注她的订单进展,说不定会一直刷新查看他的订单排队情况。

## 二、实现方案 — MySQL

用户的订单数据肯定得持久化存储,MySQL是一个不错的选择。既然需求这么简单,无非一个订单数据嘛。暂且用一张表“订单表(T\_Order)”来保存正在排队的订单,已经处理完毕的订单则从T\_Order表迁移至“(历史订单表T\_History\_Order)”。这样的好处避免订单表数据量太大,提高读写性能。

1.需求1完成订单的入库,显然就是一个insert语句了,类似:

~~~

insert into T_Order(...) values(...);

~~~

2.需求2查询自己订单的排队情况,那肯定看比自己订单时间还早的用户有多少人了。这些比自己下单时间还早的人,就是排在自己前面的人了。假设一个用户同时只能有一个订单在排队。

~~~

#先查出自己订单时间, 假设是1429389316

select orderTime from T_Order where uid=8888;

#再查有多少人的订单时间比自己的早

select count(orderTime) from T_Order where orderTime <= 1429389316;

#先查出自己订单时间, 假设是1429389316

select orderTime from T_Order where uid=8888;

#再查有多少人的订单时间比自己的早

select count(orderTime) from T_Order where orderTime <= 1429389316;

~~~

3.需求3查询所有的订单数,显然就是一个select语句了,类似:

~~~

select count(1) from T_Order;

~~~

## 三、遇到问题

互联网的精髓就是“小步快跑,快速迭代”。用MySQL快速完成需求,面向用户服务后。初期阶段,一切ok。但是当这个业务运营得好,用户量大的时候,就会发现用户经常投诉“我查询自己的订单排队进度,经常报错”。甚至处理订单的同事,也经常抱怨从订单系统里面查看订单,非常缓慢。select count 操作基本都是全表扫描操作,看来MySQL面对这么大规模的全表查询操作,还是有点吃力。

## 四、解决查询性能问题

NoSQL在互联网领域的江湖地位已经很牢靠了,看来得请他老人家出来救场了。没错,使用Redis的有序集合(sorted sets)数据结构,就可以完美的解决这个问题。因为有序集合底层的实现是跳表这种数据结构,时间复杂度是logN,即使有序集合里面的订单有100万之多,耗时也基本都是纳秒级别(基本不到1毫秒)。

【注意】有序集合有另外一种底层实现—-压缩列表。不过要求是,有序集合的元素个数小于128。这对于一个庞大的订单后台,元素个数绝对不仅仅128。

假设我们在的有序集合名字就叫做:task,那么:

1、用户提交一个订单,除了持久化到MySQL之外,我们再异步的写入redis中。比如用户uid=8888在1429389316这个时间点提交了一个订单,那么就往redis有序集合里面添加这个订单。

~~~

127.0.0.1:6379> zadd task 1429389316 8888

(integer) 1

~~~

2、用户要查询自己的订单排队情况,这时候我们只要查询redis的有序集合就可以了。命令为rank:

(为了方便演示,在8888用户之前,我们假设8885,8886,8887这3个用户已经提交了订单,而8889是在8888后提交的订单。)

~~~

127.0.0.1:6379> zadd task 1429389316 8888

(integer) 1

127.0.0.1:6379> zadd task 1429389310 8887

(integer) 1

127.0.0.1:6379> zadd task 1429389309 8886

(integer) 1

127.0.0.1:6379> zadd task 1429389308 8885

(integer) 1

127.0.0.1:6379> zadd task 1429389326 8889

(integer) 1

127.0.0.1:6379> zrank task 8888

(integer) 3

127.0.0.1:6379>

~~~

可见,仅仅通过一个rank命令就可以准确的反映出用户订单的排队情况。时间复杂度为logN。

3、查询目前有多少正在排队的订单。这个就更简单了,直接一个zcard命令就可以了。而且时间复杂度是O(1),因为redis的跳表本身已经存储有这个数据了,直接取出即可!

~~~

127.0.0.1:6379> zcard task

(integer) 5

127.0.0.1:6379>

~~~

4、当这个订单被处理完成后,直接一个zrem命令将订单从有序集合中删除即可。时间复杂度为logN。

~~~

127.0.0.1:6379> zrange task 0 -1

1) "8885"

2) "8886"

3) "8887"

4) "8888"

5) "8889"

127.0.0.1:6379> zrem task 8888

(integer) 1

127.0.0.1:6379> zrange task 0 -1

1) "8885"

2) "8886"

3) "8887"

4) "8889"

127.0.0.1:6379>

~~~

因为Redis基本都是内存操作,而且有序集合的底层实现是跳表这种效率媲美平衡树,但是实现又简单的数据结构,从而完美的释放了MySQL的读压力。

五、redis之跳表

既然redis的有序集合这么给力的解决了我们的问题,那我们很有必要记住redis为我们做了什么,简单分析一下redis是如何通过跳表这种数据结构,通过zadd,zrank,zcard,zrem来满足我们的需求的!

作者:nickbi

链接:https://www.jianshu.com/p/2d5cf0a6da1b

來源:简书

简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值