Redis和nosql简介,api调用;Redis数据功能(String类型的数据处理);List数据结构(及Java调用处理);Hash数据结构;Set数据结构功能;sortedSet(有序集合)数

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 1、Redis和nosql简介,api调用14.1/ nosql介绍 NoSQL:一类新出现的数据库(not only sql),它的特点:1、  不支持SQL语法2、  存储结构跟传统关系型数据库中的那种关系表完全不同,nosql中存储的数据都是KV形式3、  NoSQL的世界中没有一种通用的语言,每种nosql数据库都有自己的api和语法,以及擅长的业务场景4、  NoSQ

1、Redis和nosql简介,api调用

14.1/ nosql介绍

 

NoSQL:一类新出现的数据库(not only sql),它的特点:

1、  不支持SQL语法

2、  存储结构跟传统关系型数据库中的那种关系表完全不同,nosql中存储的数据都是KV形式

3、  NoSQL的世界中没有一种通用的语言,每种nosql数据库都有自己的api和语法,以及擅长的业务场景

4、  NoSQL中的产品种类相当多:

a)        Mongodb  文档型nosql数据库,擅长做CMS系统(内容管理系统)

b)        Redis        内存数据库,数据结构服务器,号称瑞士军刀(精巧),只要你有足够的想象力,它可以还给你无限惊喜

c)        Hbase  hadoop生态系统中原生的一种nosql数据库,重量级的分布式nosql数据库,用于海量数据的场景

d)        Cassandra  hadoop生态系统中原生的一种分布式nosql数据库,后起之秀

 

NoSQL和SQL数据库的比较:

1、适用场景不同:sql数据库适合用于关系特别复杂的数据查询场景,nosql反之

2、“事务”特性的支持:sql对事务的支持非常完善,而nosql基本不支持事务

3、两者在不断地取长补短,呈现融合趋势

 

 

14.2/ redis介绍

14.2.1 简述

Redis是一个高性能的kv缓存和内存数据库(存的不像mysql那样的表)

Redis的存储结构就是key-value,形式如下:


注: redis中的value内部可以支持各种数据结构类型,比如可以存入一个普通的string,还可以存listsethashmapsortedSet(有序的set

 

14.2.2 redis应用场景

A、用来做缓存(ehcache/memcached)——redis的所有数据是放在内存中的(内存数据库)

B、可以在某些特定应用场景下替代传统数据库——比如社交类的应用

C、在一些大型系统中,巧妙地实现一些特定的功能:session共享、购物车

只要你有丰富的想象力,redis可以用在可以给你无限的惊喜…….

 

 

14.2.3 redis的特性

1、redis数据访问速度快(数据在内存中)

2、redis有数据持久化机制(持久化机制有两种:1、定期将内存数据dump到磁盘;2、aof(append only file)持久化机制——用记日志的方式记录每一条数据更新操作,一旦出现灾难事件,可以通过日志重放来恢复整个数据库)

3、redis支持集群模式(容量可以线性扩展)

4、redis相比其他缓存工具(ehcach/memcached),有一个鲜明的优势:支持丰富的数据结构

14.3.Redis的api客户端连接

新建一个maven工程,导入jedis的maven依赖坐标

<dependency>

<groupId>redis.clients</groupId>

<artifactId>jedis</artifactId>

<version>2.7.2</version>

<type>jar</type>

<scope>compile</scope>

</dependency>

然后写一个类用来测试服务器跟客户端的连通性:

public class RedisClientConnectionTest {

         public static void main(String[] args) {

                  // 构造一个redis的客户端对象

                  Jedis jedis = new Jedis("pinshutang.zicp.net", 6379);

                  String ping = jedis.ping();

                  System.out.println(ping);

         }

}

 

15、Redis数据功能(String类型的数据处理)

15.1 String类型的数据

(常作为缓存使用)

1/插入和读取一条string类型的数据

redis notrue-centos:6379> set sessionid-0001 "zhangsan"

OK

redis notrue-centos:6379> get sessionid-0001

"zhangsan"

 

2/对string类型数据进行增减(前提是这条数据的value可以看成数字)

192.168.106.80:6379> DECR key

(integer) -1

192.168.106.80:6379> DECR key

(integer) -2

192.168.106.80:6379> DECR key

(integer) -3

192.168.106.80:6379> INCR key

(integer) -2

192.168.106.80:6379> INCR key

(integer) -1

 

192.168.106.80:6379> DECRBY key 4

(integer) -5

192.168.106.80:6379> DECRBY key -7

(integer) 2

192.168.106.80:6379> INCRBY key 2

(integer) 4

192.168.106.80:6379> INCRBY key -9

(integer) -5

 

3/一次性插入或者获取多条数据

192.168.106.80:6379> MSET key1 1 key2 2 key3 3

OK

192.168.106.80:6379> MGET key1 key2 key3

1) "1"

