微信红包的24小时退回机制?

清尘V 发布于 2016/06/06 16:10
阅读 1K+
收藏 0
请教个问题:微信中的红包退回机制是如何实现的?定时扫描的话是不是消耗资源太大?如果是一个红包一个定时线程的话,电脑不支持太多线程吧?各位大神有解决思路吗?
加载中
1
OSC管理员
OSC管理员
经典的高效定时器算法:双链表 小根堆 时间轮;
mi-la-king
mi-la-king
那就 基于链表的定时器 这样不?
1
f
fegaf

为什么你把电脑性能想得如此不堪,处理时间都能超过10s了,腾讯用户这么舍得掏钱,不会加不起服务器的;

扫完第一遍,不就可以排序了么,用链表排好,把最早超时的排在第一个,如果第一个都没超时,后面根本就不用扫了,没超时的肯定占大多数,所以需要处理的数据比你想象的数据量要少,而后面新加进来的肯定不可能马上超时,更简单了,放在队尾保证顺序就可以了

清尘V
清尘V
我只是拿红包举例而已,现在可以简单理解就是1s扫一次,那这个资源消耗是不是很大呢?如果说处理未支付订单,超时自动取消(譬如15分钟未支付自动取消,精确到秒),白天和晚上也是不一样的,你会发现晚上大部分时间CPU空转消耗?
0
mi-la-king
mi-la-king
怎么会一个红包一个定时线程。。。。肯定是丢一起处理,丢到哪里就不知道
mi-la-king
mi-la-king
@痞子韦森特 没有具体代码
清尘V
清尘V
嗯嗯 但是具体方案 有吗
0
Broly
Broly
我感觉是发一个红包就加入一个定时队列。到时间了执行任务,如果该红包还有剩余就退回。
清尘V
清尘V
问题就是 “到时间”怎么判断?
0
IdleMan
IdleMan
超时的红包很少,数据量少了什么事都好办
清尘V
清尘V
我只是举个例子而已,就是希望得到一个实时的定时过期处理
0
HeartArea
HeartArea

没那么复杂吧,每个红包生成的时候就增加一个失效时间属性,每次打开红包是就查询一下过没过期啊,和redis的key失效策略很像啊

清尘V
清尘V
微信红包是没有打开红包的时候也会退回
0
熊猫也天真
熊猫也天真

比较赞同上面那位兄弟说的时间轮算法,英文名 Timing wheel,可以去搜索一下。

具体做法就是搞一个双向链表。根据你的时间间隔,设置好固定的格子。每一个格子又放了list或者

array都行,里面装的就是红包信息。然后一个线程根据你的时间间隔不停的循环这个链表。凡是指针

指到的这个格子下的所有数据,全部就开始执行退款操作即可(同步或者异步,看业务逻辑)。如下

图,希望对你有所帮助:


Wanye_
Wanye_
比较赞同这种方式,释放之后又将此时段的新的红包列表添加进去。
0
boystudio
boystudio
关键是要准时到什么样的程度,假如误差允许5分钟,那么开个线程,每5分钟检查一次是可以接受。因为用户退款不需要那么准时。但当用户点开一次红包,肯定查询一次状态,这时候就很容易知道哪个过期。没人点开没人看,who care 它什么时候过期?1个小时检查一次都可以的。
boystudio
boystudio
回复 @痞子韦森特 : 具体情况具体分析,你可以避开问题的锋芒。高手往往是巧妙地避开了坑,而不是跳到坑里;新手往往是看见眼前有坑还要往里面跳,或者根本看不到坑……你非要实时的话,那肯定有很多的定时器,花很多的运算资源,一台服务器肯定很难解决,得要上集群,微信红包每天量都很大,他们不会傻到这样去解决问题。非要一台服务器上解决,那么紧张的计算资源,进程都得要排队,你觉得还能准时吗?
清尘V
清尘V
如果说是实时的呢 并且每次处理都会超过10s呢
0
LucEsape
LucEsape
// 给你个暴力的方法 参考下
import java.util.ArrayList;
import java.util.List;

class RedPacket {
	public boolean isTimeout(int hours) {
		// 是否 hours 内 还未被领取
		return true;
	}

	public void back() {
		// 未领取,退回
	}
}

public class RedPacketTimeoutHandler {

	private final List<RedPacket> list = new ArrayList<>();

	public void handler() throws InterruptedException {
		int listSize = list.size();

		for (int i = 0; i <= listSize;) {
			if (listSize == 0)
				Thread.sleep(5000);
			else {
				RedPacket redPacket = list.get(i);
				if (redPacket.isTimeout(24)) {
					redPacket.back();
					list.remove(i);
					listSize = list.size();
					i = i - 1;
				}
				i = i + 1;
				if (i == listSize) {
					i = 0;
				}
			}
		}
	}
}



LucEsape
LucEsape
回复 @痞子韦森特 : 这个单线程就能执行了,多线程就需要设定资源的抢占策略
清尘V
清尘V
加入说每个线程处理都会超过10s呢
0
for。
for。
nginx里有个红黑树,用来处理超时,效率比时间轮高
返回顶部
顶部