Redis基本数据类型汇总

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis基本数据类型汇总相关的知识,希望对你有一定的参考价值。

Redis键(key)

3.2 字符串(String)

String是Redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value。

String类型是二进制安全的。意味着Redis的string可以包含任何数据。比如jpg图片或者序列化的对象。

String类型是Redis最基本的数据类型,一个Redis中字符串value最多可以是512M

序号 命令及描述
1 SET key value 设置指定 key 的值
2 GET key 获取指定 key 的值。
3 GETRANGE key start end 返回 key 中字符串值的子字符
4 GETSET key value 将给定 key 的值设为 value ,并返回 key 的旧值(old value)。
5 GETBIT key offset 对 key 所储存的字符串值,获取指定偏移量上的位(bit)。
6 [MGET key1 key2..] 获取所有(一个或多个)给定 key 的值。
7 SETBIT key offset value 对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。
8 SETEX key seconds value 将值 value 关联到 key ,并将 key 的过期时间设为 seconds (以秒为单位)。
9 SETNX key value 只有在 key 不存在时设置 key 的值。
10 SETRANGE key offset value 用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始。
11 STRLEN key 返回 key 所储存的字符串值的长度。
12 [MSET key value key value ...] 同时设置一个或多个 key-value 对。
13 [MSETNX key value key value ...] 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。
14 PSETEX key milliseconds value 这个命令和 SETEX 命令相似,但它以毫秒为单位设置 key 的生存时间,而不是像 SETEX 命令那样,以秒为单位。
15 INCR key 将 key 中储存的数字值增一。
16 INCRBY key increment 将 key 所储存的值加上给定的增量值(increment) 。
17 INCRBYFLOAT key increment 将 key 所储存的值加上给定的浮点增量值(increment) 。
18 DECR key 将 key 中储存的数字值减一。
19 DECRBY key decrement key 所储存的值减去给定的减量值(decrement) 。
20 APPEND key value 如果 key 已经存在并且是一个字符串, APPEND 命令将指定的 value 追加到该 key 原来值(value)的末尾。

语法:[ex|px]

set   <key><value>添加键值对
*NX:当数据库中key不存在时,可以将key-value添加数据库
*XX:当数据库中key存在时,可以将key-value添加数据库,与NX参数互斥
*EX:key的超时秒数
*PX:key的超时毫秒数,与EX互斥

get   <key>查询对应键值
append  <key><value>将给定的<value> 追加到原值的末尾
strlen  <key>获得值的长度
setnx  <key><value>只有在 key 不存在时    设置 key 的值

incr  <key>
将 key 中储存的数字值增1
只能对数字值操作,如果为空,新增值为1
decr  <key>
将 key 中储存的数字值减1
只能对数字值操作,如果为空,新增值为-1
incrby / decrby  <key><步长>将 key 中储存的数字值增减。自定义步长。

mset  <key1> <value1> <key2> <value2>  ..... 
同时设置一个或多个 key-value对  
mget  <key1> <key2> <key3> .....
同时获取一个或多个 value  
msetnx <key1> <value1> <key2> <value2>  ..... 
同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。原子性,有一个失败则都失败

getrange  <key> <起始位置> <结束位置>
获得值的范围,类似java中的substring,前包,后包
setrange  <key> <起始位置> <value>
用 <value>  覆写<key>所储存的字符串值,从<起始位置>开始(索引从0开始)。

setex  <key> <过期时间> <value>
设置键值的同时,设置过期时间,单位秒。
getset <key> <value> 
以新换旧,设置了新值同时获得旧值,会设置过期时间-1。

String的数据结构为简单动态字符串(Simple Dynamic String,缩写SDS)。是可以修改的字符串,内部结构实现上类似于Java的ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配.

如图中所示,内部为当前字符串实际分配的空间capacity一般要高于实际字符串长度len。当字符串长度小于1M时,扩容都是加倍现有的空间,如果超过1M,扩容时一次只会多扩1M的空间。需要注意的是字符串最大长度为512M。

pom.xml

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.7.1</version>
    <exclusions>
        <exclusion>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.11.1</version>
