前言

相信大家都有过抢票、刷票的经验,每年年底,这都是一场盛宴。

然而,你有没有想过12306的抢票算法是怎么实现的呢?

没有吧,想过,还是没有头绪?

今天,我们就来曝光让人又爱又恨的12306是如何实现抢票的。

位运算回顾

我们知道计算机只能识别0和1,要操作这些0和1,只能通过位运算来进行,那么,一共有几种位运算呢?

让我们来回顾一下:

运算符号举例结果与& 1101
& 01100100或| 1101
& 01101111异或^ 1101
^ 01101011取反~11010010左移<<1101 << 111010带符号右移>>1101 >> 11110不带符号右移>>>1101>>>10110

以上位运算以Java为例,其他语言中可能没有 >>> 操作。

OK,位运算的简单回顾就到这里,还有不懂的同学可以自行百度一下。

位图

虽然大部分语言都有提供位运算,但是,并没有提供一种类似于位数组的类型,要使用这些位运算,我们只能通过数字类型来实现,比如Java中的int/long等类型。

而这些数字类型的数组,我们一般可以称之为“位图”(BitMap)。

比如,我们需要使用128位的内存,可以申请包含两个long类型的数组long[] bitmap = new long[2];。

不过,位图有什么用呢?

有大用处哦,比如,我们要统计某个用户一年的活跃度,就可以使用位图来实现。

一年有365天,一个long类型可以表示64位,365/64=6,只需要6个long类型就可以记录一个用户一年的活跃情况,怎么记录呢?

很简单,初始时,位图中所有位都是0,当这个用户某天登录了,就在位图中找到这天,把其位变成1,一年下来,这张位图就记录了这个用户哪些天登录了,统计这个位图中1的数量,除以365,就得到了他的活跃度。

OK,这只是位图的一个很简单的用法,位图还有很多高级的用法,比如统计活跃用户数、限流、权限控制等,当然,还有我们今天要曝光的12306抢票算法。

12306抢票算法

我们知道,一列火车,有很多个座位,可以到很多站,以北京到广州的一列火车G67为例:

G67次列车一共有18个站,有的人可能到武汉就下车了,有的人可能到长沙下车,还有的人可能从武汉上车从衡山西下车,甚至还有的人从北京一直坐到广州,我们假设这趟列车一共有200个座位。

那么,如何实现合理的抢票策略,才能保证这趟列车能够坐最多的人?(没有站票)

什么叫做“坐最多的人”呢?假设针对10号位置,一个人从北京到武汉,另一个人从武汉到长沙,再一个人从长沙到广州,那针对这个位置全程可以坐3个人;针对另一个位置,一个人从北京到广州,那这个位置全程只能坐一个人。简单点说,就是针对一个特定的位置,两个人之间不能有交集,比如一个人从北京到长沙,另一个人从武汉到广州,那这两个人不能安排到同一个位置上。

OK,先给你一分钟时间思考一下,先别急着往下看哦。

好了,一分钟时间已到,让我们继续。

首先,让我们回顾下G67这趟列车的信息:一共18个站,一共200个座位。

为了方便讲解和画图,我们假设它只有 北京、信阳、武汉、岳阳、长沙、广州 6个站,一共有8个座位。

针对这样的信息,我们可以这样来实现抢票策略:

1.创建5个位图,每个位图的大小为8位,初始时,每个位的值都是0。为什么是5个位图呢?因为到站就下车了,而广州站是终点站,到站全部人都得下车。比如,一个人从北京到武汉,他到武汉就下车了,所以,它不会占用武汉的位置。

2.把抢票逻辑放在单线程中来处理,单线程的好处是不用考虑并发问题,没有CPU上下文切换的问题等,而且整个操作都是CPU操作,速度很快,使用单线程效率更高。当然,我们还有更好的选择——Redis,Redis本身就是单线程处理的,而且它天然支持BitMap,速度又快又好,有兴趣的同学可以了解一下Redis中的BitMap。

3.假设第一个人的请求过来了,他要抢从北京到武汉的票,此时,我们只需要把北京和信阳两个位图做“与”运算,结果中,所有0的位置都表示可抢的位置,在这些位置中随机返回一个即可,并把此位置在北京和信阳这两个位图中标记为1,表示此位置在北京和信阳有人占用了。(武汉为什么不参与运算了,前面讲过了,这个人到武汉就下车了。)假设,此人最后的座位是2号,那么运算之后,各位图的情况如下:

4.接着,第二个人的请求过来了,假设他要从信阳到长沙,此时,需要把信阳、武汉和岳阳三个位图做“与”运算:假设,此人最后的座位是4号,那么,运算之后,各位图的情况如下:

5.然后,第三个人的请求来了,假设他要从北京到广州,此时,把所有5个位图做“与”运算:假设,此人最后的座位是1号位,那么,运算之后,各位图的情况如下:

6.OK,经过了多个人的请求之后,假设位图的情况变成了下面这样:请思考,此时,还能抢到从北京到广州的票吗?能?不能?回答能的同学,请从头再看一遍
好了,关于抢票算法我们就介绍到这里,你有没有Get到呢?或者你有没有更好的实现方法呢?

后记

本节,我们一起重温了位运算的操作,并学习了如何使用位图实现12306的抢票算法,关于位图,其实还有很多用途,比如,各种统计、限流、权限控制等。

