【解决方案+问题分析】微信分销会员上下级关系出现混乱,剖析全过程

微信分销会员上下级关系出现混乱,从反馈到分析问题如何发生 ,再到如果解决。在此把实际项目遇到的问题分享出来,以供以后和网友参考。

某日,接到一通领导打来的一通电话。电话主要内容是他曾接到一个用户的反馈电话,说道我们有一个项目中,微信会员上下级关系存在混乱,用户a关注的用户b,用户b却关注的用户的a。上下级关系很乱,还有很多用户存在一些,用户a关注了用户b,用户b的推荐好友列表中却没有用户a的存在……

当我拿到这个问题之后,首先的态度很是质疑,代码应该都是没有问题的,可能会存在一些数据没有对上。此处我需要在整个数据库中查找出所有的上下级混乱关系的会员。

什么是上下级混乱关系?

  1. 用户b的上级是用户a,用户a的上级是用户b。(b>a>b)
  2. 用户c的上级是用户b,用户b的上级是用户a,用户a的上级是用户c。(c>b>a>c)

所谓的混乱便是出现了这种无线循环的关系,那么,如果查找出来这种上下级关系呢?

怎么解决?

根据以上的举例,能够很明显的能看出来一个规律便是这种会员关系中,一圈之中至少存在两个会员的?自己上级的上级……的上级有可能是自己。只要找出自己所有的上级来查询是否存在两个相同会员就好了。

首先写一个脚本来执行,如果web执行超时,可采用命令行方式执行。

以下以TP框架语法进行举例:

/**
	 * 排错函数
	 */
	public function member_level(){
		$Model = M('weishop_member');
		
		//查询出所有有上级的用户
		$exist_sql = "SELECT wm_id,wm_parent_id FROM weishop_member WHERE wm_parent_id !=0";
		$exist_parent_users = $Model->query($exist_sql);
//		debug_show($exist_parent_users);
		$num = 0;
		$error_users = array();
		foreach($exist_parent_users as $val){
			//此处屏蔽的代码可以在调试时放开,测试数据是否正常,避免逻辑错误导致死循环超时
//			if($num==2){
//				exit;
//			}
			$user_status = $this->level_debug($val['wm_id'],$val['wm_parent_id'],true);
			if($user_status===3){
				$error_users[] = $val['wm_id'];
			}
			$num++;
		}
		echo '<br/>error users:'.implode(',', $error_users).'<br/>';
		echo '<br/>Check OK!';
		//拿出一个数据来进行 测试排错
//		$this->level_debug($exist_parent_users[0]['wm_id'],$exist_parent_users[0]['wm_parent_id'],true);
		echo 'Exist users number:'.count($exist_parent_users);
		
	}
	/**
	 * 递归排错
	 * @desc  查询当前用户的上级祖(祖父)中是否存在循环(儿子)
	 * @param  $wm_id     会员id
	 * @param  $parent_id 上级id
	 * @param  $init      是否初始化,即首次执行
	 * @return  1:用户正常。0:用户还有上级。3:用户关系出错
	 */
	private function level_debug($wm_id,$parent_id,$init=false){
		static $user_id = 0;//被检查的用户
		static $_son = array();//儿子组
		static $num = 0;//循环执行次数
		
		//empty  如果是初始化执行则清空
		if($init){
			$_son = array();
			$num = 0;
			$user_id = $wm_id;
		}
		$num++;
		if(!isset($_son[$wm_id])){
			//如果儿子组中不存在当前用户,则加入当前用户,继续向下查找祖父
			$_son[$wm_id] = array(
				'wm_id'=>$wm_id,
				'wm_parent_id' => $parent_id
			);
		}
		//调试时测试执行次数,防止逻辑错误,出现死循环超时
		if($num==5){
//			debug_show($wm_id);
//			debug_show($_son);
		}
		$Model = M('weishop_member');
		
		//查询当前上级
		$query_parent_sql = "SELECT wm_id,wm_parent_id FROM weishop_member WHERE wm_id = '$parent_id'";
		$parent_user = $Model->query($query_parent_sql);
		//如果上级存在 并且上级用户还有上级则继续递归
		
		//条件:1.当前用户上级存在。2.上级用户还存在上级
		if(is_array($parent_user) && isset($parent_user[0]) && $parent_user[0]['wm_parent_id']!=0){
			$buf = $parent_user[0];
			
			//如果当前用户上级的上级存在于儿子组中则进入判断
			if(isset($_son[$buf['wm_parent_id']])){
				echo '<font color="red">error!</font> user id:'.$user_id.'&nbsp;&nbsp;'.'parent_id :'.$buf['wm_id'].'&nbsp;&nbsp;'.'parent includes '
				.implode(',', array_keys($_son)).' execute:'.$num .'<br/> ';
				return 3;
//				exit;
			}
			//符合条件 继续进入循环探寻祖父
			$this->level_debug($buf['wm_id'],$buf['wm_parent_id']);
			return 0;
		}
		//数据量过多,则关闭正常用户结果显示
//		echo 'user id:'.$user_id.'&nbsp;&nbsp;'.'parent_id :'.$parent_id.'&nbsp;&nbsp;'.'parent includes '
//		.implode(',', array_keys($_son)).' execute:'.$num .'<br/> ';
		return 1;
	}