</dependency>
public class RedisDemo 

    @Test
    public void str1()
        Jedis j = new Jedis("localhost", 6379, 10000);
        j.auth("123456");
        String p = j.ping();
        System.out.println(p);
        //j.flushAll();
        //j.flushDB();
        //j.mset("m1","100","m2","200","m3","400");
        //j.expire("m1",1800l);
        for (String key : j.keys("*")) 
            System.out.println(j.get(key));
        

        System.out.println(j.exists("name"));
        System.out.println(j.del("name"));
        System.out.println(j.dbSize());
        System.out.println(j.ttl("m1"));
        System.out.println(j.type("m1"));
    

    private Jedis jedis;
    @BeforeEach
    public void init()
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();

        JedisPool pool = new JedisPool(poolConfig, "localhost", 6379, 10000, "123456");
        jedis = pool.getResource();
    
    @AfterEach
    public void close()
        jedis.close();
    

    @Test
    public void str2()
        System.out.println(jedis.ttl("m1"));
        for(String k : jedis.keys("m*"))
            System.out.println(jedis.get(k));
        
    

    @Test
    public void test1() throws InterruptedException 
        System.out.println("清空数据:" + jedis.flushDB());
        System.out.println("判断某个键是否存在:" + jedis.exists("username"));
        System.out.println("新增<username,wukong>的键值对:" + jedis.set("username", "wukong"));
        System.out.println("是否存在:" + jedis.exists("name"));
        System.out.println("新增<password,password>的键值对:" + jedis.set("password", "password"));
        Set<String> keys = jedis.keys("*");
        System.out.println("系统中所有的键如下:" + keys);
        System.out.println("删除键password:" + jedis.del("password"));
        System.out.println("判断键password是否存在:" + jedis.exists("password"));
        System.out.println("设置键username的过期时间为5s:" + jedis.expire("username", 5));
        TimeUnit.SECONDS.sleep(2);
        System.out.println("查看键username的剩余生存时间:" + jedis.ttl("username"));
        System.out.println("移除键username的生存时间:" + jedis.persist("username"));
        System.out.println("查看键username的剩余生存时间:" + jedis.ttl("username"));
        System.out.println("查看键username所存储的值的类型:" + jedis.type("username"));
    

    @Test
    public void test2() throws InterruptedException 
        // 字符串  string 的 操作
        jedis.flushDB();
        System.out.println("===========增加数据===========");
        System.out.println(jedis.set("key1", "value1"));
        System.out.println(jedis.set("key2", "value2"));
        System.out.println(jedis.set("key3", "value3"));
        System.out.println("删除键key2:" + jedis.del("key2"));
        System.out.println("获取键key2:" + jedis.get("key2"));
        System.out.println("修改key1:" + jedis.set("key1", "value1Changed"));
        System.out.println("获取key1的值:" + jedis.get("key1"));
        System.out.println("在key3后面加入值:" + jedis.append("key3", "End"));
        System.out.println("key3的值:" + jedis.get("key3"));
        System.out.println("增加多个键值对:" + jedis.mset("key01", "value01", "key02", "value02", "key03", "value03"));
        System.out.println("获取多个键值对:" + jedis.mget("key01", "key02", "key03"));
        System.out.println("获取多个键值对:" + jedis.mget("key01", "key02", "key03", "key04"));
        System.out.println("删除多个键值对:" + jedis.del("key01", "key02"));
        System.out.println("获取多个键值对:" + jedis.mget("key01", "key02", "key03"));

        jedis.flushDB();
        System.out.println("===========新增键值对防止覆盖原先值==============");
        System.out.println(jedis.setnx("key1", "value1"));
        System.out.println(jedis.setnx("key2", "value2"));
        System.out.println(jedis.setnx("key2", "value2-new"));
        System.out.println(jedis.get("key1"));
        System.out.println(jedis.get("key2"));

        System.out.println("===========新增键值对并设置有效时间=============");
        System.out.println(jedis.setex("key3", 2, "value3"));
        System.out.println(jedis.get("key3"));
        TimeUnit.SECONDS.sleep(3);
        System.out.println(jedis.get("key3"));

        System.out.println("===========获取原值,更新为新值==========");//GETSET is an atomic set this value and return the old value command.
        System.out.println(jedis.getSet("key2", "key2GetSet"));
        System.out.println(jedis.get("key2"));

        System.out.println("获得key2的值的字串:" + jedis.getrange("key2", 2, 4));


    

    /***
     * 整数和浮点数
     */
    @Test
    public void testNumber() 
        jedis.flushDB();
        jedis.set("key1", "1");
        jedis.set("key2", "2");
        jedis.set("key3", "2.3");
        System.out.println("key1的值:" + jedis.get("key1"));
        System.out.println("key2的值:" + jedis.get("key2"));
        System.out.println("key1的值加1:" + jedis.incr("key1"));
        System.out.println("获取key1的值:" + jedis.get("key1"));
        System.out.println("key2的值减1:" + jedis.decr("key2"));
        System.out.println("获取key2的值:" + jedis.get("key2"));
        System.out.println("将key1的值加上整数5:" + jedis.incrBy("key1", 5));
        System.out.println("获取key1的值:" + jedis.get("key1"));
        System.out.println("将key2的值减去整数5:" + jedis.decrBy("key2", 5));
        System.out.println("获取key2的值:" + jedis.get("key2"));
    