2) "2"

3) "3"

 

4/在插入一条string类型数据的同时为它指定一个存活期限

setex key seconds value

 

例如:

# bancao这条数据就只会存活10秒钟,过期会被redis自动清除

192.168.106.80:6379> setex bancao 10 testvalue

OK

192.168.106.80:6379> get bancao

"testvalue"

192.168.106.80:6379> get bancao

"testvalue"

192.168.106.80:6379> get bancao

(nil)

192.168.106.80:6379> get bancao

(nil)

 

案例:

其中maven项目的pom文件的内容如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.toto.redis</groupId>

    <artifactId>redistest</artifactId>

    <version>0.0.1-SNAPSHOT</version>

 

    <dependencies>

 

       <!-- <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId>

           <version>2.7.2</version> <type>jar</type> <scope>compile</scope> </dependency> -->

 

       <dependency>

           <groupId>redis.clients</groupId>

           <artifactId>jedis</artifactId>

           <version>2.8.0</version>

       </dependency>

 

       <dependency>

           <groupId>com.google.code.gson</groupId>

           <artifactId>gson</artifactId>

           <version>2.3.1</version>

       </dependency>

      

       <dependency>

           <groupId>junit</groupId>

           <artifactId>junit</artifactId>

           <version>4.7</version>

           <scope>test</scope>

       </dependency>

    </dependencies>

</project>

代码:

package cn.toto.redis.client;

 

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

 

import org.junit.Before;

import org.junit.Test;

 

import com.google.gson.Gson;

 

import cn.toto.redis.bean.ProductInfo;

 

import redis.clients.jedis.Jedis;

 

public class StringStructureData {

 

    private Jedis jedis = null;

 

    @Before

    public void init() {

       //这里的是hadoop2可以用ip地址替换

       jedis = new Jedis("hadoop2",6379);

      

    }

   

    @Test

    public void testString() {

       jedis.set("user02:name", "ruhua");

       jedis.set("user03:name", "滑板鞋");

      

       String u02 = jedis.get("user02:name");

       String u03 = jedis.get("user03:name");

      

       System.out.println(u02);

       System.out.println(u03);

    }

   

    @Test

    public void testObjectCache() throws Exception {

       ProductInfo p = new ProductInfo();

      

       p.setName("username");

       p.setDescription("备注信息");

       p.setCatelog("unknow");

       p.setPrice(10.8);

      

       //将对象序列化成字节数组

       ByteArrayOutputStream ba = new ByteArrayOutputStream();

       ObjectOutputStream oos = new ObjectOutputStream(ba);

      

       //用对象序列化流来将p对象序列化,然后把序列化之后的二进制数据写到ba流中

       oos.writeObject(p);

      

       //ba流转成byte数组

       byte[] pBytes = ba.toByteArray();

      

       //将对象序列化之后的byte数组存到redisstring结构数组中

       jedis.set("product:01".getBytes(), pBytes);

      

       //根据keyredis中取出对象的byte数据

       byte[] pBytesResp = jedis.get("product:01".getBytes());

      

      

       //byte数据反序列化列出对象

       ByteArrayInputStream bi = new ByteArrayInputStream(pBytesResp);

       ObjectInputStream oi = new ObjectInputStream(bi);

      

       //从对象读取流中取出对象

       ProductInfo pResp = (ProductInfo) oi.readObject();

       System.out.println(pResp);

    }

   

    @Test

