这就叫“面试造火箭,工作拧螺丝!”

· 浏览次数 : 0

小编点评

你好呀,我是歪歪。我想再讨论一下上次的这篇文章《哎,被这个叫做at least once的玩意坑麻了》,因为有些朋友看完之后在评论区给出了自己的思考,也有朋友和我私聊,分享了自己的看法,我觉得有些想法很好,所以我决定一鱼两吃,再聊聊这个问题。 假设,我们是一场面试,面试官给你抛出了这样一个问题:如果一个消费队列由于某些原因,对于某个消息发起了两次,导致一样的数据落库两条,请问你会怎么处理这个问题? 这题你一拿到手上,应该就立马能分析出是在问如何实现一个幂等机制。想着这玩意我熟啊,张口就能给出方案:业务消息 = select(业务唯一流水号); if(业务消息 == null){ save(业务消息); }面试官一听,提示道:你这个方案在多线程的情况下会不会有什么问题呢? 于是你的小脑瓜子立刻开始转了起来:先查询,再判断,最后保存。如果两个线程同时过来,都查不到数据,那么就能都走到保存的逻辑里面去,确实拦不住。于是你扣了一下脑壳,想起了你上家公司针对这个问题,就是在数据库的表结构里面,对业务唯一流水号做了唯一索引,所以不会出现重复插入的情况。然后你给出了“加唯一索引”的方案,准备绝杀这个问题。 没想到面试官非常不懂事,还在继续追问:我想尽量不要让程序抛出异常,还有没有其他的方案呢? Redis 你抱着自己的左手,边啃指甲边思考:唯一索引是数据库帮我们保证的逻辑,现在面试官这个老登不想让我用数据库来做这件事情。那就必须要控制在并发的场景下,只有一个请求能抵达数据库。锁!这不就是锁干的事儿吗? 于是你飞快的又想到了一个方法:flag = redis(业务唯一流水号,过期时间); if(flag){ save(业务消息); }可以利用业务唯一流水号结合 Redis 来做一个锁,加锁成功的请求才能走到 save 逻辑中。这样就能解决并发场景下,多个请求穿透到 save 逻辑这一步的问题。 面试官听到你这个方案之后,立马就启动了追问技能:如果放 Redis 成功了,但是还没来得及 save,服务重启了。这个请求理论上是应该能再次发起的,但是由于 Redis 锁的存在,导致不会走到 save 的逻辑去,怎么办呢? 于是你又扣了一下脑壳,想起你在上家公司的时候,好像也遇到过这个情况。当时的解决方案就是人工介入,分析了一波数据,确认了这个消息确实应该被继续处理,于是你找 DBA 帮忙删除了 Redis 对应的 key,流程就通了。 然而这个回答面试官并不满意:人工就显得不优雅了,要不再想想? 你又抱着自己的右手,边啃指甲边思考:这个老登考虑的确实挺多的,感觉应该在一个很厉害的团队,我得加把劲儿,再想想。现在要人工介入的原因,是因为我们把第二次的请求拦截住并丢弃了。如果不丢弃,那么理论上在“过期时间”到了,锁被释放后,第二次的请求拿到锁,就能接着往下走。所以,这里需要在 Redis 这里加一个加锁失败则等待的逻辑:flag = redis(业务唯一流水号,过期时间,获取不到则等待); if(flag){ save(业务消息); }但是你一看这个逻辑又不对了:由于有锁等待的逻辑,那么如果两个请求过来,还是有可能会都放入到 Redis 里面,flag 都会为 true,那么 save 方法还是会走两遍。所以,还得在获取锁成功之后加上一个查询数据库的逻辑:flag = redis(业务唯一流水号,过期时间,获取不到则等待); if(flag){ save(业务消息); } else{ //等待结束后还是未获取到锁,发送预警 monitor(预警信息); } 第一层的 Redis 相当于让请求排队,确保只有一个请求进来。第二层的 select 才是真正的防止重复的业务逻辑。同时,如果等待结束后还是未获取到锁,出现这种低概率情况,就预警出来,人工兜底嘛,一旦人工介入,那就是能解决任何问题。 你心想这波应该是稳了,应该是可以换题了。然而面试官并不打算在这个回合上轻易放过你:这个方案确实是可以解决这个问题,但是在技术实现上引入了 Redis 框架,如果我不使用 Redis,单纯的靠 MySQL 呢? 回到 MySQL 听到这个问题的时候你觉得不对啊,最开始的时候不就是说了“加唯一索引”就可以解决这个问题吗?于是面试官补充了一下描述:最开始的加唯一索引是基于业务表来做的,如果出现问题就让其抛出主键冲突异常,这个方案确实是可以实现需求。但是我现在想让你给我设计一个通用的技术组件,不需要基于某个具体的业务场景去设计。 我想听听你的思路。拿到新的题目,你开始觉得这是***难,看着面试官求知的眼神,你又开始怀疑:这个老登不会是来套方案的吧? 看着自己已经被咬秃了的左右大拇指指甲,感觉自己的灵感和指甲一样都光秃秃的。开始后悔前面几个回合咬得太快了,原以为可以秒杀这个面试,没想到面试官还在缠斗。 你动了使用必杀技来结束战斗的念想。于是从帽子的缝隙中插进入一根指甲已经秃了的手指,在差不多秃了的头顶,用指腹画圈,给自己头皮按摩,医生说这样的有助于毛囊发育,你想着头发还会长出来,就思如泉涌,这就是必杀技。 你陷入了思考,Redis 在前面的方案中是为了防止有多条数据穿透到 save 方法中去,如果不让用 Redis。MySQL 怎么实现类似的效果呢?也加锁吗?for update?业务消息 = select(业务唯一流水号);//select *** for for update if(业务消息 == null){ save(业务消息); }这玩意一看上去就是性能就拉胯了,为了解决这个偶发的问题,牺牲了接口的性能,这个路线就走的有点远了。 而且这个上锁的逻辑隐藏的有点深,容易留下后患,面试官肯定不会满意的。那还有什么办法,能把 MySQL 当作锁来用,确保并发情况下只有一个请求能穿过这个锁呢?那还是得靠唯一索引的约束才行。但是这个唯一索引面试官不让用业务表的,那就只能直接搞个“消息消费记录表”,里面有个“消息唯一标识”的字段,这个字段是唯一索引。 这张表面试官问起来,我就说这张表是完全独立于业务的存在,只是为了解决消息幂等这个存粹的技术问题而出现的,基于它,我们就可以设计出一个通用的技术组件,这样应该说的过去。 表有了,技术方法大概的雏形就有了。然而你还不能开始答题,现在思路还不是特别清晰,你要把方案捋清楚了再张口。 在不知不觉间,你的指腹已经摩擦的有点麻木了,于是你换了一个手,穿过帽子,接着按摩着自己的头顶。这个表我怎么用呢?if(保存数据到消息消费记录表){ //出现主键冲突就返回false save(业务消息); }先校验,再保存,非原子性,这样肯定不行啊,我们想想一个场景,如果保存数据到消息消费记录表成功,还没来得及 save(业务消息),服务重启了,怎么办?所以为了保证原子性,我们可以加入事务,把这两步绑定到一起:开启事务;if(保存数据到消息消费记录表){ //出现主键冲突就返回false save(业务消息); }提交事务;这样,如果保存数据到消息消费记录表成功,还没来得及 save(扣款信息),服务重启,事务回滚,消息消费记录表就不会真的插入成功。而 MQ 没有收到这个消息的回执,也会再次进行投递。由于消息消费记录表里没有这个数据,所以会再次进行消费。 现在你觉得似乎没啥问题了,刚想给面试官说你这个思路,但是立马又想到了另外一个问题:通过引入事务来解决了“非原子性”的问题,但是事务这玩意,一般来说,大家都是能不使用事务的地方就尽量不使用事务,通过最终一致性来保证数据的完整性。这个老登肯定会在这个地方继续穷追猛打的,我先预判了他,想想这个问题怎么解决。我们可以在消息消费记录表里面再引入一个“状态”字段,这个字段有两个取值:消费中、消费完成。同时把唯一索引改成“消息唯一标识+状态”。 首先,MQ 发起请求,数据往消息消费记录表插的时候,状态直接就是“消费中”。如果插入成功,则说明是第一次消费,进入到业务逻辑中去。如果业务逻辑执行成功,则更新消息消费记录表对应数据为“消费完成”。如果业务逻辑执行失败,则删除消息消费记录表对应数据,把消息仍回 MQ,等待下次重试。如果插入失败,则说明是重复消费,直接扔掉。 画成流程图上大概是这样的: 顺便提一嘴,上面这个流程图我是用这个网站直接生成的,我觉得这个网站画图还挺舒服的:https://excalidraw.com/ 你感觉这波应该稳了,于是给面试官说出了自己的方案,并在白字上画了流程图。面试官拿着你的流程图,看了一眼,立马就看出了一个问题:如果一个消息插入失败,你的逻辑是扔掉。那假设这条消息的状态是消费中,业务逻辑执行失败,是不是应该重新消费才对呢? 于是你立马反映过来,如果插入失败,则说明是重复消费,还需要判断数据的状态。如果状态是“消费成功”,则说明重复请求,直接返回成功;如果状态是“消费中”,则说明还未处理完成,为了确保成功,需要把请求再次仍回到 MQ。修改了流程图: 面试官拿着这个流程图,微微一笑:倘若我业务执行完之后,状态更新之前,服务挂了,阁下又该如何应对?巧了,这个问题上一篇文章的评论区也提到了:所以,还需要针对长时间在“消费中”的数据进行一个监控,人工兜底一下。此外,为了防止“消费完成”的数据量过多,还应该对于这个状态的数据做一个定时清理的任务。 终于,你看到了面试官脸上那一闪而过的满意表情,在你觉得面试官应该会放过你了的时候,他又提出了另外的问题:你这个通用组件理论上确实是可行的。但是,这张表放在哪个库的哪个表里呢?是统一放在一个库里呢还是就放在业务服务的库里呢?统一放一个库的话太大了怎么办呢?是不是要按日期分表?万一跟业务库用的数据库不是一个数据库产品那事务不生效咋办呢?放在业务库里的话万一业务服务连好几个库那我具体放哪一个呢?是不是所有业务库我都得加这么一张表强制绑架他们的数据库? 这一部分问题,也来自上一篇文章评论区。听到这些问题,你开始觉得这个面试官是在胡搅蛮缠,一气之下,准备拿回简历,结束面试。但是手上动作稍微大了一点,一不小心掀起了自己的帽子,漏出了“资深的发型”。 面试官也愣住了,看着你“资深的发型”,当即就握住了你的手:你就是我要找的人才。不面了,就你了,明天来报道! 入职 入职之后你第一件事情就是看看这个公司的代码。当你看第一个接口的时候,发现根本没有做幂等。当你看第二个接口的时候,发现就是靠业务表的唯一索引做的幂等。当你看第三个接口的时候,Redis 的方案跃然纸上。突然一个哥们气喘吁吁的跑过来找昨天面试你的老登,说:快,又出问题了,帮忙删除一个 Redis key。于是,你抽过去准备看一下怎么操作。不经意间看到了老登正在写一个文档,题目叫做《一种分布式系统中数据唯一性的消息幂等保障策略》。老登看到你过来了,说:正好,你来写这个文档,我已经把名字给你想好了,你就按照这个写,把你昨天的思路写清楚,到时候我去汇报。你兴奋的问:汇报过了之后我们要按照这个方案落地吗?老登说:不不不,落地干啥啊,多麻烦啊,方案汇报嘛,体现一下我们在技术方面的时刻,在领导面前去刷个脸,所以你要多用一些高大上的词,越晦涩难懂越好。哦,对了,我顺便教教你怎么“删除 Redis key”,以后就让他们找你了。这帮老登,大半夜的,老是给我打电话。

正文

你好呀,我是歪歪。

我想再讨论一下上次的这篇文章《哎,被这个叫做at least once的玩意坑麻了》

因为有些朋友看完之后再评论区给出了自己的思考,也有朋友和我私聊,分享了自己的看法,我觉得有些想法很好,所以我决定一鱼两吃,再聊聊这个问题。

假设,我们是一场面试,面试官给你抛出了这样一个问题:

如果一个消费队列由于某些原因,对于某个消息发起了两次。导致一样的数据落库两条,请问你会怎么处理这个问题?

这题你一拿到手上,应该就立马能分析出是在问如何实现一个幂等机制。

想着这玩意我熟啊,张口就能给出方案:

业务消息 = select(业务唯一流水号);
if(业务消息 == null){
    save(业务消息);
}

面试官一听,提示道:你这个方案在多线程的情况下会不会有什么问题呢?

于是你的小脑瓜子立刻开始转了起来:先查询,再判断,最后保存。

如果两个线程同时过来,都查不到数据,那么就能都走到保存的逻辑里面去,确实拦不住。

于是你扣了一下脑壳,想起了你上家公司针对这个问题,就是在数据库的表结构里面,对业务唯一流水号做了唯一索引,所以不会出现重复插入的情况。

然后你给出了“加唯一索引”的方案,准备绝杀这个问题。

没想到面试官非常不懂事,还在继续追问:我想尽量不要让程序抛出异常,还有没有其他的方案呢?

Redis

你抱着自己的左手,边啃指甲边思考:唯一索引是数据库帮我们保证的逻辑,现在面试官这个老登不想让我用数据库来做这件事情。那就必须要控制在并发的场景下,只有一个请求能抵达数据库。

锁!这不就是锁干的事儿吗?

于是你飞快的又想到了一个方法:

flag = redis(业务唯一流水号,过期时间);
if(flag){
    save(业务消息);    
}

可以利用业务唯一流水号结合 Redis 来做一个锁,加锁成功的请求才能走到 save 逻辑中。

这样就能解决并发场景下,多个请求穿透到 save 逻辑这一步的问题。

面试官听到你这个方案之后,立马就启动了追问技能:如果放 Redis 成功了,但是还没来得及 save,服务重启了。

这个请求理论上是应该能再次发起的,但是由于 Redis 锁的存在,导致不会走到 save 的逻辑去,怎么办呢?

于是你又扣了一下脑壳,想起你在上家公司的时候,好像也遇到过这个情况。

当时的解决方案就是人工介入,分析了一波数据,确认了这个消息确实应该被继续处理,于是你找 DBA 帮忙删除了 Redis 对应的 key,流程就通了。

然而这个回答面试官并不满意:人工就显得不优雅了,要不再想想?

你又抱着自己的右手,边啃指甲边思考:这个老登考虑的确实挺多的,感觉应该在一个很厉害的团队,我得加把劲儿,再想想。

现在要人工介入的原因,是因为我们把第二次的请求拦截住并丢弃了。

如果不丢弃,那么理论上在“过期时间”到了,锁被释放后,第二次的请求拿到锁,就能接着往下走。

所以,这里需要在 Redis 这里加一个加锁失败则等待的逻辑:

flag = redis(业务唯一流水号,过期时间,获取不到则等待);
if(flag){
    save(业务消息);    
}

但是你一看这个逻辑又不对了:由于有锁等待的逻辑,那么如果两个请求过来,还是有可能会都放入到 Redis 里面,flag 都会为 true,那么 save 方法还是会走两遍。

所以,还得在获取锁成功之后加上一个查询数据库的逻辑:

flag = redis(业务唯一流水号,过期时间,获取不到则等待);
if(flag){
    业务消息 = select(业务唯一流水号);
    if(业务消息 == null){
        save(业务消息);    
    }
}else{
    //等待结束后还是未获取到锁,发送预警
    monitor(预警信息);
}

第一层的 Redis 相当于让请求排队,确保只有一个请求进来。

第二层的 select 才是真正的防止重复的业务逻辑。

同时,如果等待结束后还是未获取到锁,出现这种低概率情况,就预警出来,人工兜底嘛,一旦人工介入,那就是能解决任何问题。

你心想这波应该是稳了,应该是可以换题了。

然而面试官并不打算在这个回合上轻易放过你:这个方案确实是可以解决这个问题,但是在技术实现上引入了 Redis 框架,如果我不使用 Redis,单纯的靠 MySQL 呢?

回到 MySQL

听到这个问题的时候你觉得不对啊,最开始的时候不就是说了“加唯一索引”就可以解决这个问题吗?

于是面试官补充了一下描述:

最开始的加唯一索引是基于业务表来做的,如果出现问题就让其抛出主键冲突异常,这个方案确实是可以实现需求。但是我现在想让你给我设计一个通用的技术组件,不需要基于某个具体的业务场景去设计。我想听听你的思路。

拿到新的题目,你开始觉得这是***难,看着面试官求知的眼神,你又开始怀疑:这个老登不会是来套方案的吧?

看着自己已经被咬秃了的左右大拇指指甲,感觉自己的灵感和指甲一样都光秃秃的。

开始后悔前面几个回合咬得太快了,原以为可以秒杀这个面试,没想到面试官还在缠斗。你动了使用必杀技来结束战斗的念想。

于是从帽子的缝隙中插进入一根指甲已经秃了的手指,在差不多秃了的头顶,用指腹画圈,给自己头皮按摩,医生说这样的有助于毛囊发育,你想着头发还会长出来,就思如泉涌,这就是必杀技。

你陷入了思考,Redis 在前面的方案中是为了防止有多条数据穿透到 save 方法中去,如果不让用 Redis。MySQL 怎么实现类似的效果呢?

也加锁吗?for update?

业务消息 = select(业务唯一流水号);//select *** for update
if(业务消息 == null){
    save(业务消息);    
}

这玩意一看上去就是性能就拉胯了,为了解决这个偶发的问题,牺牲了接口的性能,这个路线就走的有点远了。

而且这个上锁的逻辑隐藏的有点深,容易留下后患,面试官肯定不会满意的。

那还有什么办法,能把 MySQL 当作锁来用,确保并发情况下只有一个请求能穿过这个锁呢?

那还是得靠唯一索引的约束才行。

但是这个唯一索引面试官不让用业务表的,那就只能直接搞个“消息消费记录表”,里面有个“消息唯一标识”的字段,这个字段是唯一索引。

这张表面试官问起来,我就说这张表是完全独立于业务的存在,只是为了解决消息幂等这个存粹的技术问题而出现的,基于它,我们就可以设计出一个通用的技术组件,这样应该说的过去。

表有了,技术方法大概的雏形就有了。

然而你还不能开始答题,现在思路还不是特别清晰,你要把方案捋清楚了再张口。

在不知不觉间,你的指腹已经摩擦的有点麻木了,于是你换了一个手,穿过帽子,接着按摩着自己的头顶。

这个表我怎么用呢?

if(保存数据到消息消费记录表){//出现主键冲突就返回false
    save(业务消息);    
}

先校验,再保存,非原子性,这样肯定不行啊,

我们想想一个场景,如果保存数据到消息消费记录表成功,还没来得及 save(业务消息) ,服务重启了,怎么办?

所以为了保证原子性,我们可以加入事务,把这两步绑定到一起:

开启事务;
if(保存数据到消息消费记录表){//出现主键冲突就返回false
    save(业务消息);    
}
提交事务;

这样,如果保存数据到消息消费记录表成功,还没来得及 save(扣款信息) ,服务重启,事务回滚,消息消费记录表就不会真的插入成功。

而 MQ 没有收到这个消息的回执,也会再次进行投递。

由于消息消费记录表里没有这个数据,所以会再次进行消费。

现在你觉得似乎没啥问题了,刚想给面试官说你这个思路,但是立马又想到了另外一个问题:通过引入事务来解决了“非原子性”的问题,但是事务这玩意,一般来说,大家都是能不使用事务的地方就尽量不使用事务,通过最终一致性来保证数据的完整性。

这个老登肯定会在这个地方继续穷追猛打的,我先预判了他,想想这个问题怎么解决。

我们可以在消息消费记录表里面再引入一个“状态”字段,这个字段有两个取值:消费中、消费完成。

同时把唯一索引改成“消息唯一标识+状态”。

首先,MQ 发起请求,数据往消息消费记录表插的时候,状态直接就是“消费中”。

如果插入成功,则说明是第一次消费,进入到业务逻辑中去。

  • 如果业务逻辑执行成功,则更新消息消费记录表对应数据为“消费完成”。
  • 如果业务逻辑执行失败,则删除消息消费记录表对应数据,把消息仍回 MQ,等待下次重试。

如果插入失败,则说明是重复消费,直接扔掉。

画成流程图上大概是这样的:

顺便提一嘴,上面这个流程图我是用这个网站直接生成的,我觉得这个网站画图还挺舒服的:

https://excalidraw.com/

你感觉这波应该稳了,于是给面试官说出了自己的方案,并在白字上画了流程图。

面试官拿着你的流程图,看了一眼,立马就看出了一个问题:如果一个消息插入失败,你的逻辑是扔掉。那假设这条消息的状态是消费中,业务逻辑执行失败,是不是应该重新消费才对呢?

于是你立马反映过来,如果插入失败,则说明是重复消费,还需要判断数据的状态。

  • 如果状态是“消费成功”,则说明重复请求,直接返回成功
  • 如果状态是“消费中”,则说明还未处理完成,为了确保成功,需要把请求再次仍回到 MQ。

修改了流程图:

面试官拿着这个流程图,微微一笑:

倘若我业务执行完之后,状态更新之前,服务挂了,阁下又该如何应对?

巧了,这个问题上一篇文章的评论区也提到了:

所以,还需要针对长时间在“消费中”的数据进行一个监控,人工兜底一下。

此外,为了防止“消费完成”的数据量过多,还应该对于这个状态的数据做一个定时清理的任务。

终于,你看到了面试官脸上那一闪而过的满意表情,在你觉得面试官应该会放过你了的时候,他又提出了另外的问题:

你这个通用组件理论上确实是可行的。

但是,这张表放在哪个库的哪个表里呢?

是统一放在一个库里呢还是就放在业务服务的库里呢?

统一放一个库的话太大了怎么办呢是不是要按日期分表?

万一跟业务库用的数据库不是一个数据库产品那事务不生效咋办呢?

放在业务库里的话万一业务服务连好几个库那我具体放哪一个呢?

是不是所有业务库我都得加这么一张表强制绑架他们的数据库?

...

这一部分问题,也来自上一篇文章评论区。

听到这些问题,你开始觉得这个面试官是在胡搅蛮缠,一气之下,准备拿回简历,结束面试。

但是手上动作稍微大了一点,一不小心掀起了自己的帽子,漏出了“资深的发型”。

面试官也愣住了,看着你“资深的发型”,当即就握住了你的手:你就是我要找的人才。不面了,就你了,明天来报道!

入职

入职之后你第一件事情就是看看这个公司的代码。

当你看第一个接口的时候,发现根本没有做幂等。

当你看第二个接口的时候,发现就是靠业务表的唯一索引做的幂等。

当你看第三个接口的时候,Redis 的方案跃然纸上。

突然一个哥们气喘吁吁的跑过来找昨天面试你的老登,说:快,又出问题了,帮忙删除一个 Redis key。

于是,你抽过去准备看一下怎么操作。

不经意间看到了老登正在写一个文档,题目叫做《一种分布式系统中数据唯一性的消息幂等保障策略》。

老登看到你过来了,说:正好,你来写这个文档,我已经把名字给你想好了,你就按照这个写,把你昨天的思路写清楚,到时候我去汇报。

你兴奋的问:汇报过了之后我们要按照这个方案落地吗?

老登说:不不不,落地干啥啊,多麻烦啊,方案汇报嘛,体现一下我们在技术方面的时刻,在领导面前去刷个脸,所以你要多用一些高大上的词,越晦涩难懂越好。哦,对了,我顺便教教你怎么“删除 Redis key”,以后就让他们找你了。这帮老登,大半夜的,老是给我打电话。

与这就叫“面试造火箭,工作拧螺丝!”相似的内容:

这就叫“面试造火箭,工作拧螺丝!”

你好呀,我是歪歪。 我想再讨论一下上次的这篇文章《哎,被这个叫做at least once的玩意坑麻了》 因为有些朋友看完之后再评论区给出了自己的思考,也有朋友和我私聊,分享了自己的看法,我觉得有些想法很好,所以我决定一鱼两吃,再聊聊这个问题。 假设,我们是一场面试,面试官给你抛出了这样一个问题:

Rust中的并发性:Sync 和 Send Traits

在并发的世界中,最常见的并发安全问题就是数据竞争,也就是两个线程同时对一个变量进行读写操作。但当你在 Safe Rust 中写出有数据竞争的代码时,编译器会直接拒绝编译。那么它是靠什么魔法做到的呢? 这就不得不谈 Send 和 Sync 这两个标记 trait 了,实现 Send 的类型可以在多线程

过年必备!亲戚计算器「GitHub 热点速览 v.23.02」

过完这周大家就要开始为期 7 天的春节长假了,当然有些 HG 小伙伴拥有了 10+ 天的长假就低调点不要告诉他人,以免招人妒忌。春节必经的事情可能就是走亲戚了,所以本周特推选取了一个研究亲戚关系的资深项目,助你不用母上大人开口就能叫出这位不知名的亲戚是你的谁。 回到本周的 GitHub 趋势,新上线

golang开发 gorilla websocket的使用

很多APP都需要主动向用户推送消息,这就需要用到长连接的服务,即我们通常提到的websocket,同样也是使用socket服务,通信协议是基本类似的,在go中用的最多的、也是最简单的socket服务就是gorilla/websocket,它有21.1K的star,足以说明它的受欢迎程度, 它的git

循序渐进讲解负载均衡vivoGateway(VGW)

在大规模业务场景中,已经不可能通过单机提供业务,这就衍生出了负载均衡的需求。为了满足合适可靠的负载,本文将从简单的基础需求出发,一步步推进并解释如何建立负载均衡平台。

WPF网格类型像素着色器

由于WPF只能写像素着色器,没法写顶点着色器,所以只能在这上面做文章了 刚好有个纹理坐标TEXCOORD输入可用,而且值的范围是已知的0-1,左上角是原点,这就好办了 例子 索引 二分网格 使用ceil 0-1移动定义域到-0.5 - 0.5,然后向上取整变成 0 / 1 float4 main(f

递归在多级数据结构中的简单应用

哈喽,我是小码,半年多没更新了,这段时间换了新工作,工作也很忙。后续会尽量多写点,坚持确实是一件很难,很酷的事情。最近在公司负责开发商品有关的开发,商品包含类型、款式等属性,而类型可能有一级类型、二级类型甚至是三级类型,针对这种多级分类,这就就不好使用简单的查询了。之前也写了一篇文章,Java递归实

基于.NetCore开发博客项目 StarBlog - (21) 开始开发RESTFul接口

## 前言 最近电脑坏了,开源项目的进度也受到一些影响 这篇酝酿很久了,作为本系列第二部分(API接口开发)的第一篇,得想一个好的开头,想着想着就鸽了好久,索性不扯那么多了,直接开写吧~ ## 关于RESTFul 网上很多相关的文章都要把RESTFul历史来龙去脉给复制一遍,所以我这就不重复了,现在

数据库深分页介绍及优化方案 | 京东云技术团队

在前端页面显示,为了避免一次性展示全量数据,通过上下翻页或指定页码的方式查看部分数据,就像翻书一样,这就利用了MySQL的分页查询。

适用于linux的bilibiliB站直播间弹幕爬虫脚本

适用于linux的bilibiliB站直播间弹幕爬虫脚本,命令行运行之,输入到命令行,部分内容参考自网络,代码底部可见原始代码出处 BUFF:然而,经测试,每次爬只能读取10条弹幕记录,这就使得在(sleeptime*10)(每秒)<弹幕新增量(每秒)时出现弹幕丢失的情况,此时需要调短sleepti