3.3 列表(List)

单键多值

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。

命令及描述
1 [BLPOP key1 key2 ] timeout 移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
2 [BRPOP key1 key2 ] timeout 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
3 BRPOPLPUSH source destination timeout 从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
4 LINDEX key index 通过索引获取列表中的元素
5 LINSERT key BEFORE|AFTER pivot value 在列表的元素前或者后插入元素
6 LLEN key 获取列表长度
7 LPOP key 移出并获取列表的第一个元素
8 [LPUSH key value1 value2] 将一个或多个值插入到列表头部
9 LPUSHX key value 将一个值插入到已存在的列表头部
10 LRANGE key start stop 获取列表指定范围内的元素
11 LREM key count value 移除列表元素
12 LSET key index value 通过索引设置列表元素的值
13 LTRIM key start stop 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
14 RPOP key 移除列表的最后一个元素,返回值为移除的元素。
15 RPOPLPUSH source destination 移除列表的最后一个元素,并将该元素添加到另一个列表并返回
16 [RPUSH key value1 value2] 在列表中添加一个或多个值
17 RPUSHX key value 为已存在的列表添加值

它的底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。

lpush/rpush  <key> <value1> <value2> <value3> .... 从左边/右边插入一个或多个值。
lpop/rpop  <key>从左边/右边吐出一个值。值在键在,值光键亡。

rpop lpush  <key1><key2>从<key1>列表右边吐出一个值,插到<key2>列表左边。

lrange <key> <start> <stop>
按照索引下标获得元素(从左到右)
lrange mylist 0 -1   0左边第一个,-1右边第一个,(0-1表示获取所有)
lindex <key><index>按照索引下标获得元素(从左到右)
lindex num -1 获取最后一个,就是右边的第一个
lindex num 0
lindex num 6

llen <key> 获得列表长度 

linsert <key>  before <value><newvalue>在<value>的后面插入<newvalue>插入值
127.0.0.1:6379> linsert num before 10 1000

lrem <key> <n> <value>从左边删除n个value(从左到右)
lset <key> <index> <value>将列表key下标为index的值替换成value

LTRIM key start stop
对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。


List的数据结构为快速链表quickList。

首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是ziplist,也即是压缩列表。

它将所有的元素紧挨着一起存储,分配的是一块连续的内存。

当数据量比较多的时候才会改成quicklist。

因为普通的链表需要的附加指针空间太大,会比较浪费空间。比如这个列表里存的只是int类型的数据,结构上还需要两个额外的指针prev和next。

Redis将链表和ziplist结合起来组成了quicklist。也就是将多个ziplist使用双向指针串起来使用。这样既满足了快速的插入删除性能,又不会出现太大的空间冗余。

@Test
public void testlist()
    jedis.flushDB();
    System.out.println("===========添加一个list===========");
    jedis.lpush("collections", "ArrayList", "Vector", "Stack", "HashMap", "WeakHashMap", "LinkedHashMap");
    jedis.lpush("collections", "HashSet");
    jedis.lpush("collections", "TreeSet");
    jedis.lpush("collections", "TreeMap");
    System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));//-1代表倒数第一个元素,-2代表倒数第二个元素
    System.out.println("collections区间0-3的元素:" + jedis.lrange("collections", 0, 3));
    System.out.println("===============================");
    // 删除列表指定的值 ,第二个参数为删除的个数(有重复时),后add进去的值先被删,类似于出栈
    System.out.println("删除指定元素个数:" + jedis.lrem("collections", 2, "HashMap"));
    System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
    System.out.println("删除下表0-3区间之外的元素:" + jedis.ltrim("collections", 0, 3));
    System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
    System.out.println("collections列表出栈(左端):" + jedis.lpop("collections"));
    System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
    System.out.println("collections添加元素,从列表右端,与lpush相对应:" + jedis.rpush("collections", "EnumMap"));
    System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
    System.out.println("collections列表出栈(右端):" + jedis.rpop("collections"));
    System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
    System.out.println("修改collections指定下标1的内容:" + jedis.lset("collections", 1, "LinkedArrayList"));
    System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
    System.out.println("===============================");
    System.out.println("collections的长度:" + jedis.llen("collections"));
    System.out.println("获取collections下标为2的元素:" + jedis.lindex("collections", 2));
    System.out.println("===============================");
    jedis.lpush("sortedList", "3", "6", "2", "0", "7", "4");
    System.out.println("sortedList排序前:" + jedis.lrange("sortedList", 0, -1));
    System.out.println(jedis.sort("sortedList"));
    System.out.println("sortedList排序后:" + jedis.lrange("sortedList", 0, -1));


    jedis.flushDB();
    jedis.lpush("num","10","20","30","40");
    jedis.lpush("num","1","600");
    jedis.rpush("num","20","11");
    //System.out.println(jedis.lrange("num",0,-1));
    List<String> list =  jedis.lrange("num",0,-1);

    List<Integer> num = list.stream().map(Integer::parseInt).collect(Collectors.toList());
    System.out.println(num);
    num.sort(Comparator.comparingInt(a -> a));//升序
    System.out.println(num);
    num.sort((a,b)->b-a);//降序
    System.out.println(num);
    Collections.shuffle(num);//乱序
    System.out.println(num);

    System.out.println("--------");
    System.out.println(jedis.sort("num"));