    public void testObjectToJsonCache() {

       ProductInfo p = new ProductInfo();

      

       p.setName("ABC");

       p.setDescription("刘亦菲专用");

       p.setCatelog("化妆品");

       p.setPrice(10.8);

      

       //利用gson将对象转成json

       Gson gson = new Gson();

       String pJson = gson.toJson(p);

      

       //json串存入redis

       jedis.set("prodcut:02", pJson);

      

       //redis中取出对象的json

       String pJsonResp = jedis.get("prodcut:02");

      

       //将返回的json解析成对象

       ProductInfo pResponse = gson.fromJson(pJsonResp, ProductInfo.class);

      

       //显示对象的属性

       System.out.println(pResponse);

    }

}

 

16、List数据结构(及Java调用处理)

16.1 List图示

 

16.2 List功能演示

#从头部(左边)插入数据

redis>LPUSH  key  value1  value2  value3   

#从尾部(右边)插入数据

redis>RPUSH  key  value1  value2  value3  

#读取list中指定范围的values

redis>LRANGE  key  start   end

redis> lrange  task-queue  0  -1      读取整个list

#从头部弹出一个元素

LPOP  key

#从尾部弹出一个元素

RPOP  key

#从一个list的尾部弹出一个元素插入到另一个list

RPOPLPUSH   key1    key2     ## 这是一个原子性操作

例如下面的案例:

#从头部(左边)插入数据

192.168.106.81:6379> lpush task task0 task1 task2

(integer) 3

192.168.106.81:6379> lrange task 0 2

1) "task2"

2) "task1"

3) "task0"

192.168.106.81:6379> lrange task 0 -2

1) "task2"

2) "task1"

192.168.106.81:6379> lrange task 0 -1

1) "task2"

2) "task1"

3) "task0"

#从尾部(右边)插入数据

192.168.106.81:6379> rpush ids id0 id1 id2

(integer) 3

192.168.106.81:6379> lrange ids 0 -1

1) "id0"

2) "id1"

3) "id2"

192.168.106.81:6379> lpop ids

"id0"

192.168.106.81:6379> lpop ids

"id1"

192.168.106.81:6379> rpop task

"task0"

192.168.106.81:6379> rpoplpush task ids

"task1"

192.168.106.81:6379> lrange ids 0 -1

1) "task1"

2) "id2"

192.168.106.81:6379>

 

16.3 List的应用案例demo

1 需求描述

任务调度系统:

生产者不断产生任务,放入task-queue排队

消费者不断拿出任务来处理,同时放入一个tmp-queue暂存,如果任务处理成功,则清除tmp-queue,否则,将任务弹回task-queue

 

2 代码实现

1/生产者

——模拟产生任务

package cn.toto.redis.productAndCustomer;

 

import java.util.Random;

import java.util.UUID;

 

import redis.clients.jedis.Jedis;

 

public class TaskProducer {

    //获取一个redis的客户端连接对象

    public static Jedis getRedisConnection(String host,int port) {

       Jedis jedis = new Jedis(host,port);

       return jedis;

    }

   

    public static void main(String[] args) {

       Jedis jedis = getRedisConnection("hadoop3", 6379);

      

       Random random = new Random();

       //生成任务

       while(true) {

           try {

              //生成任务的速度有一定的随机性,在1-2秒之间

              Thread.sleep(random.nextInt(1000) + 1000);

              //生成一个任务

              String taskid = UUID.randomUUID().toString();

              //往任务队列"task-queue"中插入,第一次插入时,"task-queue"还不存在

              //但是lpush方法会在redis库中创建一条新的list数据

              jedis.lpush("task-queue", taskid);

              System.out.println("向任务队列中插入了一个新的任务:" + taskid);

           } catch (Exception e) {

              e.printStackTrace();

           }

       }

    }

}

 

2/消费者

——模拟处理任务,并且管理暂存队列

package cn.toto.redis.productAndCustomer;

 

import java.util.Random;

 

import redis.clients.jedis.Jedis;

 

public class TaskConsumer {

 

