前言
排行榜作为互联网应用中几乎必不可少的一个元素,其能够勾起人类自身对比的欲望,从而来增加商品的销量。排行榜的实现方式基本大同小异,大部分都基于 Redis 的有序集合 sorted set 来实现。本文通过了商品销售排行榜这一模型,来进行演示,同时您还可以根据本文章实现
文章的点赞排行,
积分排行等..
项目Github地址:https://github.com/haoxiaoyong1014/springboot-redis-examples/tree/master/springboot-redis-ranking
需求

1,按照商品销量进行排行
2,可以获得指定商品的排名
3,显示实时销售动态情况

一,首先看一下效果图:
image

准备工作: 定义两个 key值

public static String SALES_LIST = "phone:sales:list";
public static String BUY_DYNAMIC = "phone:buy:dynamic"
public static String separator = "#";

二,添加依赖:

<dependency>
     <groupId>redis.clients</groupId>
     <artifactId>jedis</artifactId>
     <version>2.7.3</version>
</dependency>

三,本案例中使用的所有 redis命令:

获得销售排行榜上该商品的排名

命令实例描述
ZREVRANKZREVRANK key member返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递减(从大到小)排序。排名以 0 为底,也就是说, score 值最大的成员排名为 0

实例:

redis 127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES     # 测试数据
1) "jack"
2) "2000"
3) "peter"
4) "3500"
5) "tom"
6) "5000"

redis> ZREVRANK salary peter     # peter 的工资排第二
(integer) 1

redis> ZREVRANK salary tom       # tom 的工资最高
(integer) 0

返回值:

如果 member 是有序集 key 的成员,返回 member 的排名。
如果 member 不是有序集 key 的成员,返回 null

项目中所用实例:

 @Override
    public int phoneRank(int phoneId) {
        // 如果是排名第一, 返回的是0 ,因此如果为null 即不在排行榜上则返回-1
        Long zrank = jedis.zrevrank(Constants.SALES_LIST, String.valueOf(phoneId));
        return zrank == null ? -1 : zrank.intValue();
    }

获得销售动态:

命令实例描述
LINDEXLINDEX key index返回列表 key 中,下标为 index 的元素。

实例:

redis> LPUSH mylist "World"
(integer) 1

redis> LPUSH mylist "Hello"
(integer) 2

redis> LINDEX mylist 0
"Hello"

redis> LINDEX mylist -1
"World"

redis> LINDEX mylist 3        # index不在 mylist 的区间范围内
(nil)

返回值:

列表中下标为 index 的元素。
如果 index 参数的值不在列表的区间范围内(out of range),返回 nil

项目中的实例:

 @Override
    public List<DynamicInfo> getBuyDynamic() {
        List<DynamicInfo> dynamicList = new ArrayList<DynamicInfo>();
        for (int i = 0; i < 3; i++) {
           /* jedis.lindex(String key,int index)
            * 返回存储在指定键中的列表的指定元素。0是第一个元素,1是第二个元素
            */
            String result = jedis.lindex(Constants.BUY_DYNAMIC, i);
            if (StringUtils.isEmpty(result)) {
                break;
            }
            String[] arr = result.split(Constants.separator);
            long time = Long.valueOf(arr[0]);
            String phone = arr[1];
            DynamicInfo vo = new DynamicInfo();
            vo.setPhone(phone);
            vo.setTime(StringUtil.showTime(new Date(time)));
            dynamicList.add(vo);
        }

购买商品

命令实例描述
ZINCRBYZINCRBY key increment member为有序集 key 的成员 member 的 score 值加上增量 increment ,当 key 不存在,或 member 不是 key 的成员时, ZINCRBY key increment member 等同于 ZADD key increment member

实例:

redis> ZSCORE salary tom
"2000"

redis> ZINCRBY salary 2000 tom   # tom 加薪啦!
"4000"

返回值:

member 成员的新 score 值,以字符串形式表示

项目中实例:

@Override
    public void buyPhone(int phoneId) {
        // 购买成功则对排行榜中该手机的销量进行加1
        jedis.zincrby(Constants.SALES_LIST, 1, String.valueOf(phoneId));
        // 添加购买动态
        long currentTimeMillis = System.currentTimeMillis();
        String msg = currentTimeMillis + Constants.separator + phones.get(phoneId - 1).getName();
        //将字符串添加到指定的key中存储列表的头部(LPUSH)或尾部(RPUSH)
        jedis.lpush(Constants.BUY_DYNAMIC, msg);
    }

添加购买动态:

命令实例描述
LPUSHLPUSH key value [value …]将一个或多个值 value 插入到列表 key 的表头

实例:

# 加入单个元素

redis> LPUSH languages python
(integer) 1


# 加入重复元素

redis> LPUSH languages python
(integer) 2

redis> LRANGE languages 0 -1     # 列表允许重复元素
1) "python"
2) "python"


# 加入多个元素

redis> LPUSH mylist a b c
(integer) 3

redis> LRANGE mylist 0 -1
1) "c"
2) "b"
3) "a"

返回值:

执行 LPUSH 命令后,列表的长度。

项目中的实例:

 String msg = currentTimeMillis + Constants.separator + phones.get(phoneId - 1).getName();
        //将字符串添加到指定的key中存储列表的头部(LPUSH)或尾部(RPUSH)
        jedis.lpush(Constants.BUY_DYNAMIC, msg);

获取销量排行榜

命令实例描述
zrevrangeWithScoreszrevrangeWithScores key start,end取出下标start到 end 的数据

返回值:

Set<Tuple> 集合

项目中的实例:

@Override
    public List<PhoneInfo> getPhbList() {
        // 按照销量多少排行,取出前五名
        Set<Tuple> tuples = jedis.zrevrangeWithScores(Constants.SALES_LIST, 0, 4);
        List<PhoneInfo> list = new ArrayList<PhoneInfo>();
        for (Tuple tuple : tuples) {
            PhoneInfo vo = new PhoneInfo();
            // 取出对应 phoneId 的手机名称
            int phoneId = Integer.parseInt(tuple.getElement());
            vo.setName(phones.get(phoneId - 1).getName());
            vo.setSales((int) tuple.getScore());
            list.add(vo);
        }
        return list;
    }

重置排名:

命令实例描述
DELDEL key [key …]删除给定的一个或多个 key,不存在的 key 会被忽略。

实例:

#  删除单个 key

redis> SET name huangz
OK

redis> DEL name
(integer) 1


# 删除一个不存在的 key

redis> EXISTS phone
(integer) 0

redis> DEL phone # 失败,没有 key 被删除
(integer) 0


# 同时删除多个 key

redis> SET name "redis"
OK

redis> SET type "key-value store"
OK

redis> SET website "redis.com"
OK

redis> DEL name type website
(integer) 3

返回值:

被删除 key 的数量。

项目中实例:

@Override
    public void clear() {
        jedis.del(Constants.SALES_LIST);
        jedis.del(Constants.BUY_DYNAMIC);
    }

至此项目中所有用到的命令都介绍了一下: 更多的命令请参考: http://doc.redisfans.com/ ,建议大家练习一下,熟能生巧
本案例项目地址: 点击查看

纸上得来终觉浅,绝知此事要躬行。————出自《冬夜读书示子聿》

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