3.4 集合(Set)

Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。

Redis的Set是string类型的无序集合。它底层其实是一个value为null的hash表,所以添加,删除,查找的**复杂度都是****O(1)**。

一个算法,随着数据的增加,执行时间的长短,如果是O(1),数据增加,查找数据的时间不变

序号 命令及描述
1 [SADD key member1 member2] 向集合添加一个或多个成员
2 SCARD key 获取集合的成员数
3 [SDIFF key1 key2] 返回第一个集合与其他集合之间的差异。
4 [SDIFFSTORE destination key1 key2] 返回给定所有集合的差集并存储在 destination 中
5 [SINTER key1 key2] 返回给定所有集合的交集
6 [SINTERSTORE destination key1 key2] 返回给定所有集合的交集并存储在 destination 中
7 SISMEMBER key member 判断 member 元素是否是集合 key 的成员
8 SMEMBERS key 返回集合中的所有成员
9 SMOVE source destination member 将 member 元素从 source 集合移动到 destination 集合
10 SPOP key 移除并返回集合中的一个随机元素
11 [SRANDMEMBER key count] 返回集合中一个或多个随机数
12 [SREM key member1 member2] 移除集合中一个或多个成员
13 [SUNION key1 key2] 返回所有给定集合的并集
14 [SUNIONSTORE destination key1 key2] 所有给定集合的并集存储在 destination 集合中
15 [SSCAN key cursor MATCH pattern] [COUNT count] 迭代集合中的元素
sadd <key><value1><value2> ..... 
将一个或多个 member 元素加入到集合 key 中,已经存在的 member 元素将被忽略
smembers <key>取出该集合的所有值。
127.0.0.1:6379> sadd lang java javascript php html mysql redis spring
(integer) 7
127.0.0.1:6379> type lang
set
127.0.0.1:6379> smembers lang
1) "java"
2) "javascript"
3) "redis"
4) "mysql"
5) "php"
6) "html"
7) "spring"
127.0.0.1:6379> 
sismember <key><value>判断集合<key>是否为含有该<value>值,有1,没有0
127.0.0.1:6379> sismember lang mybatis
(integer) 0
127.0.0.1:6379> sismember lang java
(integer) 1

scard<key>返回该集合的元素个数。
srem <key><value1><value2> .... 删除集合中的某个元素。
spop <key>随机从该集合中吐出一个值。
127.0.0.1:6379> scard lang
(integer) 7
127.0.0.1:6379> smembers lang
1) "java"
2) "javascript"
3) "redis"
4) "mysql"
5) "php"
6) "html"
7) "spring"
127.0.0.1:6379> srem lang php mysql spring
(integer) 3
127.0.0.1:6379> smembers lang
1) "java"
2) "javascript"
3) "redis"
4) "html"
127.0.0.1:6379> spop lang
"java"
127.0.0.1:6379> spop lang
"redis"
127.0.0.1:6379> spop lang 2
1) "javascript"
2) "html"

srandmember <key><n>随机从该集合中取出n个值。不会从集合中删除 。
127.0.0.1:6379> srandmember lang 2
1) "mysql"
2) "java"
127.0.0.1:6379> smembers lang
1) "java"
2) "javascript"
3) "mysql"
4) "html"

smove <source><destination>value把集合中一个值从一个集合移动到另一个集合
127.0.0.1:6379> sadd s1 a b c
(integer) 3
127.0.0.1:6379> sadd s2 10 20 30
(integer) 3
127.0.0.1:6379> smove s1 s2 a
(integer) 1
127.0.0.1:6379> smembers s1
1) "c"
2) "b"
127.0.0.1:6379> smembers s2
1) "30"
2) "a"
3) "20"
4) "10"