    public static void main(String[] args) {

       Jedis jedis = new Jedis("hadoop3",6379);

       Random random = new Random();

       

       while(true) {

           try {

              //task-queue中取一个任务,同时放入tmp-queue

              String taskid = jedis.rpoplpush("task-queue", "tmp-queue");

             

              //模拟处理任务

              Thread.sleep(1000);

             

              //模拟有成功又有失败的情况

              int nextInt = random.nextInt(13);

              if (nextInt % 7 == 0) {//模拟失败的情况

                  //在失败的情况下,需要将任务从tmp-queue弹回"task-queue"

                  jedis.rpoplpush("tmp-queue", "task-queue");

                  System.out.println("----任务处理失败:" + taskid);

              } else {//模拟成功的情况

                  //成功的情况下,将任务从"tmp-queue"清除

                  jedis.rpop("tmp-queue");

                  System.out.println("任务处理成功:" + taskid);

              }

           } catch (Exception e) {

              e.printStackTrace();

           }

       }

    }

}

 

上述机制是一个简化版,真实版的任务调度系统会更加复杂,如下所示:

(增加了一个专门用来管理暂存队列的角色,以便就算消费者程序失败退出,那些处理失败的任务依然可以被弹回task-queue)

 

17、Hash数据结构

17.1 Hash图示

Redis中的Hashes类型可以看成具有String Key和String Value的map容器

 

17.2 Hash功能演示

1、往redis库中插入一条hash类型的数据

redis> HSET  key  field  value

举例:

redis 127.0.0.1:6379> hset user001:zhangsan  iphone   6

(integer) 1

redis 127.0.0.1:6379> hset user001:zhangsan   xiaomi   7

(integer) 1

redis 127.0.0.1:6379> hset user001:zhangsan   meizu   8

(integer) 1

在redis库中就形成了这样一条数据:

 

2、从redis库中获取一条hash类型数据的value

ü 取出一条hash类型数据中所有field-value对

redis 127.0.0.1:6379> hgetall user001:zhangsan

1) "iphone"

2) "6"

3) "xiaomi"

4) "7"

5) "meizu"

6) "8"

 

ü 取出hash数据中所有fields

redis 127.0.0.1:6379> HKEYS user001:zhangsan

1) "iphone"

2) "xiaomi"

3) "meizu"

 

ü 取出hash数据中所有的value

redis 127.0.0.1:6379> hvals user001:zhangsan

1) "6"

2) "7"

3) "8"

 

ü 取出hash数据中一个指定field的值

redis 127.0.0.1:6379> hget user001:zhangsan xiaomi

"8"

 

ü 为hash数据中指定的一个field的值进行增减

redis 127.0.0.1:6379> HINCRBY user001:zhangsan xiaomi 1

(integer) 8

 

ü 从hash数据中删除一个字段field及其值

redis 127.0.0.1:6379> hgetall user001:zhangsan

1) "iphone"

2) "6"

3) "xiaomi"

4) "7"

5) "meizu"

6) "8"

redis 127.0.0.1:6379> HDEL user001:zhangsan iphone

(integer) 1

redis 127.0.0.1:6379> hgetall user001:zhangsan

1) "xiaomi"

2) "7"

3) "meizu"

4) "8"

 

18、Set数据结构功能

集合的特点:无序、无重复元素

1、  插入一条set数据

redis 127.0.0.1:6379> sadd frieds:zhangsan  bingbing baby fengjie furong ruhua tingting

(integer) 6

redis 127.0.0.1:6379> scard frieds:zhangsan

(integer) 6

redis 127.0.0.1:6379>

 

 

2、获取一条set数据的所有members

redis 127.0.0.1:6379> smembers frieds:zhangsan

1) "fengjie"

2) "baby"

3) "furong"

4) "bingbing"

5) "tingting"

6) "ruhua"

 

3、判断一个成员是否属于某条指定的set数据

redis 127.0.0.1:6379> sismember frieds:zhangsan liuyifei     #如果不是,则返回0

(integer) 0

redis 127.0.0.1:6379> sismember frieds:zhangsan baby       #如果是,则返回1

(integer) 1

 

4、求两个set数据的差集

#求差集

redis 127.0.0.1:6379> sdiff  frieds:zhangsan  friends:xiaotao

