2016年1月份,我们的产品上线版已经是1.1.0,开发版已经做到1.2.0。这些版本之间除了UI上做了一些改动(可以在我的产品分类文章里看到我为什么会做这些改动),大部分是些底层的优化,比如App端缓存架构的修改,后台Server的API优化等等。第一个阶段的产品规划此时已经进入一个相对平缓的时期,这个平缓不是说产品做完了,而是说产品从无到有(0到1)之后,进入2(大需求改动)之前一个节奏相对平衡的时期。在这个时候,我终于开始腾出手来重点关注一个一直悬而未决的需求——线上竞价。

注:本文里竞价和拍卖代表一个概念。这里的竞价指的是传统意义上的拍卖的线上版本,不是指像某些SP商提供的线上广告位自动竞价系统。两者有一定区别。

线上竞价这个概念,在有淘宝的今天,已经不是什么新鲜事了。但是亲手做一个完全模拟线下拍卖流程的在线竞价系统,这样的需求不会很多。这对我们团队对于我个人来说,即是一个机会也是一个挑战。

好,怎么做呢?首先看看能不能借用别人的轮子,能不重复造当然不要自己造。可是在网上搜索一大圈,几天下来,能用的资料寥寥无几。可能是一个竞价系统太简单了,做的人都不屑于不好意思写下来;又或者是做的人实在是太少了,都没来得及写;也可能是凡是做竞价的都是商业需要,不能写;还有可能我搜索技术太烂,找不到。不管怎样,看起来我们又是得从零做起,而且我得写点什么,好歹将来一无是处的时候给自己的子孙吹个NB说,“你爷爷曾经做过竞价系统!”“啥破玩意?…”“……”

从头做,还是得分几步:

1. 首先要熟悉拍卖本身,至少得先懂;没有太多的时间让我一点点的完全熟悉拍卖这个市场,于是我拉上运营部门里做过真实拍卖交易的人,不断聊天了解概念,然后又亲自和他们参加了几场真实的现场拍卖会,首先对真实线下情况混个八九成熟;

2. 分析竞品,了解别人都做了什么;拉上UI设计师一起,测试机器上装上4,5个有相同功能的App,我们两个人一起分析每一个页面里的内容和操作流程,互相讨论;

3. 根据竞品和我们的实际需求,整理出基本的数据模型;在这个过程中,需要非常多得取舍决策,因为一个完整的线下拍卖有太多的概念可以抽象到数据,哪些真的需要用在产品里,哪些不重要,这个完全考察的是经验和理解决策力;

4. 根据线下规则,竞品常态和我们的实际需求,设计我们自己的业务流程;这部分,有时间的话,我想在产品分类文章里分享下我是怎么设计我们的竞价产品的;

5. 根据流程,设计系统架构。

6. 根据架构原型实现中遇到的问题,优化细节。

下文将着重讨论5,6这两部分。

一、竞价的系统架构

我们来看下常规状态下,一个线下拍卖的核心模式。拍卖,简单来说,就是一个人吆喝卖,多个人抢着买,在卖的人规定的条件下(一般为时间限制),出价最高者得。好,那么整体模式可以概括成下面这张图:

那我现在把这张图,变化一下,只保留他们之间传递的信息,再看一下:

这像什么?对了,聊天室。整个拍卖过程在结构上本质上就是一个群聊。只不过,普通的聊天室的实现,服务器端只是单纯的广播消息,客户端只是单纯的收发消息;而竞价系统,服务器端除了负责广播消息之外,还需要对每一条消息进行判定,并在最终聊天室关闭时(也就是竞价结束时)对所有消息进行一次综合判定,而各个不同客户端发出的消息时,互相之间有依赖关系(后一次出价必定在前一次基础之上)。

这样做起来思路就相对清晰了:两大模块:聊天系统+判定逻辑。

