OSCHINA 问答合集[4]:入职一个月发现公司项目代码管理乱、代码烂,该留还是走?

局长 发布于 2018/08/18 19:44
阅读 5K+
收藏 24

开源中国问答区新栏目OSCHINA 问答合集上线啦,本期收录了 7 月高热度的问题及回复(吐槽),希望能让你有所收获~!

进入问答区:

你可以在技术问答版块畅聊技术
你可以在职业生涯版块寻道解惑
你可以在IT大杂烩版块和大家谈笑风生

我们希望:

这里可以成为一个能让大家有所收获的地方。因此,这里拒绝攻击、拒绝谩骂、拒绝无脑黑。
这里可以沉淀大家各种的技术问题。无论是新手的基础问题,还是资深开发的深度问题,都是有价值的。
这是一个更纯粹讨论技术的地方,能给程序员提供一片友好交流的清净之地,不懂的可以在这里寻找帮助,懂的可以在这里帮助别人。

总之,

在这里你可以向所有人提问。
反正你的问题可能会没答案。;-)

emmm……本期收录的技术问答基本都和数据库相关,秒杀场景、读写分离、缓存数据这些问题相信各位都遇到过不少,大家不妨看看别人的思路是否有值得借鉴的地方。

不多说了,大家接着阅读 oscer 的精彩回答吧~!

==========分割线==========

开源中国技术问答

@winston952:秒杀场景,异步扣减库存的问题

最近工作中遇到了秒杀场景,

1、限流
2、将库存放到redis中、接收用户请求的时候。从redis取库存,判断库存量是否大于本次订单购买量
   库存大于本次购买量:扣减redis中的库存、并且将订单信息推送到MQ;
   库存小于本次购买量:直接返回、数量不足。
3、MQ消费者获取消息:
   1):更新数据库库存(乐观锁)
   2):生成订单信息,扣除用户账户的订单金额(余额不足的话、将本次购买量加回到库存里)
   3):异步通知用户购买结果。

问题:
     如果redis挂掉、或者redis中的库存超时。那么在第2步,就需要从数据库里面获取存库量。
     但是此时可能MQ里面存在还未消费的消息,导致第2步中取到的库存大于实际的库存。

     请问一下  各位是否有好的解决办法。还是说只能将更新数据库库存 也放到第2步完成。

>>>MikeDrew
你这个解决思路要分开看。redis 一定存在超卖的情况,原因是 redis 数据的准确有一定时间的滞后,假设是5秒。redis实际在做的事是限制5秒以后的多余交易,起一个能限流5秒以后交易的功能。不是在承担解决超卖的问题。

你靠锁解决的是数据库的数据一致的问题,和redis解决的问题不是一个问题,这两件事最好都要做,库存实际就是使用数据库。redis里的库存数据相当于不是库存数据,就是一个限流用的数据,而且只限5秒以后的流,5秒内的限制不到,都进队列了。

实际买卖扣储存的操作是mq消费者在操作数据库在做,不是你操作redis的那个线程在做。如果你队列消费存在竞争的情况下,你要对数据库加锁,保证消费数据是顺序的,然后就ok了。

你数据库放第2步也行,不过那样相当于redis就没用了。流程变为先放入mq,消费mq,mq消费者操作数据库,如果mq存在数据竞争的话数据库操作别忘了加锁,把redis操作去了,反正也没用了。

>>>lkclkc888
你所说的问题根本就不存在。既然订单的结果是消费mq消息之后异步通知用户的,那么,实际上此时多放几个订单信息到MQ并不会产生超卖的情况,因为在MQ消费的时候,是可以保证数据库不超卖的。这里面只需要做好友好提示即可。所以,redis挂掉重启,即使redis中的库存+mq中的消息数>db数据也没有问题,只是会多放消息进入mq。
对于用户来讲,可能就是订单数据建立了, 但是订单最终没成功,我想抢火车票的时候,大家都遇到过这情况。