sinter <key1><key2>返回两个集合的交集元素。
sunion <key1><key2>返回两个集合的并集元素。
sdiff <key1><key2>返回两个集合的差集元素(key1中的,不包含key2中的)
127.0.0.1:6379> sadd s1 1 2 3 a b c 
(integer) 6
127.0.0.1:6379> sadd s2 1 3 c d b a
(integer) 6
127.0.0.1:6379> sinter s1 s2
1) "a"
2) "3"
3) "1"
4) "b"
5) "c"
127.0.0.1:6379> sdiff s1 s2
1) "2"
127.0.0.1:6379> sunion s1 s2
1) "a"
2) "b"
3) "d"
4) "3"
5) "2"
6) "c"
7) "1"
127.0.0.1:6379> 

pom.xml

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>2.6.0</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.11.1</version>
</dependency>
 
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.7.1</version>
</dependency>

RedisConfig.java

@Configuration
public class RedisConfig 
    @Bean(destroyMethod = "close")
    public Jedis jedis()
        Jedis j = new Jedis("localhost",6379);
        return j;
    

    @Bean
    public GenericObjectPoolConfig poolConfig()
        GenericObjectPoolConfig cfg = new GenericObjectPoolConfig();
        return cfg;
    

    @Bean(destroyMethod = "close")
    public JedisPool jedisPool()
        JedisPool jp = new JedisPool(poolConfig(), "localhost", 6379, 10000, "123456");
        return jp;
    


SpringDemo.java

@SpringJUnitConfig(RedisConfig.class)
public class SpringDemo 
    @Autowired
    private ApplicationContext ctx;

    @Autowired
    private Jedis jedis;

    @Autowired
    private JedisPool jedisPool;

    /***
     * set集合
     */
    @Test
    public void testSet() 
        jedis.auth("123456");
        jedis.flushDB();
        System.out.println("============向集合中添加元素============");
        System.out.println(jedis.sadd("eleSet", "e1", "e2", "e4", "e3", "e0", "e8", "e7", "e5"));
        System.out.println(jedis.sadd("eleSet", "e6"));
        System.out.println(jedis.sadd("eleSet", "e6"));
        System.out.println("eleSet的所有元素为:" + jedis.smembers("eleSet"));
        System.out.println("删除一个元素e0:" + jedis.srem("eleSet", "e0"));
        System.out.println("eleSet的所有元素为:" + jedis.smembers("eleSet"));
        System.out.println("删除两个元素e7和e6:" + jedis.srem("eleSet", "e7", "e6"));
        System.out.println("eleSet的所有元素为:" + jedis.smembers("eleSet"));
        System.out.println("随机的移除集合中的一个元素:" + jedis.spop("eleSet"));
        System.out.println("随机的移除集合中的一个元素:" + jedis.spop("eleSet"));
        System.out.println("eleSet的所有元素为:" + jedis.smembers("eleSet"));
        System.out.println("eleSet中包含元素的个数:" + jedis.scard("eleSet"));
        System.out.println("e3是否在eleSet中:" + jedis.sismember("eleSet", "e3"));
        System.out.println("e1是否在eleSet中:" + jedis.sismember("eleSet", "e1"));
        System.out.println("e1是否在eleSet中:" + jedis.sismember("eleSet", "e5"));
        System.out.println("=================================");
        System.out.println(jedis.sadd("eleSet1", "e1", "e2", "e4", "e3", "e0", "e8", "e7", "e5"));
        System.out.println(jedis.sadd("eleSet2", "e1", "e2", "e4", "e3", "e0", "e8"));
        System.out.println("将eleSet1中删除e1并存入eleSet3中:" + jedis.smove("eleSet1", "eleSet3", "e1"));
        System.out.println("将eleSet1中删除e2并存入eleSet3中:" + jedis.smove("eleSet1", "eleSet3", "e2"));
        System.out.println("eleSet1中的元素:" + jedis.smembers("eleSet1"));
        System.out.println("eleSet3中的元素:" + jedis.smembers("eleSet3"));
        System.out.println("============集合运算=================");
        System.out.println("eleSet1中的元素:" + jedis.smembers("eleSet1"));
        System.out.println("eleSet2中的元素:" + jedis.smembers("eleSet2"));
        System.out.println("eleSet1和eleSet2的交集:" + jedis.sinter("eleSet1", "eleSet2"));
        System.out.println("eleSet1和eleSet2的并集:" + jedis.sunion("eleSet1", "eleSet2"));
        System.out.println("eleSet1和eleSet2的差集:" + jedis.sdiff("eleSet1", "eleSet2"));//eleSet1中有,eleSet2中没有
    

    @Test
    public void t2()
        Jedis js = jedisPool.getResource();
        System.out.println(js.ping());
        //js.sadd("lang","java","javascript","php","html","mysql","中文编程");
        //js.expire("lang",1800l);

        System.out.println(js.smembers("lang"));

    


    @Test
    public void t1()
        //显示所有ioc中的bean名称
        System.out.println(Arrays.toString(ctx.getBeanDefinitionNames()));

        System.out.println("hello world");
        jedis.auth("123456");
        System.out.println(jedis.ping());
    