1) "furong"

2) "fengjie"

3) "ruhua"

4) "feifei"

#求差集,并将结果存入到另一个set

redis 127.0.0.1:6379> sdiffstore zhangsan-xiaotao frieds:zhangsan friends:xiaotao

(integer) 4

#查看差集结果

redis 127.0.0.1:6379> smembers zhangsan-xiaotao

1) "furong"

2) "fengjie"

3) "ruhua"

4) "feifei"

 

5、  求交集,求并集

#求交集

redis 127.0.0.1:6379> sinterstore zhangsan:xiaotao frieds:zhangsan friends:xiaotao

(integer) 2

redis 127.0.0.1:6379> smembers zhangsan:xiaotao

1) "bingbing"

2) "baby"

 

#求并集

redis 127.0.0.1:6379> sunion  frieds:zhangsan friends:xiaotao

 1) "fengjie"

 2) "tangwei"

 3) "liuyifei"

 4) "bingbing"

 5) "ruhua"

 6) "feifei"

 7) "baby"

 8) "songhuiqiao"

 9) "furong"

10) "yangmi"

案例代码:

package cn.toto.redis.hashcart;

 

import java.util.Map;

import java.util.Map.Entry;

import java.util.Set;

 

import org.junit.Before;

import org.junit.Test;

 

import redis.clients.jedis.Jedis;

 

public class BuyCartServiceImpl {

   

    private Jedis jedis = null;

    private static final String CART_PRIFIX = "cart:";

   

    @Before

    public void init() {

       jedis = new Jedis("hadoop3",6379);

    }

   

    /**

     * 添加商品到购物车

     */

    @Test

    public void testAddItemToCart() {

       jedis.hset(CART_PRIFIX + "user02", "上衣", "2");

       jedis.hset(CART_PRIFIX + "user02", "鞋子", "1");

       jedis.hset(CART_PRIFIX + "user02", "毛衣", "3");

       jedis.hset(CART_PRIFIX + "user02", "羽绒服", "4");

      

       jedis.close();

    }

   

    /**

     * 查看购物车信息,当本类中的其它单元测试执行完成之后,可以通过执行这个单元测试方法查看内容

     * @author toto

     * @date 2017-1-14

     * @note  begin modify by 涂作权 2017-1-14  原始创建

     */

    @Test

    public void testGetCartInfo() {

       Map<String, String> cart = jedis.hgetAll(CART_PRIFIX + "user02");

       Set<Entry<String, String>> entrySet = cart.entrySet();

       for(Entry<String, String> ent : entrySet) {

           System.out.println(ent.getKey() + ":" + ent.getValue());

       }

       jedis.close();

    }

   

    /**

     * 编辑缓存中的内容

     */

    @Test

    public void editCart() {

       //给蜡烛商品项的数量加1

       jedis.hincrBy(CART_PRIFIX + "user02", "羽绒服", 1);

       jedis.close();

    }

   

    /**

     * 删除内存中上衣这个内容

     */

    @Test

    public void delItemFromCart() {

       jedis.hdel(CART_PRIFIX + "user02", "上衣");

       jedis.close();

    }

}

生产者消费者:

生产者:

package cn.toto.redis.listqueue;

 

import java.util.Random;

import java.util.UUID;

 

import redis.clients.jedis.Jedis;

 

public class TaskProducer {

    private static Jedis jedis = null;

   

    public static void main(String[] args) throws Exception {

       jedis = new Jedis("hadoop2",6379);

       Random random = new Random();

      

       while(true) {

           int nextInt = random.nextInt(1000);

           Thread.sleep(1000 + nextInt);

          

           //生成一个任务的id

           String taskid = UUID.randomUUID().toString();

          

           jedis.lpush("task-queue", taskid);

          

           System.out.println("生成了一个任务:" + taskid);

       }

    }

}

消费者:

package cn.toto.redis.listqueue;

 

import java.util.Random;

 

import redis.clients.jedis.Jedis;

 

/**

 * @brief TaskProcessor.java 任务处理模块

 */

public class TaskProcessor {

   

    private static Jedis jedis = null;

   

