C# 使用Redis实现粉丝好友互粉数据存储和查询

7 篇文章 0 订阅
3 篇文章 0 订阅

因开发需要加入粉丝关注模块.

 

在好友关注关系中,主要有以上三种状态,即:


我的粉丝(fans)
我的关注(follow)
互粉(mutual)

设计思路如下:


​总体思路我们采用redis里面的zset完成整个功能, 原因是zset有排序(我们要按照关注时间的倒序排列), 去重(我们不能多次关注同一用户)功能. 一个用户我们存贮两个集合, 一个是保存用户关注的人 另一个是保存关注用户的人.
具体命令参考:http://doc.redisfans.com/sorted_set/index.html
用到的命令是:
​ 1、 zadd 添加成员:命令格式: zadd key score member [score …]
​ 2、zrem 移除某个成员:命令格式: zrem key member [member ...]
​ 3、 zcard 统计集合内的成员数:命令格式: zcard key
​ 4、 zrange 查询集合内的成员:命令格式: ZRANGE key start stop [WITHSCORES]
​ 描述:返回指定区间的成员。其中成员位置按 score 值递增(从小到大)来排序。 WITHSCORES选项是用来让成员和它的score值一并返回.
​ 5、 zrevrange跟zrange作用相反
​ 6、zrank获取成员的排名:命令格式: zrank key member
​ 描述:返回有序集key中成员member的排名。成员按 score 值递增(从小到大)顺序排列。排名以0开始,也就是说score 值最小的为0。返回值:返回成员排名,member不存在返回nil.
​ 7、 zinterstore 取两个集合的交集:命令格式:ZINTERSTORE destination numkeys key key ...] [AGGREGATE SUM|MIN|MAX]
​ 描述:计算给定的一个或多个有序集的交集。其中给定 key 的数量必须以 numkeys 参数指定,并将该交集(结果集)储存到 destination 。默认情况下,结果集中某个成员的 score 值是所有给定集下该成员 score 值之 和 。
返回值:保存到 destination 的结果集成员数。

 

Redis实现思路

 

1. 添加关注


添加关注分为两步:

将对方Bid添加到自己的关注A列表中;

Redis::ZADD("A:follow", time(), B)

将自己的Aid添加到对方B的粉丝列表中:

Redis::ZADD("B:fans", time(), A)

2. 取消关注


取消关注同样分为两步:

将对方Bid从自己A的关注A列表中移除;

Redis::ZREM("A:follow", B)

将自己的Aid从对方的粉丝B列表中移除:

Redis::ZREM("B:fans", A)

3. 关注列表

Redis::ZRANGE("A:follow", 0 , -1)

4. 粉丝列表

Redis::ZRANGE("A:fans", 0 , -1)

5. 人物关系


5.1、 单向关注
A单向关注B,要同时满足两个条件:1、A的关注列表中有B(或B的粉丝列表中有A);2、A的粉丝列表中没有B(或B的关注列表中没有A)。

Redis::ZSCORE("A:fans", B) #未返回分数

Redis::ZSCORE("A:follow", B) #返回分数

5.2、 是否互粉
A和B是否互粉,要同时满足两个条件:1、A的关注列表中有B(或B的粉丝列表中有A);2、A的粉丝列表中有B(或B的关注列表中有A)。同时成立才为互粉。

Redis::ZSCORE("A:fans", B) #返回分数

Redis::ZSCORE("A:follow", B) #返回分数

6. 数量相关


6.1、 关注数
Redis::ZCARD("A:follow"); #返回数量

6.2、 粉丝数
Redis::ZCARD("A:fans"); #返回数量

7. 排序取出所有的人


7.1、根据关注的时间倒叙取出用户的id

Redis::ZREVRANGE("A:fans", 0, -1, TRUE); #倒序取值

7.2、根据关注时间顺序取出用户的id

Redis::ZRANGE("A:fans", 0, -1, TRUE); #顺序取值

8.获取互粉列表Mutuals

Redis::SInter("A:follow","B:follow"); 

Redis::SInterStore("A_B:follow" , "A:follow","B:follow"); //选存储

Redis::ZRANGE("A_B:follow", 0 , -1)//再获取

具体功能实现 代码分为8个部分