3.5 哈希(Hash)

Redis hash 是一个键值对集合。

Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。

类似Java里面的Map<String,Object>

用户ID为查找的key,存储的value用户对象包含姓名,年龄,生日等信息,如果用普通的key/value结构来存储

主要有以下2种存储方式:

序号 命令及描述
1 [HDEL key field1 field2] 删除一个或多个哈希表字段
2 HEXISTS key field 查看哈希表 key 中,指定的字段是否存在。
3 HGET key field 获取存储在哈希表中指定字段的值。
4 HGETALL key 获取在哈希表中指定 key 的所有字段和值
5 HINCRBY key field increment 为哈希表 key 中的指定字段的整数值加上增量 increment 。
6 HINCRBYFLOAT key field increment 为哈希表 key 中的指定字段的浮点数值加上增量 increment 。
7 HKEYS key 获取所有哈希表中的字段
8 HLEN key 获取哈希表中字段的数量
9 [HMGET key field1 field2] 获取所有给定字段的值
10 [HMSET key field1 value1 field2 value2 ] 同时将多个 field-value (域-值)对设置到哈希表 key 中。
11 HSET key field value 将哈希表 key 中的字段 field 的值设为 value 。
12 HSETNX key field value 只有在字段 field 不存在时,设置哈希表字段的值。
13 HVALS key 获取哈希表中所有值。
14 [HSCAN key cursor MATCH pattern] [COUNT count] 迭代哈希表中的键值对。
hset <key><field><value>给<key>集合中的  <field>键赋值<value>
hget <key1><field>从<key1>集合<field>取出 value 
hmset <key1><field1><value1><field2><value2>... 批量设置hash的值
hexists<key1><field>查看哈希表 key 中,给定域 field 是否存在。 
hkeys <key>列出该hash集合的所有field
hvals <key>列出该hash集合的所有value
192.168.16.9:6379> hset user id 100 name lisi 
(integer) 2
192.168.16.9:6379> hmset stu id 11 name wangwu gender nan address zhengzhou
OK
192.168.16.9:6379> type stu
hash
192.168.16.9:6379> type user
hash
192.168.16.9:6379> hget user name
"lisi"
192.168.16.9:6379> hmget stu name address
1) "wangwu"
2) "zhengzhou"
192.168.16.9:6379> hkeys stu
1) "id"
2) "name"
3) "gender"
4) "address"
192.168.16.9:6379> hvals stu
1) "11"
2) "wangwu"
3) "nan"
4) "zhengzhou"
192.168.16.9:6379> hexists user address
(integer) 0
192.168.16.9:6379> hexists stu address
(integer) 1
192.168.16.9:6379> 

hincrby <key><field><increment>为哈希表 key 中的域 field 的值加上增量 1   -1
hsetnx <key><field><value>将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在 .

Hash类型对应的数据结构是两种:ziplist(压缩列表),hashtable(哈希表)。当field-value长度较短且个数较少时,使用ziplist,否则使用hashtable。

@Controller
public class IndexController 
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    @RequestMapping
    public String index(Model m)
        //redis string
        var v = redisTemplate.opsForValue();
        v.set("name","张三丰");
        m.addAttribute("msg","中文信息:" + v.get("name"));

        User u = new User();
        u.setId(10);
        u.setName("张三丰");
        u.setMoney(25.5);
        u.setBirth(LocalDate.now());
        u.setRegtime(new Date());
        u.setLtime(LocalDateTime.now());
        u.setLogtime(LocalTime.now());
        Set<String> set = new HashSet<String>();
        set.add("java");
        set.add("java1");
        set.add("java2");
        set.add("java3");
        u.setAddress(set);

        v.set("users",u);

        //redis list
        var list = redisTemplate.opsForList();
        List<String> lt = new ArrayList<>();
        lt.addAll(List.of("java程序","html网页","mysql数据库"));
        list.leftPushAll("lang",lt);

        //redis set
        var s = redisTemplate.opsForSet();
        s.add("address","郑州","天津","北京","上海");

        //redis hash
        var h = redisTemplate.opsForHash();
        Map<String,Object> map = new HashMap<String, Object>();
        map.put("id",30);
        map.put("name","李四四");
        map.put("birth", LocalDate.now());
        h.putAll("user",map);

        return "index";
    

    @GetMapping("/show")
    public String show(Model m)
        var list = redisTemplate.opsForList();
        List<Object> li = list.range("lang",0,-1);
        m.addAttribute("li",li);
        return "show";
    


3.6 有序集合Zset(sorted set)

Redis有序集合zset与普通集合set非常相似,是一个没有重复元素的字符串集合。