>>>newzai
对redis不是很熟悉,但只是提供一个思路给你参考。
1.秒杀做一个队列,用户提交的订购信息插入临时数据库,或一个队列,插入后,依次统计队列前面的订单信息总的商品数量和该用户的商品数量之和有没有超过总库存,如果超过了,就直接删除,或者标识为无效(同时反馈给前端页面,商品售罄什么的   )。 插入数据库或队列的时候可以根据用户id 或其他唯一标识来防止重复提交。
该订单用户付款后,再从总库存里减,同时从该队列中去掉(或者做已付款标识)。  同时也定时检查队列里面的待付款订单是否超时,如果超时就删除或者标记为无效订单。也就是说 总库存和 用户的队列记录来对应,这样也不用什么锁了。
2.将库存放到redis中、接收用户请求的时候。从redis取库存,判断库存量是否大于本次订单购买量
   库存大于本次购买量:扣减redis中的库存、并且将订单信息推送到MQ;
   库存小于本次购买量:直接返回、数量不足。
不能取回到本地内存, 最好使用lua脚本,在redis 内部计算。返回结果。
否则取回 扣减 这个流程就要涉及到 redis 分布式加锁。

@落后君丶:读写分离我有点想不通

上面那个图,读库压力没变啊!!!!!数据复制一样是写入数据啊,读不变啊!为啥说读写分离能提高效率?这不符合逻辑!!!难道他这个数据复制跟写sql不一样?效率高些????

>>>325G
读库可以以集群方式部署 节点多压力就会变小

>>>巴林的狗尾草
这个是个架构问题,不是个编程问题。

首先读写分离带来的好处是你本来只有一个数据库现在有两个库了,有做过高性能经验人都知道对于共享资源的扩展带来的性能提升,这是一个好处,然后写库往往又叫做实时库,读库是个异步库,需要根据业务来决定使用哪个库,然后就是读库带来的好处了,读库因为没有那么频繁的写入操作(同步过程一般都是批量的),所以可以允许增加更加多维度的索引而不会造成性能的下降,然后还牵扯数据归档,同时可以支持的在线库的存储规模等等。

总之,哪天你的应用的体量上来了,你自然就能明白到底为什么了,这个图并不能说明多少问题

>>>北风刮的不认真了
这个,还是取决于你的业务。不过大部分业务都是读的操作是写的10倍以上。
所以读写分离,咱们一个一个说

1. 读:当有大量(非常大,大到一个数据库都执行的慢)的读操作时,有多个数据库来分摊,那么读的性能肯定会提升
2. 写:咱们设定,写的操作比读会少很多很多,就那么1个或几个数据库就能写的过来,并且不干扰读的数据库。(复制的I/O操作相比直接在一个数据库上读写开销会小很多)
以上场景建立在读比写多很多的情况下。如果你写操作比读还多,读写分离,,好像也可以的。就是写库比读库还多... 但这个场景就没研究了,不多说

@快速开发师:客服业务缓存问题求修改

现在有个客服系统,由于用户打电话进来的人较多,客服来不及处理一些业务,于是就把客服电话信息缓存在session里,挂机后再处理,这涉及到一个问题,如果客服退出系统session里缓存自动被服务器销毁就没了;现用户要求至少要保留1天,咋整,想到了保存到表里,但如果不保存到表里该如何做?保存到cookie中我也想过,但客服说,他们可能在另外登陆一台电脑,说明cookie也完蛋(cookie只能存本机硬盘)。

>>>Sel8616
这还纠结啥,肯定得持久化,要么数据库,要么文件系统,其实存数据库本质上也是存到文件系统里。
放到内存里虽然也能实现要求,但存在宕机丢失数据的风险;如果是集群,还得自己实现同步机制,徒增工作量。
最佳方案见投票 ↓↓↓

>>>sxgkwei
redis 里面有个存储方法是带超时时间的,你可以考虑一下。过了1天了去取自然就取不到了,很适合你这个场景。

@芒果味丶:关于数据库表设计的问题

如果我数据库有这两张表(员工信息表和成长情况表)

1.员工信息表的主键是选职工工号,还是员工信息ID?,外键是职工工号,还是成长情况ID?
2.另一张表主键是选择成长情况ID还是职工工号?
3.如果两张表主键职工工号这种情况算不算表的垂直分割?