以上代码经过多次修改后的,并不是一气呵成。需要用到的朋友可以仔细分析下逻辑。

经过多次的修改,以上的代码没有超时执行,跟用户数量还是有关系,毕竟只有几千个。返回的内容如下:

说明一下,红色error都是关系混乱的用户,在最后我们可以看到出错的用户抱(bāo)括2和116。所存在上级的用户总共有3158个。

那么问题看来都是由2和116的关系混乱导致的,只需要将他们更正后即可。之后便联系了用户id分别为2和116的用户,将他们的注册时间和推荐时间做一了解,将2的上级清空,恢复为0.

那么再执行刚才的排错来看看结果。

这次检查之后,发现并没有关系混乱的用户。一切恢复平静。虽然说目前的问题解决了,但并不意味着,以后都会正常,问题的根源还没有找出来。

怎么修复?

带着问题继续在代码中寻找,来到会员绑定的逻辑处。

/**
	 * 绑定微信上下级(未修复)
	 * @param   $openid    当前用户openID
	 * @param   $parent_id 上级用户id
	 * @return  bool
	 */
	 public function bingding($openid,$parent_id){
	 	//检测当前用户是否有上级并且上级不能为自己,没有则继续 
	 	$res = $this->where("wm_openid ='$openid' && wm_id != '$parent_id' && wm_parent_id ='0'")->save(array("wm_parent_id" => $parent_id));
		if($res){
			return true;
		}
	 }

粗略一看几乎看不出来啥问题,绑定时首先判断的是当前用户的上级是否存在,如果有自然不能附加上级了。如果没有的情况下,并且上级不能为自己,否则自己跟自己成为上级就乱了套。当时写的代码本以为是正常。结果出了一个隐性bug。

怎么发生的呢?

上面的逻辑会忽略掉,下级下级的用户偶然一天变成自己的上级(可能是因为自己失误的去扫码,扫了自己辛辛苦苦下级用户的码,反而让下级成为了自己的上级),导致关系混乱,在用户方面可能会导致佣金等利益计算错误,在平台层面会影响一笔损失,在此可以给各位一个提醒,凡是跟钱有关的一定要慎重!

至于修复呢,而此处只需要增加一层判断即可解决。

修改后代码奉上:

/**
	 * 绑定微信上下级(已修复)
	 * @param   $openid    当前用户openID
	 * @param   $parent_id 上级用户id
	 * @return  bool
	 */
	 public function bingding($openid,$parent_id){
	 	//检测是否有下级
		$sql = "SELECT count(a.wm_id) as count FROM `weishop_member` as a  join `weishop_member` as b on a.wm_parent_id = b.wm_id WHERE b.wm_openid='{$openid}';";
	 	
	 	$count_res = $this->query($sql);
		if(is_array($count_res) || count($count_res)==1){
			if(isset($count_res[0]['count']) && $count_res[0]['count']>0){
				return false;
				//如果有下级则不能成为别人的下级
			}
		}
		
	 	//检测当前用户是否有上级并且上级不能为自己,没有则继续 
	 	$res = $this->where("wm_openid ='$openid' && wm_id != '$parent_id' && wm_parent_id ='0'")->save(array("wm_parent_id" => $parent_id));
		if($res){
			return true;
		}
	 	return false;
	 }

如果自己已经有了下级用户就不能成为别人的下级,这样一来,就不会出现这种死循环。当然解决的方案不只是这一个,符合业务逻辑就好。

修改好代码检查无误后立即将代码更新至服务器,以防止出现更多差错。

基本上此次的bug检查及解决方案就到此结束了,过程中一些细节性东西不太好描述,最好去实际实践一下,或者是实际用到时慢慢体会。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏腾讯技术工程官方号的专栏

你不知道的Android SDK安全测试

image.png 作者介绍:anglia,2014年加入腾讯TEG,一直致力于信鸽和MTA两款产品的移动终端 引言 作为Android手机用户中的一枚残粉...

30450
来自专栏数据和云

DBA生存警示:系统存储级误删除案例及防范建议

编辑手记:对于资深的老DBA们,他们在漫长的职业生涯中养成了很多稀奇古怪的守则,以在复杂多变的环境中“幸存”,这源于无数血泪的教训,我曾经在《数据安全警示录》一...

334100
来自专栏FreeBuf

APT攻击演练之捕鱼人的构想

两个环节:beef-xss钓鱼环节(建议使用服务器)、Nday钓鱼环节(很好用)、钓鱼框架环节(便携好用)

14740
来自专栏FreeBuf

一大波iCloud钓鱼网站来袭 果粉们会分辨吗?

国外的FireEye实验室有一套自动化系统,这套系统能够主动侦测最新注册的恶意域名。所谓的恶意域名,绝大部分都是伪装成很多人知道的常用域名,以此来达到“恶意”的...

37550
来自专栏FreeBuf

记一次Linux服务器被入侵后的检测过程

0x00 前言 故事是这样的,大年初一,客户反应他们服务器无法访问,查看路由,发现某oracle+tomcat服务器UDP流量超大,把带宽占完了,过年嘛,客户那...

45860
来自专栏BeJavaGod

分布式系统的那些事儿(四) - MQ时代的通信

之前在讲RPC通信的各种好处,特别好用,但是RPC并不是万能的,也并不是适用于各种场景的,因为他是同步的;现如今很多场景下的调用都是异步的,系统A调用B后,并不...

37440
来自专栏菩提树下的杨过

silverlight 4 tools for vs2010无法在vs2010 SP1上安装的解决办法

环境:英文版vs2010 sp1 + vs2013 RC 90天体验版 原来可以正常做silverilght 4 项目开发,今天因为vs2013 RC过了90天...

22950
来自专栏FreeBuf

记一次服务器被入侵的调查取证

*本文原创作者:fish1983,本文属FreeBuf原创奖励计划,未经许可禁止转载

98610
来自专栏FreeBuf

你说安全就安全?对红芯浏览器的一次安全测试

近日,红芯浏览器“套壳”一事被网络舆论炒的沸沸扬扬。红芯浏览器被官方标榜为“安全、稳定、可控的企业浏览器”,其中“自主可控”一项已经被舆论所质疑,但是被官方放在...

9020
来自专栏杨建荣的学习笔记

一个简单的bigfile tablespace无法扩展的案例处理 (r8笔记第31天)

最近帮助开发的同学处理了一个简单的问题,想通过这个问题来反思一下。 在一天下午的时候,开发的同事突然找到我说,有一个开发的数据库貌似有些表空间的问题,...

29470

扫码关注云+社区

领取腾讯云代金券