    public static void main(String[] args) throws Exception {

       Random random = new Random();

      

       jedis = new Jedis("hadoop2",6379);

      

       while(true) {

           Thread.sleep(1500);

          

           //从任务队列中取出一个任务,同时放入到暂存队列中

           String taskid = jedis.rpoplpush("task-queue", "tmp-queue");

          

           //处理任务

           if (random.nextInt(19) % 9 == 0) {

              //模拟失败

              //失败的情况下,需要将任务从暂存队列弹回任务队列

              jedis.rpoplpush("tmp-queue", "task-queue");

              System.out.println("该任务处理失败:" + taskid);

           } else {

              //模拟成功

              //成功的情况下,只需要将任务从暂存队列清除

              jedis.rpop("tmp-queue");

              System.out.println("任务处理成功:" + taskid);

           }

       }

    }

}

Set的案例:

package cn.toto.redis.set;

 

import java.util.Set;

 

import redis.clients.jedis.Jedis;

 

public class TestSet {

   

    public static void main(String[] args) {

        Jedis jedis = new Jedis("hadoop2",6379);

       

        jedis.sadd("friends:shuangshuang", "dandan","lulu","lili");

        jedis.sadd("friends:laobi", "laowang","laodu","laoli","lili","lulu");

       

        //判断一个成员是否属于指定的集合

        Boolean isornot = jedis.sismember("friends:laobi", "shuangshuang");

        System.out.println(isornot);

       

        //求两个集合的差并交集

        Set<String> ssDiffbb = jedis.sdiff("friends:shuangshuang","friends:laobi");

       Set<String> ssUnionbb = jedis.sunion("friends:shuangshuang","friends:laobi");

       Set<String> ssInterbb = jedis.sinter("friends:shuangshuang","friends:laobi");

      

       //打印结果

       for (String mb : ssUnionbb) {

           System.out.println(mb);

       }

    }

}

 

 

19、sortedSet(有序集合)数据结构

19.1 sortedSet图示

sortedset中存储的成员都有一个附带的分数值

而redis就可以根据分数来对成员进行各种排序(正序、倒序)

 

1、  sortedSet存储内容示意图:

 

19.2 SortedSet功能演示

1、往redis库中插入一条sortedset数据

redis 127.0.0.1:6379> zadd nansheng:yanzhi:bang  70 liudehua  90 huangbo  100 weixiaobao  250 yangwei  59 xiaotao

(integer) 5

 

 

2、  从sortedset中查询有序结果

#正序结果

redis 127.0.0.1:6379> zrange nansheng:yanzhi:bang  0  4

1) "xiaotao"

2) "liudehua"

3) "huangbo"

4) "weixiaobao"

5) "yangwei"

#倒序结果

redis 127.0.0.1:6379> zrevrange nanshen:yanzhi:bang 0 4

1) "yangwei"

2) "weixiaobao"

3) "huangbo"

4) "liudehua"

5) "xiaotao"

 

3、  查询某个成员的名次

#在正序榜中的名次

redis 127.0.0.1:6379> zrank nansheng:yanzhi:bang  xiaotao

(integer) 0

 

#在倒序榜中的名次

redis 127.0.0.1:6379> zrevrank nansheng:yanzhi:bang xiaotao

(integer) 4

 

4、修改成员的分数

redis 127.0.0.1:6379> zincrby nansheng:yanzhi:bang  300  xiaotao

"359"

redis 127.0.0.1:6379> zrevrank nansheng:yanzhi:bang xiaotao

(integer) 0

案例:

下面的这个先运行:

package cn.toto.redis.sortedset;

 

import java.util.Random;

 

import redis.clients.jedis.Jedis;

 

public class LolBoxPlayer {

   

    public static void main(String[] args) throws Exception {

       Jedis jedis = new Jedis("hadoop2",6379);

      

       Random random = new Random();

       String[] heros = {"易大师","德邦","剑姬","盖伦","阿卡丽","金克斯","提莫","猴子","亚索"};

       while(true) {

           int index = random.nextInt(heros.length);

           //选择一个英雄

           String hero = heros[index];

          

           //开始玩游戏

           Thread.sleep(1000);

          

           //给集合中的该英雄的出场次数加1

           //第一次添加的时候,集合不存在,zincrby方法会创建

           jedis.zincrby("hero:ccl:phb", 1, hero);

          

           System.out.println(hero + "出场了......");

       }

    }

}