ps:刚学习数据库,我想知道为什么怎么选主键怎么选外键而不是答案。

>>>魔力猫
一般主外键不要使用业务字段,而是选择一个无业务意义的主键。外键关联,必然是关联表主键。而且一定要添加外键索引。

如果你用有意义的字段,那么就要考虑日后这个字段如果变化了会怎么样。比如字段长度扩展、字段定义变化。而这种变化很可能引发超多的麻烦。
比如你这个表字段被几百个表引用,那么你就要确保几百个表,因为字段变化都要同时修改。重建索引、修改无数表的定义、删除重建所有的外键。而且要保证这些都要在停止服务的情况下,一次完成。这意味着需要一个超长的窗口时间和严重的业务风险。
建立一个无业务意义的字段,就没有这些问题。除非你这个表不要主键了,不然你完全不用担心主键相关的表定义在某一天会被修改。

职业生涯问答

本期的职业生涯问答所挑选的问题都十分实际,如创业公司中如何处理“老人”们消极怠工的问题、而面对公司的项目代码管理乱且烂,又该如何抉择?篇幅较长,不过值得一读。

@Sgmder:如何提升创业公司技术团队的研发速度和效率?

背景:合肥O2O行业创业公司,项目上线1年+,目前发展良好

随着业务发展,市场和运营的需求越来越多,需要配称更高更快的技术研发速度和效率,而技术团队(13人)由于长期待遇好要求低,养成了一些不好的习惯,现在开发效率较低,不知道如何进行提升。

我原以为可以通过提高人力、待遇、设备和福利等方式解决问题,但发现基本是无用功反而提高了公司的成本。
尝试过项目管理,使用teambetion、为知笔记、钉钉等工具协助,受到部分抵制,执行的很不理想。
老板建议我直接换人...考虑换人学习培养成本和感情因素不希望如此啊!
求各位前辈指点。

大多都有说换人,但合肥这2.5线城市招人实在太难了,房价高工资低,人才本来就少,大部分都去了讯飞等一批上市公司了,社招基本上一个月才能面到一两个不错的还被鸽,校招也有做,效果也不错,但创业公司没有时间去一个个培养啊。

>>>sxgkwei
如果忍不了,你可以换人试试看。很多情况,换来的人还是那样儿,而且可能因为技术断代而导致产品开发长期处于停滞状态。还有可能始终招不到合适的人,非一线城市招 程序员 简直就是折磨,长期找不齐人手太正常了。

如果你是技术的老员工了,长期带着这个队伍,那么,可以考虑把那种一让做事就给你讲事实摆困难的人直接T掉。这种人在队伍里,就是负能量影响场,会影响周围一圈人。别给我说“听他每次说的,确实是困难”这种话,“公司花钱用你,就是让你解决问题的,不是让你把问题摆给我,让我来解决的”。

如果你是空降的管理职位,那我只能说,你自己干不长了还不自知。你刚到公司,自己应该并未干出什么所有人都承认的优秀成果。然后就觉得老队伍这不行,那不好,到处都是拖油瓶,这种不承认别人劳动成果的,只会叨叨的,最容易引起集体性抵制。如果你是这种人,那么,别想了,别人就是抵制你,你咋滴。

>>>7upzcc
说说自己的观点:
首先我不赞成简单暴力的换人。这样既会造成技术断代,也会对剩下的人造成不好的影响。同时对于个人发展来讲,这种暴力的处理问题的方式对上对下方法都不漂亮。其次,我也不建议每个人都找来谈这种略温和的处理方式,这种方式会造成每个人都有自己的看法和条件,最后无法统一,那么挨累的还是管理者。