俗话说,条条大路通罗马。同样的需求,做起来有不同的方法,只是不同的方法最后的效果可能不同。同样是做巧克力,Teuscher的手工巧克力就是比超市里卖的廉价巧克力口感好,卖的价格高。就看具体的要求标准是什么。同理,做一个聊天系统,可以是实时系统,也可以是一个非实时系统;可以用长连接,也可以用短连接;可以用轮询驱动,也可以用事件驱动。关键看需求标准。

那么,回到我们的产品。最深层次的需求是:

  • 客户端能发起出价请求;
  • 当价格更新时,所有参与出价的客户端能够看到最新价格;
  • 系统功能要求远高于性能要求;
  • 开发周期紧。

摆在我们面前的,最明显的有2种做法:

1) 非实时的polling:

所有客户端的页面定时向服务器发起更新请求,拉取最新价格和出价历史列表。

2) 实时事件驱动:

所有价格更新以事件方式主动更新到每一个激活客户端。

两种方式优劣对比:

  非实时Polling 实时事件驱动
优势

简单。

后台系统只需要设计最基本的REST接口即可,前端只需要增加一个定时刷新机制即可;

和已有Web系统的扩展方法保持一致。

实时;用户体验好。

系统压力线性稳定,系统吞吐率高;

长连接,可以基于事件做更多实时性效果。

劣势

定时间隔直接影响用户体验和系统压力:

增加定时间隔,用户的基于过期的价格上而发出失效出价的概率增大;

缩短定时间隔,在竞价人数较少时将造成大量服务器无谓的请求;

而在竞价人数较多时又会造成服务器的压力成倍数增大。

需要一个区别于已有Web系统的支持长连接的事件驱动的系统框架

到这肯定有人会有这样的问题:聊天系统想都不用想——很自然的应当选择第二种直接上Node.js+socket.io啊。可是,我做任何设计,总是喜欢考虑这些问题:

我是不是非得用这种技术,是否有其他更快的方法,“杀鸡要不要用牛刀”,“我是不是只有一把刀”……

那么落到手头的实际项目,我要考虑的是:

  • 不能直接使用Node.js操作数据库,因为Node的ORM和系统的Django ORM不匹配
  • 必须尽可能复用已有系统架构,在最短时间内完成功能
  • 必须顾及竞价系统可能存在的复杂功能的要求
  • 用户体验优先级最高

这些东西已考虑下来,最终就形成了现在的系统方案,方案1)和方案2)的结合:

我们利用原有系统架构(图中右下部框内部分),使用Redis作为桥梁,直接让Node服务器连接在Django服务器:

1)Node服务器负责维护WebSocket连接并且广播消息,通知客户端实时更新价格;

2)Django服务器负责响应出价POST请求,直接操作数据库;然后通知Node服务器更新事件;

这样,我们做出的权衡就是:

  • 舍弃Node的高并发的能力,把系统压力仍然嫁接在已有Server之上;
  • 利用Node对WebSocket的优秀支持,提升用户的实时体验;
  • 复杂度上,增加客户端(Web和App)支持WebSocket的能力,但是利用Redis队列润滑系统整体框架,复用已有系统的处理逻辑和方式。

二、细节的打磨

上面提到的是竞价基础架构的设计思路,那么想要把一个聊天系统真正的变成一个竞价系统,还得靠消息判定逻辑。

原本来说,来一个出价POST请求,通过App Server判断价格是否生效,生效修改数据库并通知,失效则拒绝。多个请求到来时,FIFO排队,或者数据加锁。

很简单,和普通的Web请求读写思路没有太大区别。但是竞价系统在这里有一个不得不去考虑的特殊需求:代理出价。

在这里需要解释一下代理出价:代理出价就是“替你出价,当你不在场的时候”。相当于一个自动机器人,每当别人的报价高于自己的报价则在价格到达自己限定的最高上限之前都会自动加价后报价。比如,某件商品起拍价1000,加价幅度为100,我设定的代理出价额度为2000,那么只要价格低于2000,你无论出价多少,我都会自动比你高100出价。你出1100,我出1200,你出1300,我出1400……这个过程中,我不必在线出价,系统自动帮我出价。

那这个代理出价的需求会带来哪些新的问题:

1) 惊群效应:在有多个代理人的情况下,因为自动竞争,价格会在最短时间内上升到最高上限。比如有3个人都设置了代理出价,分别设定最高限额是M1,M2,M3。那么一旦竞价开始价格将飚升至Max(Mi)。那么,系统要不要控制这个过程?

2) 如果M1=M2=M3,最终获胜的应该是谁?

3) 如果把系统自动出价的行为看做是一个后台的机器人,那么这个机器人的“地位”如何?是把每一个设置代理出价的用户都看做是单独的机器人独立出价,还是由一位机器人统一负责协调所有的代理出价?

其中,前2个问题是需求策略问题,最后一个是技术实现问题。

关于惊群的问题,首先来看从产品的角度要不要“刻意”控制:系统刻意延缓这个“互相抬价”的过程,还是放任让价格在很短的时间内的飙涨到代理人群中的最高出价。开发人员在第一版的设计里,是考虑了“用户体验”,加入了一个定时机制,刻意延缓了整个代理“互相出价”的进程,这样还能让手动出价的用户能够在代理竞争出价的“间隙”里也能有机会出价,即时这个价格并没有竞争力。理由是:这样看起来更像是大家坐在一起互相出价,不然看起来“很假”。由于做这个设计的时候我正好休假,所以开发人员并没有和我沟通就直接把代码写完了。我回来以后,我的第一反应是很开心,因为至少说明团队的开发人员能“主动思考用户体验”,而且证明他做的很快,想到方案并快速原型实现是必须的。但是,我习惯性的问了自己一个问题:“真的有必要让它看起来不那么假么?用户真的在意出价过程中如果出现多个代理出价的情形,自己还必须要有机会出价么?”。要回答这个问题,我们退一步,退回到线下拍卖的真实场景中:

现实拍卖中,拍卖公司或者组织者会给每一个有代理出价需求的客户提前安排好专门的出价代表,并和现场其他到场客户坐在一起举牌。线上“惊群效应”其实就是现实场景中,这些代表们争先恐后的举到自己代理的客户承受的最高价才能力保客户最大可能获得最终胜利。那么在这个过程中,现场其他的客户很有可能没有机会来的及举牌,会在意么?我看不会,为什么,因为竞价不是“享受过程”,而是“获得结果”!你们在争相举牌,我没机会,但是我无所谓,因为当代理举牌完毕后,只可能有两种结果:当前价格我还能再加,或者当前价格已经超过我的预期。那么这两种情况都不会降低我的体验,我想加我就等你们消停了我再举牌,这个时候只要你们代理不修改代理价格,你们就都不是我的竞争对手了;而如果当前哄抬的价格已经超过我的心理价位,前面我有没有举过牌对我来说显然一点意义都没有,反正我肯定是拿不到这个拍品了。所以,我问开发“把这个定时器拿掉对你的代码有多大改动?”“不大”“好,拿掉。不需要增加额外复杂度。”

所以这里我的权衡是:即使让开发翻工(当然是在可以接受的范围内),也必须去掉过度的“结构设计”。

第二个问题,理解好线下拍卖对这个问题的处理方式就比较好办。线下的方法是:“拍卖师说的算!”其实就是说,系统保留所有解释权。那就好办了,自己定义了一个规则就可以。

关于第三个问题,字面上不太好理解,我们来看一个图:

这就是描述第一种情况中的“机器人是作为独立出价人单独出价”,指的就是系统并不对代理出价者做特殊处理,每一个代理在接收到价格更新事件后都可以直接对竞价系统发起出价请求。这种设计优劣如下:

  • 优点:系统功能角色划分清晰,每个代理可以享有独立出价权,更接近真实拍卖场景;
  • 缺点:因为每个代理都可以接收到更新事件,每个代理都可以发出新的出价请求,而这些出价请求又会被其他代理收到,再响应出新的出价请求。所以必须额外增加一个机制,防止多个代理循环出价带来监听的“竞价事件”爆发问题。

我们再来看看第二种可能的设计:

在这里,所有的代理出价者被纳入内部的“Coordination System”中,而不再和外部的手动出价人并列。当任何一个出价事件发生时,首先由这个“Coordinator”在众多代理出价者中协调出一个最终胜者,然后再向竞价服务器发出一个最终竞价请求。Coordinator选出唯一胜者的同时,也把所有其他的代理给淘汰掉了。也就是说,只需要1次出价,就能够把所有可能的代理者全部“洗清”,只剩一个最高代理者和其他手动出价人竞争。在这个“协调”过程中,忽略所有其他手动出价。这种设计优劣如下:

  • 优点:系统实现清晰简单,不会产生“惊群”问题;
  • 缺点:系统逻辑和真实场景有直观上的差距;

这两种都有明显的优缺点,从模拟真实线下逻辑来说,第一种更优,理解起来也更容易;而从系统结构实现角度来说,我更喜欢第二种,做起来更直接更简单。你会问我第二种的话,如果用户体验很差怎么办?其实这种场景,用户体验差只有一种情况,就是很多人真实在线出价,同时有大量的人设置了代理出价。而这种情况对于我们目前的业务而言,显然遥不可及。更何况,如果真的是这种大规模并发的场景,整个系统结构都可能要做调整了。虽然我个人倾向第二种但是我们线上版本用的是第一种,因为……在我休假期间我们NB的开发把第一种做完了!(摊手)。最后想来好像应该怪我应该提前把设计提前讨论到这层再交给开发,但是仔细想想,以目前的情况看,这两种并不会对产品本身有本质影响。所以既然已经做完了,那就先用。

至于使用第一种设计,我们额外设计了附加的措施来解决具体的“惊群”问题:

因为我们是使用遍历列表的方式扫描所有的出价代理的,那么当某个代理成功发起出价请求后,在本次扫描循环周期内,后续的代理不再出价,而只是扫描其设置的封顶价格是否失效,是则忽略,否则从列表中移除。而当每个代理接收到价格更新事件时,首先确认此次出价是否为本人,是则忽略此次更新,否则继续发起出价事件。

三、总结

本文主要记录的是我在做产品的竞价功能的前后遇到的问题和设计思路。我个人认为,这是一个很好的关于产品需求和架构设计之间互相权衡乃至制衡的例子。做互联网产品的架构师,不能只是掉在架构的黑洞里钻研架构本身,而是应该千方百计的用最合理的架构用最快的时间去满足产品的功能。我一直认为,做产品和做架构本身是不应该分离的,我坚持认为研发出身的人如果去能做产品,应该比其他人更有优势,至少在产品本身的实现上,更有说服力更有效。当然,关于市场和运营本身的能力也是至关重要,但那是另外的话题了。

2016年2月25日,完稿于南京。

转载于:https://www.cnblogs.com/wizardguy/p/how-to-design-a-auction-system.html

