Skip to content

真的要动起来了

先来唠唠

今晚和学员开完最后一个会议后,带着一个20多岁的同事去锻炼,据他所说他已经有一年多没有专门花时间去运动过了,现在比之前胖了20多斤

跑了二十多分钟,气喘吁吁,满头大汗,这样可不行啊,身体素质太差了,所以我决定以后只要工作不多,就带着他去运动。

在看这篇文章的你们想必大多数是程序员,工作的时候一直坐着,我建议你们平时工作和学习无论有多忙,都要花一点时间去锻炼,赚钱固然重要,但身体永远是革命的本钱

运动和学习在一个方面是一样的,那就是要坚持,如果你也和我这个同事一样甚至更严重,一定要早点动起来!

话就唠到这,重要的还是下面的Java面经

面经分享

守护线程在扫描表中状态为NEW的记录进行处理的时候,如果有多个节点多个守护线程都同时扫描表中的记录,如何避免并发操作,一条表记录怎么避免被重复处理了?

示例回答:

在实际分布式系统中很常见,核心思路就是让多个节点或线程在处理同一条记录时能够“互斥”操作。举个例子,我们可以用数据库的行级锁机制,比如在查询的时候用SELECT FOR UPDATE SKIP LOCKED这样的语句(Oracle或PostgreSQL),或者SQL Server里的WITH (ROWLOCK, UPDLOCK, READPAST)。这样执行的时候,数据库会直接把符合条件的记录锁住,其他线程来查的时候会发现这条记录已经被锁了,直接跳过,这样就避免了多个线程同时捞到同一条数据的情况。

还有一种常见做法是加版本号乐观锁。比如表里加个version字段,处理的时候先查当前的版本号,更新的时候必须匹配这个版本号才能成功。比如执行UPDATE table SET status='PROCESSING', version=version+1 WHERE id=123 AND version=5,如果其他线程已经更新了这条数据,版本号变了,这条SQL就不会生效,这样后面来的线程就知道这条记录已经被处理过了。

如果是跨多个服务节点的情况,可以结合分布式锁,比如用Redis或者Zookeeper。比如处理前先用Redis的setnx命令抢锁,只有拿到锁的节点才能处理这条记录,处理完再释放锁。不过这里要注意锁的过期时间和续期问题,防止死锁或者锁提前释放导致的问题。

另外在设计表的时候,可以通过状态机的约束来规避重复处理。比如规定状态只能从NEW到PROCESSING再到COMPLETED,绝对不能回退。这样即使有并发,数据库的唯一性约束和