不同之处是有序集合的每个成员都关联了一个评分score,这个评分(score)被用来按照从最低分到最高分的方式排序集合中的成员。集合的成员是唯一的,但是评分可以是重复了 。

因为元素是有序的, 所以你也可以很快的根据评分(score)或者次序(position)来获取一个范围的元素。

访问有序集合的中间元素也是非常快的,因此你能够使用有序集合作为一个没有重复成员的智能列表。

序号 命令及描述
1 [ZADD key score1 member1 [score2 member2] 向有序集合添加一个或多个成员,或者更新已存在成 员的分数
2 ZCARD key 获取有序集合的成员数<br />192.168.16.9:6379> zcard lang<br/>(integer) 5
3 ZCOUNT key min max 计算在有序集合中指定区间分数的成员数<br />192.168.16.9:6379> zcount lang 1 50<br/>(integer) 4
4 ZINCRBY key increment member 有序集合中对指定成员的分数加上增量 increment
5 [ZINTERSTORE destination numkeys key key ...] 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 destination 中
6 ZLEXCOUNT key min max 在有序集合中计算指定字典区间内成员数量
7 [ZRANGE key start stop WITHSCORES] 通过索引区间返回有序集合指定区间内的成员
8 [ZRANGEBYLEX key min max LIMIT offset count] 通过字典区间返回有序集合的成员
9 [ZRANGEBYSCORE key min max WITHSCORES] [LIMIT] 通过分数返回有序集合指定区间内的成员<br />
10 ZRANK key member 返回有序集合中指定成员的索引
11 [ZREM key member member ...] 移除有序集合中的一个或多个成员
12 ZREMRANGEBYLEX key min max 移除有序集合中给定的字典区间的所有成员
13 ZREMRANGEBYRANK key start stop 移除有序集合中给定的排名区间的所有成员
14 ZREMRANGEBYSCORE key min max 移除有序集合中给定的分数区间的所有成员
15 [ZREVRANGE key start stop WITHSCORES] 返回有序集中指定区间内的成员,通过索引,分数从高到低
16 [ZREVRANGEBYSCORE key max min WITHSCORES] 返回有序集中指定分数区间内的成员,分数从高到低排序
17 ZREVRANK key member 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序
18 ZSCORE key member 返回有序集中,成员的分数值
19 [ZUNIONSTORE destination numkeys key key ...] 计算给定的一个或多个有序集的并集,并存储在新的 key 中
20 [ZSCAN key cursor MATCH pattern] [COUNT count] 迭代有序集合中的元素(包括元素成员和元素分值)
zadd  <key><score1><value1><score2><value2>…
将一个或多个 member 元素及其 score 值加入到有序集 key 当中。
192.168.16.9:6379> zadd lang 10 java 5 html
(integer) 2
192.168.16.9:6379> type lang
zset

zrange <key><start><stop>  [WITHSCORES]   
返回有序集 key 中,下标在<start><stop>之间的元素
带WITHSCORES,可以让分数一起和值返回到结果集。
192.168.16.9:6379> zrange lang 0 1
1) "html"
2) "java"
192.168.16.9:6379> zrange lang 0 1 withscores
1) "html"
2) "5"
3) "java"
4) "10"
192.168.16.9:6379> 

192.168.16.9:6379> zadd lang 100 c 50 javascript 15 mysql
(integer) 3
192.168.16.9:6379> type lang
zset

192.168.16.9:6379> zrange lang 0 8
1) "html"
2) "java"
3) "mysql"
4) "javascript"
5) "c"
192.168.16.9:6379> zrange lang 0 -1  #显示所有元素
1) "html"
2) "java"
3) "mysql"
4) "javascript"
5) "c"
192.168.16.9:6379> 

zrangebyscore key minmax [withscores] [limit offset count]
返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。 
192.168.16.9:6379> zrangebyscore lang 1 50 withscores
1) "html"
2) "5"
3) "java"
4) "10"
5) "mysql"
6) "15"
7) "javascript"
8) "50"


zrevrangebyscore key maxmin [withscores] [limit offset count]               
同上,改为从大到小排列。   withscores 是显示score limit 0 2 分页 第一页

4) "15"
192.168.16.9:6379> zrangebyscore lang 1 50 withscores limit 1 1
1) "java"
2) "10"
192.168.16.9:6379> zrangebyscore lang 1 50 withscores limit 2 1
1) "mysql"
2) "15"
192.168.16.9:6379> zrangebyscore lang 1 200 
1) "html"
2) "java"
3) "mysql"
4) "javascript"
5) "c"
192.168.16.9:6379> zrangebyscore lang 1 200 limit 0 2
1) "html"
2) "java"
192.168.16.9:6379> zrangebyscore lang 1 200 limit 2 2
1) "mysql"
2) "javascript"
192.168.16.9:6379> zrangebyscore lang 1 200 limit 3 2
1) "javascript"
2) "c"
192.168.16.9:6379> zrangebyscore lang 1 200 limit 4 2
1) "c"
192.168.16.9:6379> 