好了,说说我的方法。产品平稳运行一年的时间点上,初期开发的繁忙基本已经没有了,1.0版本的BUG对于现有团队来讲,几乎没有任何难度,长时间没有“活儿”导致团队中怠慢的思想蔓延,这种很常见。既然现在随着业务发展带来的需求增多了 ,那么工作量肯定是一个递增的趋势,在怠慢思想严重的时候,缓慢的需求增加肯定会是各种需求完不成,需求完成度不高,BUG各种出现的情况。我说一个解决方法,这也是我在开发的时候经历的,希望给你一些参考。我会将需求整理之后,分出优先级,然后将急需解决的问题和需求直接呈报给负责人(鉴于最近的产品经理与开发的冲突事件,请把握好需求的可实现性)。制定好上线时间,然后,骨气勇气,要求开发加班吧!这步最关键。适当的集中加班可以帮助你的团队找回开发的状态,之后再短暂的休息放松一段,之后再一次集中开发一段。这样每一次集中开发的成果都会转化成团队的成绩,然后每一次的放松都会帮助团队恢复状态。就这样。

说好听点,你的团队有里程碑计划么?有需求整理么?有功能责任落实到人么?如果没有,长时间出于放松状态的开发,慢慢会懒惰致死。当怠慢的情绪占主流的时候,离职吧,团队死掉了,产品也就这样了。或者1.0到2.0之间,你可以提出重构啊:)另外,我恨重构。

>>>小小程序员
本人恰好一直兼任行政管理岗位,也一直涉及到这块,给你一些建议:
团队由好变坏易,由坏变好难,就算你招一个非常肯干活的人进来,多半要同化;
作为一个领头羊,本身要以身作则,同时不停催促让下面的人跟上你的节奏;
当你老板要建议你换人的时候,你如果还不行动,那么老板下次可能换得就是你了;
要员工自己给自己定目标,一个功能分配给你,员工自己定时间,时间完成不了惩罚,超时的时间造成的工资支出全部罚掉(保留基本工资部分);然后你根据你的经验+员工的个人能力,给出一个挑战时间,这个时间内完成的,有奖励

管理不狠,底下不稳,通过全员大会,确定奖惩制度、炒鱿鱼条件,严格照章办事,不要怕离开,再招人就是。

@骚不动的程序员:你们怎么看待公司项目代码管理乱,代码烂?

公司用的框架有点落后,写出来的代码经过N代码农的“改造”过后,以及几个版本掺和在一起,已经不忍直视了,页面jsp中各种structs、spring标签,后端ibatis、mybatis混用,包命名、结构不合理,很多重名文件,在不同版本包下,冗余代码,引入了新技术,代码里整体用的很少,更不提注释了,很多问题,请问这还有必要待在这嘛?
我来了一个月,以前公司前后端分离,挺规范的,可能养成了“代码洁癖”,在这要么改BUG,要么在原来的功能上进行改造,每天就是给个bug清单,然后自己跟踪修改,哎~~~,各位怎么看?(补充:124,加班到8点半,周六9点半到四点半,平时上班8点半到5点半)

>>>NeverMore_Jugg
还不走等出任cto啊 老铁

>>>aa小马
要么忍,要么滚,没有什么好BB的,你改变不了什么东西。钱到位,什么事都可以商量,钱不到位,代码写的再漂亮有什么用,在外行看来就是程序自己的意淫而已。

>>>sxgkwei
代码方面都还好,综合起来,都不是问题。主要是加班,这种上班制度,如果你当初要薪资的时候,没考虑加班薪资,还是算了吧。

代码能成目前这种模样,说明公司做的还不错,业务上最少是成功了,而且也做了不少年头了,那么毕竟有可以学习的地方。比如工作流程管理啊,处理各种情况下的客户问题啊,应该怎么取舍客户需求啊,这些东西还是值得学习的,但代码洁净的一批的公司,这些基本是学不到的。

>>>AlanVision
哪家公司还没点烂代码,多见识一下就不会来发这个贴了,包括百度,阿里,京东这些一线互联网公司,发展的过程中同样会有烂代码,不是每个公司一开始都请得起架构师,高级coder,理解一下这句话:“业务为王”,你就什么都能理解了,在绝大多数公司技术只是个工具而已

>>>蹲在地上写字的男孩儿
我觉得看看自己能否有权力调整一下架构,如果实在无法优化或者没权调整或者费力不讨好,就算了,不过只要待遇到位就还好,不然才跳槽