架构和产品的制衡——说说竞价拍卖那点事相关推荐

  1. SpringBoot在线拍卖竞价拍卖竞拍系统源码

    SpringBoot在线拍卖竞价拍卖竞拍系统源码 视频效果 https://www.bilibili.com/video/BV15a411U7uX/ SpringBoot在线拍卖竞价拍卖竞拍系统源码+ ...

  2. 公有云上基于微服务架构SAAS产品研发实践「活动通知」

    公有云SAAS产品不同于传统的软件包产品,我们不仅需要负责软件的研发,同时需要负责产品的运维,面对众多用户,需要保障产品7X24不间断运行:客户业务是不断变化的,产品需要在持续运行过程中进行持续升级, ...

  3. IBM IaaS:云计算基础架构明星产品解决方案

    IBM IaaS:云计算基础架构明星产品解决方案 IBM基础设施即服务IaaS云计算架构明星产品包括PureSystem .System Z.Power Cloud.System X.Storage ...

  4. 信息架构、产品架构和业务架构

    来自网易音乐云产品经理<幕后产品>一书: 信息架构.产品架构与业务架构的关系可以认为是递进式的:信息架构是最前端 的表现层架构,产品架构是连接业务与用户表现层的产品功能.系统的架构,业务架 ...

  5. 基于springboot在线竞价拍卖管理系统

    主要实现了普通用户在线参与竞价拍卖基本操作流程的全部功能,系统分普通用户.企业用户.超级管理员等角色,实现的功能有:超级管理员:系统管理.用户管理(冻结等).审批竞拍标的物管理.竞标类型管理.审批机构 ...

  6. 华为业务:组织架构和产品矩阵

    华为是一家伟大的公司,不仅仅因为其本身伟大,同时还是很多伟大公司跟随的榜样. 一.华为简介 已经记不清人工智能还没出现的时候华为的愿景了,现在华为公司的**企业愿景–构建万物互联的智能世界.**印象中 ...

  7. Milestone 系统架构 及产品白皮书

    White paper 白皮书 Milestone InterconnectTM 里程碑interconnecttm Prepared by: 制备: John Rasmussen, Senior T ...

  8. 揭秘LOL背后的IT基础架构丨产品而非服务

    欢迎来到Tungsten Fabric用户案例系列文章,一起发现TF的更多应用场景."揭秘LOL"系列的主人公是Tungsten Fabric用户Riot Games游戏公司,作为 ...

  9. HiTSDB 时序数据库技术架构和产品解析

    8月24日阿里云数据库技术峰会上,来自阿里数据库事业部高级专家钟宇带来HiTSDB 时序数据库方面的演讲.本文主要从时序数据开始介绍,包括时序序列数据的特点,接着介绍了时序数据业务场景,以及OpenT ...

最新文章

  1. python之路---25 模块和包
  2. OS / 进程启动过程
  3. 【Ubuntu】 Ubuntu18.04修改主机名
  4. Java面试面向对象三大特征,Java面试经典基础问答三
  5. 程序员制作出价值5亿外卖神器却不能取消订单,你知道吗?
  6. 优化 ASP.NET Core Docker 镜像的大小
  7. 趣文:追MM的各种算法
  8. python 京东签到在哪里_python 使用selenium登陆京东签到哪京豆
  9. [转载] python中断响应_用Python脚本监测.py脚本的进程状态,并实现中断重启。
  10. 美图秀秀计算机教程,美图秀秀怎么抠图 美图秀秀抠图详细教程
  11. 图论及其应用 2009年 期末考试答案 总结
  12. 各种数据库之间数据迁移工具
  13. c# .net Paypal支付Webhooks回调验证
  14. 生成式对抗网络(GAN)相关问题汇总(较全面)
  15. intellij idea 类和文件夹(目录)左上角出现小叉号
  16. 老人与海好词100英文带翻译_老人与海优美段落英文,英文的优美句子,带翻译,越多越好,谢谢...
  17. POLYWORKS案例:MTU航空发动机 - 最前沿的机翼检测技术
  18. 重磅!瑞泰信息发布中国企业数字化增长行业实践白皮书——《数字化平台造就企业增长新引擎》
  19. 如何根据vin码查询_vin查配置 车辆VIN码查询车辆基本配置信息 知道车辆vin码怎么查配置...
  20. 探营长虹软服 共议数字化转型与创新

热门文章

  1. 具有OpenCV和相似度测量的视频输入
  2. OpenGL blending 混合的实例
  3. OpenGL Static Texture静态纹理的实例
  4. QT的QModbusResponse类的使用
  5. C++11 - sizeof用于类成员
  6. c语言整行乘非整形等于什么意思,C语言--整形升级寻常算术转换
  7. linux dd devzero,makefile中ifeq与ifneq dev/null和dev/zero简介 dd命令
  8. php 函数传值_传址_函数参数,php函数的传值与传址(引用)详解_PHP教程
  9. Apache Ranger、业务背景、现状与需求、大数据安全组件介绍与对别、系统架构及实践、ranger admin、UserSync、plugin、权限模型、权限实现等
  10. NDK开发环境安装,CDT安装,Cygwin安装