收到最新情报:所有的递归都可以改写成非递归,怎么实现呢?有没有什么套路呢?下一节,我们一起来聊下这个话题。

原文链接:彤哥读源码

全网首发:12306抢票算法大曝光?(十张图搞定)相关推荐

  1. 12306抢票算法居然被曝光了,居然这么简单

    导读 相信大家应该都有抢火车票的经验,每年年底,这都是一场盛宴.然而你有没有想过抢火车票这个算法是怎么实现的呢? 应该没有吧,咱们今天就来一一探讨.其实并没有你想的那么难 bitmap与位运算 red ...

  2. 12306抢票算法居然被曝光了!!!居然是redis实现的

    开发者(KaiFaX) 面向全栈工程师的开发者 专注于前端.Java/Python/Go/PHP的技术社区 导读 相信大家应该都有抢火车票的经验,每年年底,这都是一场盛宴.然而你有没有想过抢火车票这个 ...

  3. 【数据结构与算法】7.位图算法、12306抢票算法

    前言 本文收录于专辑:http://dwz.win/HjK,点击解锁更多数据结构与算法的知识. 你好,我是彤哥,一个每天爬二十六层楼还不忘读源码的硬核男人. 相信大家都有过抢票.刷票的经验,每年年底, ...

  4. 12306 抢票,极限并发带来的思考

    点击上方"蓝色字体",选择"置顶或者星标" 你关注的就是我关心的! 来源:https://juejin.im/post/5d84e21f6fb9a06ac824 ...

  5. 同为高并发,微博热搜、天猫秒杀、12306 抢票有什么不同?

    同为高并发,微博热搜.天猫秒杀.12306 抢票有什么不同呢? 那接下来我们就来分别聊聊他们有什么特性~ 1.微博热搜 「微博热搜」是一个典型的读多写少场景,读今日的热点新闻,写自己的微博评论. 作为 ...

  6. 12306抢票插件拖垮GitHub

    本文是作者在2013-01-16发布的一篇内容,搬来测试用:https://www.csdn.net/article/a/2813696 摘要:每逢佳节抢票难,这不,12306的一个抢票插件竟拖垮Gi ...

  7. 12306抢票带来的启示:看我如何用Go实现百万QPS的秒杀系统

    本文为开源实验性工程:"github.com/GuoZhaoran/spikeSystem"的配套文章,原作者:"绘你一世倾城",现为:猎豹移动php开发工程师 ...

  8. 如何定制一款12306抢票浏览器——完结篇

    差不多花了一个星期的业余时间去完成了相关的编码.最后也只是使用了5篇文章将整个大题流程和使用的关键技术介绍了一下.其中有很多酸甜苦辣,其中记忆最为深刻的就是我对图像做了处理后,tesseract-oc ...

  9. 如何定制一款12306抢票浏览器——构架

    快春节了,火车票一票难求.虽然黄牛市场冷淡了,但是互联网"娱乐界"却越来越闹腾了.先是猎豹等浏览器推出抢票专版(插件),然后是铁道部约谈金山,之后流传工信部叫停抢票插件,之后再是工 ...

  10. 分享12306抢票心得-终极秒杀思路篇

    12306抢票的关键拼的就是整点出票的速度,快的几秒钟,慢的几分钟,本文提供终极抢票攻略,通过多线程扫描上万个CDN,来大幅度提升出票速度. 准备一:需要了解CDN和切站的机制,请参考: 分享1230 ...

最新文章

  1. java中单例实现常用的方式_Java单例的常见形式
  2. Cassandra使用的各种策略
  3. hbuilder打包的app如何设置自动清理缓存_手机空间不足,这些“隐形”文件如何找到删除?...
  4. Python中的strip()函数的用法
  5. 利用三层交换机实现VLAN间路由配置
  6. 日期getUTCMonth()方法以及JavaScript中的示例
  7. LINUX考证优惠信息转发(图)
  8. 红旗linux培训文档,Linux基本应用培训-红旗Linux.ppt
  9. python3.6sysos_python3.6实现学生信息管理系统
  10. Wheel ProgressBar 实现之三——模拟进度过程
  11. Spring入门之bean的配置
  12. 大白菜装机教程win10_大白菜U盘启动工具|大白菜超级U盘启动制作工具 V6.0_2009.25官方版下载...
  13. linux聊天室项目课程设计,网络编程课程设计报告--基于linux网络聊天室设计.docx...
  14. Windows下进行域名映射并配置Nginx反向代理
  15. 存储、读取、清除cookies数据
  16. php sybase存储过,SYBASE存储过程详解
  17. pip install 命令报错Temporary failure in name resolution
  18. Basemap库绘制地图
  19. Head First Java资源
  20. [附源码]Node.js计算机毕业设计高校运动会管理系统 Express

热门文章

  1. freenom 申请免费域名
  2. Java培训后如何找工作?
  3. python抓取网站访客手机号_网站获取访客QQ系统
  4. 图床:使用新浪微博相册
  5. 浅论cherry机械键盘与其在war3中的表现
  6. pdo mysql 函数_PDO函数属性详解
  7. [BZOJ3993]-[SDOI2015]星际战争-二分答案+最大流
  8. windows7计算机或资源管理器窗口,win7系统资源管理器(文件夹)总是在新窗口打开的解决方法...
  9. 详解电源反接使用MOS管保护电路原理及其优势
  10. office办公软件之ppt视频录制