>>>后海
都是在各种扩展的需求和有限的时间下,慢慢变烂的。

>>>zbbmaster
跟你说句实话,国内靠前的互联网公司也有你说的框架落后,代码乱,不加注释,没有文档的系统。所以关键在于自己优化的能力,变通能力,说服领导让你来重构系统,这些问题不正是你表现自己,进行代码重构的好机会吗?

@老道士:一个程序员在大城市,还是选择离家近的好城市呢?

关乎到之后的发展,大家有什么好的建议吗

>>>开源中国首席钛金逗比
每个人的好不一样,别人眼里的好不等于你眼里的好.
至于这个问题,既然你问出来,心里有这个纠结,说明你偏向回家,但是又想城市的收入.
所以归根结底不是哪个答案对你是好的,而是你想综合两个方案的好处,一点都不想妥协.
相信等有一天你不得不做出选择的时候,就有答案了

>>>Diors__
回答你的问题也是闲着蛋疼了,作为一个工作有几个年头的低水平码农来给你个建议,可以简单参考一下。

1、如果你想未来创业的话,建议是大城市,因为技术水平不一样。做东西总需要技术,如果你在小城市,可能连个技术方案都不会想,小城市遇到技术有难度的东西,不敢相信有人会帮你解决,因为水平普遍都不怎么高,没有技术环境,还在用古老的ssh。至少有好几个老家的码农,在我刚毕业没几个月的时候,居然还在问maven怎么用,是干什么的。比如跟你说个环形队列,你可能都不知道他能快速解决什么问题。
2、如果你只是想混口吃的或者将来想做个不大不小的领导,家里又是小康水平,建议家里。因为做事儿总需要人际关系,大城市漂流十年,再回去,你可能既没钱又没人脉。毕竟,你现在不太缺钱,家里父母能帮上忙,离家里又近。
3、如果你家里没钱,自己又急缺钱,可以选择大城市,机会多,大城市看实力,毕竟大城市给的工资会比小城市高很多。

>>>竹蜻蜓0927
要不在自己家乡, 要不去北上广深, 反正最后要租房,为什么不去好点的地方。
我当时不去北京,是因为家里有车 有房 有女朋友,所以他妈的废了。
掌握着不高不低的技术 赚着不高不低的工资 。

你也希望自己的提问/回答上榜?欢迎大家前往>>>技术问答区,多多提问,多多回答~!
遇到技术问题,就上开源中国问答区

==========分割线==========

OSCHINA 问答合集[1]:老大竟然说我不会写 SQL ……
OSCHINA 问答合集[2]:我有一套高峰期每秒钟约有 1 万人下单的系统,遇到了关于 Java 高并发的问题
OSCHINA 问答合集[3]:无法确定自己的方向,又无法转行怎么办?

加载中
1
wendal
wendal

想离职就直说, 无非两个原因: 

1. 钱没给够

2. 干得不爽, 因为钱没给够

0
SimonYe
SimonYe

地球上不爽的事情有很多,走?去月球?

0
zxl78585
zxl78585
你要是足够牛的话,就把他代码整理下,如果没有那个金刚钻,我建议也别拦那个瓷器活
0
--路边小草--
--路边小草--

这个读写分离的图是错的吧,都弄反了,还有就是redis并不能解决高并发的超卖,它只是读写比mysql快很多而已,要解决超卖,还是得靠自己的业务代码,比如在mysql层面即可解决超卖,update store = store - sell_num where store > sell_num;  (store是库存,sell_num是购买量),或者事先把库存存入redis的list,每抢购一个就pop一下,这样也不会超卖,为什么不使用redis取库存,判断库存量是否大于本次订单购买量,因为取与判断之间的这点空隙时间就有可能库存已经变了。

0
z
zhao4zhong

地球上有项目代码管理不乱、代码不烂的公司吗?!

家周伟
学到了
0
leafyi
leafyi

代码烂可以改 ,如果改不了就重新写呗 有什么大不了的

0
熊猫basara
熊猫basara

能赚钱就行。

返回顶部
顶部