public class RedisFollowHelper

  {

      //(FOLLOW_USERS)关注表

      private static string FOLLOW_USERS = "gz:{0}:follow";

      //(FANS_USERS)粉丝表

      private static string FANS_USERS = "gz:{0}:fans";



      private static string INFO_USERS = "uinfo:{0}";

      private static int INFO_USERS_TIME = 86400;





      /// <summary>

      /// 0.判断是否已经关注了

      /// </summary>

      /// <param name="cid"></param>

      /// <param name="followId"></param>

      /// <returns></returns>

      public static bool isFollowed(long cid, long followId)

      {

          string followUsersKey = string.Format(FOLLOW_USERS, cid);

          object value = RedisHelper.ZScore(followUsersKey, followId);

          return value != null;

      }

      followId去关注别人,判断是否已关注

      //public static bool isFollowedByFollowId(long followId, User user)

      //{



      //    string fanUsersKey = string.Format(FANS_USERS, followId);

      //    Object value = RedisHelper.HGet(fanUsersKey, user.getId().ToString());

      //    return value != null;

      //}



      /// <summary>

      /// 1. 添加关注

      /// </summary>

      /// <param name="cid"></param>

      /// <param name="followId"></param>

      public static void follow(long cid, long followId)

      {

          long dt = CFunc.GetTimeStamp(DateTime.Now);

          //1、将对方id添加到自己的关注列表中;

          string followUsersKey = string.Format(FOLLOW_USERS, cid);

          RedisHelper.ZAdd(followUsersKey, (dt, followId));



          //2、将自己的id添加到对方的粉丝列表中:

          string fanUsersKey = string.Format(FANS_USERS, followId);

          RedisHelper.ZAdd(fanUsersKey, (dt, cid));

      }

      /// <summary>

      /// 2. 取消关注

      /// </summary>

      /// <param name="cid"></param>

      /// <param name="followId"></param>

      public static void unFollow(long cid, long followId)

      {

          //1、将对方id从自己的关注列表中移除;

          string followUsersKey = string.Format(FOLLOW_USERS, cid);

          RedisHelper.ZRem(followUsersKey, followId);



          //将自己的id从对方的粉丝列表中移除:

          string fanUsersKey = string.Format(FANS_USERS, followId);

          RedisHelper.ZRem(fanUsersKey, cid);

      }

      /// <summary>

      /// 3. 关注列表

      /// </summary>

      /// <param name="userId">查看者的用户id</param>

      /// <param name="start"></param>

      /// <param name="stop"></param>

      /// <returns></returns>

      public static string[] Follows(long userId, long start = 0, long stop = -1)

      {

          string followsUsersKey = string.Format(FOLLOW_USERS, userId);

          string[] objectMap = RedisHelper.ZRange(followsUsersKey, start, stop);

          return objectMap;

      }

      /// <summary>

      /// 4. 粉丝列表

      /// </summary>

      /// <param name="followId"></param>

      /// <param name="start"></param>

      /// <param name="stop"></param>

      /// <returns></returns>

      public static string[] Fans(long userId, long start = 0, long stop = -1)

      {

          string fansUsersKey = string.Format(FANS_USERS, userId);

          string[] objectMap = RedisHelper.ZRange(fansUsersKey, start, stop);

          return objectMap;

      }



      /// <summary>

      /// 5. 人物关系

      /// 1.cidA单向关注cidB

      /// </summary>

      /// <param name="cidA"></param>

      /// <param name="cidB"></param>

      public static bool LinkAtoB(long cidA, long cidB)

      {

          string fanKey = string.Format(FANS_USERS, cidA);

          string followKey = string.Format(FOLLOW_USERS, cidA);

          //A单向关注B,要同时满足两个条件:1、A的关注列表中有B(或B的粉丝列表中有A);2、A的粉丝列表中没有B(或B的关注列表中没有A)。

          if (RedisHelper.ZScore(followKey, cidB) > 0 && RedisHelper.ZScore(fanKey, cidB) == null)

          {

              return true;

          }

          return false;

      }

      /// <summary>

      /// 2.是否互粉

      /// </summary>

      /// <param name="cidA"></param>

      /// <param name="cidB"></param>

      /// <returns></returns>

      public static bool LinkAandB(long cidA, long cidB)

      {

          string fanKey = string.Format(FANS_USERS, cidA);

          string followKey = string.Format(FOLLOW_USERS, cidA);

          //A和B是否互粉,要同时满足两个条件:1、A的关注列表中有B(或B的粉丝列表中有A);2、A的粉丝列表中有B(或B的关注列表中有A)。同时成立才为互粉。

          if (RedisHelper.ZScore(followKey, cidB) > 0 && RedisHelper.ZScore(fanKey, cidB) > 0)

          {

              return true;

          }

          return false;

      }



      /// <summary>

      /// 6.1、 我的关注数

      /// </summary>

      /// <param name="userId"></param>

      /// <returns></returns>

      public static long FollowsCount(long userId)

      {

          string followsCountKey = string.Format(FOLLOW_USERS, userId);

          long iCount = RedisHelper.ZCard(followsCountKey);

          return iCount;

      }

      /// <summary>

      /// 6.2、 我的粉丝数

      /// </summary>

      /// <param name="userId"></param>

      /// <returns></returns>

      public static long FansCount(long userId)

      {

          string fansCountKey = string.Format(FANS_USERS, userId);

          long iCount = RedisHelper.ZCard(fansCountKey);

          return iCount;

      }



      /// <summary>

      /// 7.1根据粉丝添加的时间倒叙取出用户的id

      /// </summary>

      /// <param name="cid"></param>

      /// <param name="start"></param>

      /// <param name="stop"></param>

      /// <returns></returns>

      public static string[] FansByTimeDesc(long cid, long start = 0, long stop = -1)

      {

          string fansCountKey = string.Format(FANS_USERS, cid);

          string[] objectMap = RedisHelper.ZRevRange(fansCountKey, start, stop);

          return objectMap;

      }



      /// <summary>

      /// 8.获取共同关注列表

      /// </summary>

      /// <param name="cidA"></param>

      /// <param name="cidB"></param>

      /// <param name="start"></param>

      /// <param name="stop"></param>

      /// <returns></returns>

      public static string[] Mutuals(long cidA, long cidB, long start = 0, long stop = -1)

      {

          string followsUsersA = string.Format(FOLLOW_USERS, cidA);

          string followsUsersB = string.Format(FOLLOW_USERS, cidB);

          string[] objectMap = RedisHelper.SInter(followsUsersA, followsUsersB);

          //也可以使用RedisHelper.SInterStore,存储起来再查询

          if (stop > start)

          {

              long iCount = objectMap.Length;

              if (start <= iCount)

              {

                  if (stop > iCount)

                  {

                      stop = iCount;

                  }

                  int j = 0;

                  string[] newMap = new string[] { };

                  for (long i = start; i < stop; i++)

                  {

                      newMap[j] = objectMap[i];

                      j++;

                  }

                  return newMap;

              }

          }

          return objectMap;

      }



      /// <summary>

      /// 7.2根据关注的时间倒叙取出用户的id

      /// </summary>

      /// <param name="cid"></param>

      /// <param name="start"></param>

      /// <param name="stop"></param>

      /// <returns></returns>

      public static string[] FollowByTimeAsc(long cid, long start = 0, long stop = -1)

      {

          string fansCountKey = string.Format(FOLLOW_USERS, cid);

          string[] objectMap = RedisHelper.ZRevRange(fansCountKey, start, stop);

          return objectMap;

      }





      public static JObject getUserInfo(long cid, bool Refresh = false)

      {

          string UsersKey = string.Format(INFO_USERS, cid);

          string userstr = "";

          if (Refresh == false)

          {//是否强制刷新数据

              userstr = RedisHelper.Get(UsersKey);

          }

          JObject jo = new JObject();

          if (string.IsNullOrEmpty(userstr))

          {

              

              //查询数据库数据

              DataSet ds = ;



              if (ds.Tables[0].Rows.Count > 0)

              {

                  jo.Add("cid", cid);

                  jo.Add("nickname", CFunc.SafeToStr(ds.Tables[0].Rows[0]["nickname"]));

                  jo.Add("headpic", 1);// CFunc.ObjToInt32(ds.Tables[0].Rows[0]["regtime"]);

                  jo.Add("xkpic", 1);// CFunc.ObjToInt32(ds.Tables[0].Rows[0]["logindate"]);





                  RedisHelper.Set(UsersKey, jo, INFO_USERS_TIME);



              }

              ds.Clear();

          }

          else

          {

              jo = (JObject)JsonConvert.DeserializeObject(userstr);

              RedisHelper.Expire(UsersKey, INFO_USERS_TIME);

          }

          return jo;

      }

      internal static bool infoChanged(long cid)

      {

          string UsersKey = string.Format(INFO_USERS, cid);

          if (RedisHelper.Exists(UsersKey))

          {

              RedisHelper.Del(UsersKey);

              return true;

          }

          return false;

      }

  }

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值