下面的这个后运行:

package cn.toto.redis.sortedset;

 

import java.util.Set;

 

import redis.clients.jedis.Jedis;

import redis.clients.jedis.Tuple;

 

public class LolBoxViewer {

   

    public static void main(String[] args) throws Exception {

       Jedis jedis = new Jedis("hadoop2",6379);

      

       int i = 1;

       while(true) {

           //每隔3秒查看一次榜单

           Thread.sleep(3000);

           System.out.println("" + i + "次查看榜单-----------");

          

           //redis中查询榜单的前N

           Set<Tuple> topHeros = jedis.zrevrangeWithScores("hero:ccl:phb", 0, 4);

          

           for (Tuple t : topHeros) {

              System.out.println(t.getElement() + "  " + t.getScore());

           }

          

           i++;

          

           System.out.println("");

           System.out.println("");

           System.out.println("");

       }

    }

}

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
21天前
|
存储 消息中间件 缓存
Redis 5 种基础数据结构?
Redis的五种基础数据结构——字符串、哈希、列表、集合和有序集合——提供了丰富的功能来满足各种应用需求。理解并灵活运用这些数据结构,可以极大地提高应用程序的性能和可扩展性。
26 2
|
1月前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
40 5
|
1月前
|
存储 NoSQL PHP
如何用Redis高效实现点赞功能?用Set?还是Bitmap?
在众多软件应用中,点赞功能几乎成为标配。本文从实际需求出发,探讨如何利用 Redis 的 `Set` 和 `Bitmap` 数据结构设计高效点赞系统,分析其优缺点,并提供 PHP 实现示例。通过对比两种方案,帮助开发者选择最适合的存储方式。
34 3
|
1月前
|
存储 消息中间件 NoSQL
Redis数据结构:List类型全面解析
Redis数据结构——List类型全面解析:存储多个有序的字符串,列表中每个字符串成为元素 Eelement,最多可以存储 2^32-1 个元素。可对列表两端插入(push)和弹出(pop)、获取指定范围的元素列表等,常见命令。 底层数据结构:3.2版本之前,底层采用**压缩链表ZipList**和**双向链表LinkedList**;3.2版本之后,底层数据结构为**快速链表QuickList** 列表是一种比较灵活的数据结构,可以充当栈、队列、阻塞队列,在实际开发中有很多应用场景。
|
2月前
|
存储 消息中间件 NoSQL
Redis 数据结构与对象
【10月更文挑战第15天】在实际应用中,需要根据具体的业务需求和数据特点来选择合适的数据结构,并合理地设计数据模型,以充分发挥 Redis 的优势。
59 8
|
2月前
|
存储 NoSQL Java
介绍下Redis 的基础数据结构
本文介绍了Redis的基础数据结构,包括动态字符串(SDS)、链表和字典。SDS是Redis自实现的动态字符串,避免了C语言字符串的不足;链表实现了双向链表,提供了高效的操作;字典则类似于Java的HashMap,采用数组加链表的方式存储数据,并支持渐进式rehash,确保高并发下的性能。
介绍下Redis 的基础数据结构
|
1月前
|
存储 NoSQL 关系型数据库
Redis的ZSet底层数据结构,ZSet类型全面解析
Redis的ZSet底层数据结构,ZSet类型全面解析;应用场景、底层结构、常用命令;压缩列表ZipList、跳表SkipList;B+树与跳表对比,MySQL为什么使用B+树;ZSet为什么用跳表,而不是B+树、红黑树、二叉树
|
1月前
|
存储 NoSQL Redis
Redis常见面试题:ZSet底层数据结构,SDS、压缩列表ZipList、跳表SkipList
String类型底层数据结构,List类型全面解析,ZSet底层数据结构;简单动态字符串SDS、压缩列表ZipList、哈希表、跳表SkipList、整数数组IntSet
|
1月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
191 9
|
1月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
32 1