zincrby <key><increment><value>      为元素的score加上增量
192.168.16.9:6379> zrange lang 0 -1 withscores
 1) "html"
 2) "5"
 3) "java"
 4) "10"
 5) "mysql"
 6) "15"
 7) "javascript"
 8) "50"
 9) "c"
10) "100"
192.168.16.9:6379> zincrby lang 20 html
"25"
192.168.16.9:6379> zrange lang 0 -1 withscores
 1) "java"
 2) "10"
 3) "mysql"
 4) "15"
 5) "html"
 6) "25"
 7) "javascript"
 8) "50"
 9) "c"
10) "100"
192.168.16.9:6379> 
zrem  <key><value>删除该集合下,指定值的元素 
zcount <key><min><max>统计该集合,分数区间内的元素个数 
192.168.16.9:6379> zcount lang 0 -1
(integer) 0
192.168.16.9:6379> zcount lang 50 100
(integer) 2
192.168.16.9:6379> zrange lang 0 -1
1) "java"
2) "mysql"
3) "html"
4) "javascript"
5) "c"
192.168.16.9:6379> zrem lang javascript c html
(integer) 3
192.168.16.9:6379> zcard lang
(integer) 2
192.168.16.9:6379> zrange lang 0 -1
1) "java"
2) "mysql"
192.168.16.9:6379> 



zrank <key><value>返回该值在集合中的排名,从0开始。
192.168.16.9:6379> zrank lang java
(integer) 0
192.168.16.9:6379> zrank lang html
(integer) 2

192.168.16.9:6379> zrange lang 0 -1
1) "java"
2) "mysql"
3) "html"
4) "javascript"
5) "c"
192.168.16.9:6379> zrange lang 0 -1 withscores
 1) "java"
 2) "10"
 3) "mysql"
 4) "15"
 5) "html"
 6) "25"
 7) "javascript"
 8) "50"
 9) "c"
10) "100"
192.168.16.9:6379> 

案例:如何利用zset实现一个文章访问量的排行榜?

SortedSet(zset)是Redis提供的一个非常特别的数据结构,一方面它等价于Java的数据结构Map<String, Double>,可以给每一个元素value赋予一个权重score,另一方面它又类似于TreeSet,内部的元素会按照权重score进行排序,可以得到每个元素的名次,还可以通过score的范围来获取元素的列表。

zset底层使用了两个数据结构

(1)hash,hash的作用就是关联元素value和权重score,保障元素value的唯一性,可以通过元素value找到相应的score值。

(2)跳跃表,跳跃表的目的在于给元素value排序,根据score的范围获取元素列表。

01、建立springboot项目,pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>2.6.1</version>
</dependency>

02、编写配置文件resources/application.yml

spring:
  main:
    banner-mode: off
  redis:
    password: 123456
    host: localhost
    database: 0
    port: 6379

logging:
  level:
    root: off

03、编写命令行程序RedisApp.java

@Service
public class RedisApp implements ApplicationRunner 
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private ApplicationContext context;

    @Override
    public void run(ApplicationArguments args) throws Exception 
        //System.out.println(context.getBeanDefinitionNames().length);
        //var v = redisTemplate.opsForValue();
        //v.set("name","张三丰");
        //System.out.println(v.get("name"));
        var zs = redisTemplate.opsForZSet();
        //增加
        zs.add("lang","c",200);
        zs.add("lang","python",8);
        Set<TypedTuple<String>> s2 = new HashSet<>();
        s2.add(TypedTuple.of("ruby",20d));
        s2.add(TypedTuple.of("c++",30d));
        s2.add(TypedTuple.of("html",120d));
        zs.add("lang",s2);
        //读取
        Set<String> set = zs.range("lang",0,-1);
        System.out.println(set);

        var ss = zs.rangeWithScores("lang",0,-1);
        ss.forEach(e->
            System.out.println(e.getValue() + ":" + e.getScore());
        );

    


以上是关于Redis基本数据类型汇总的主要内容,如果未能解决你的问题,请参考以下文章

redis知识点汇总

Redis入门到精通——List类型数据基本操作List类型数据扩展操作List类型数据注意事项List类型应用场景

Redis入门到精通——List类型数据基本操作List类型数据扩展操作List类型数据注意事项List类型应用场景

Redis数据类型API汇总

Redis 十大数据类型命令及案例大全

Redis学习汇总(已完结)