Redis的五大基本数据类型(String/list/set/hash/zset)

142 阅读7分钟

简介

image.png REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。 Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。

Redis-key

  • 查看所有的key keys *
  • 添加一个key set key value
  • 判断键是否存在 exists key
  • 设置键过期时间 expire key time(秒)
  • 移除当前的key move key
  • 查看当前key的剩余时间 ttl key
  • 查看键的类型 type key
  • ......

String(字符串)

  • 设置值 set 键 值

  • 获取键值 get 键

  • 获取所有的键 keys *

  • 判断某一个key是否存在 exists 键

  • 追加字符串 append 键 "追加值" 如果当前key不存在,就相当于set key

  • 键值自增1 incr 键 自减1 decr 键(应用场景,统计浏览量)

    • 按指定步长(设置增量)自增 incrby 键 步长 自减decrby 键 步长
  • 字符串范围range

    • 截取字符串 GETRANGE 键 下标1 下标2
    • 截取全部 GETRANGE 键 0 -1
  • 替换

    • 替换指定位置开始的字符串 SETRANGE 键 下标 新的值
  • 过期时间

    • 设置过期时间 setex(set with expire)
    • 不存在设置(在分布式锁中常常使用) setnx(set if not exist)
      • eg: 设置key1的值为sayhi 30秒后过期 setex key1 30 "sayhi"
      • eg:如果mykey不存在 创建mykey setnx mykey "redis"
      • eg:如果mykey存在 创建失败 setnx mykey "MongoDB"
  • 批量处理

    • mset

      • 同时设置多组值 mset k1 v1 k2 v2 k3 v3
    • mget

      • 同时获取多组值mget k1 k2 k3
    • msetnx msetnx是一个原子性的操作,要么一起成功,要么一起失败

  • 对象

    • set user:1 {name:zhangsan,age:18} 设置一个user:1对象 值为json字符来保存一个对象.
  • 先get再set getset

    • 如果不存在值 则返回nil getset db redis
    • 如果存在值,获取原来的值,并设置新的值 getset db mongodb

String 类似的使用场景: value不仅仅是字符串,还可以是数字!

  • 计数器
  • 统计多单位的数量
  • 粉丝数
  • 点赞数
  • .......

List

在Redis中,可以使用list做栈,队列,阻塞队列!

  • 添加

    • 将一个值或多个值插入列表的头部(左) LOUSH list键 名
    • 将一个值或多个值插入列表的尾部(右) ROUSH list键 名
    • 获取list中的值 LRANGE list键 下标1,下标2
    • 通过区间获取具体的值LRANGE list 0 1
  • 移除

    • 移除列表的第一个元素 Lpop list
    • 移除列表的最后一个元素 Rpop list
  • 返回列表长度 Llen

  • 移除指定的值

    • 移除列表中指定个数的value,精确匹配 lren list键 1 one (移除一个one)
  • list截取

    • 通过下标截取指定的长度,这个list已经被修改了 截断了只剩下截取的元素 ltrim mylist键 1 2
  • 综合

    • 移除列表的最后一个元素 并移动到新的列表中 rpoplpush
  • 替换指定下标的值(更新)

    • 判断列表是否存在 exists 列表
    • 如果不存在的列表更新会报错(error)ERR no such key
    • 如果存在更新当前下标的值 lset 键 小标 值
  • 插入

    • 在元素后面添加指定value Linsert 键 before 定位值 "新value"
    • 在元素前面添加指定value linsert 键 after 定位值 "新值"

小结

  • list实际是一个链表,before node after left right 都可以插入值
  • 如果key不存在,创建新的链表
  • 如果key存在,新增内容
  • 如果移除了所有值,空链表,也代表不存在!
  • 在两边插入或者改动值 效率最高! 中间元素,相对而言效率低一些
@Resource
private RedisTemplate<Object,Object> redisTemplate;

@Test
void testContextList(){
    ListOperations listOperations = redisTemplate.opsForList();
    listOperations.leftPush("list","ddd");
    listOperations.leftPush("list","hhh");
    listOperations.leftPush("list","ddd");

    Object list = listOperations.rightPop("list");
    System.out.println(list);


    listOperations.range("list",0,2);

}

set

set中的值是不能重读的!

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

  • 添加元素

    • 给集合添加一个元素 sadd 键 值
    • 查看指定set的所有值 smembers 键
    • 判断某一个值是不是在set集合中 sismember 键 值
  • 获取集合中的内容元素个数 scard 键

  • 移除元素

    • 移除set集合中的指定元素 srem 键 值

set: 无序不重复集合! 随机

  • 随机抽元素

    • 随机抽出一个元素 srandmember 键
    • 随机抽出指定个数元素 srandmember 键 数
  • 删除set元素

    • 随机删除一个set集合中的元素 spop 键
  • 将一个指定的值.移动到另外一个set集合smove 原集合 新集合 移动的值 共同关注(并集)

数字集合类:

  • 差集 sdiff 键1 键2
  • 交集 sinter 键1 键2 共同好友实现方式
  • 并集 sunion 键1 键2
@Resource
private RedisTemplate<Object,Object> redisTemplate;

@Test
void testObsSet(){
    SetOperations setOperations = redisTemplate.opsForSet();
    setOperations.add("name","admin");
    setOperations.add("name","lily");
    setOperations.add("name","john");
    setOperations.add("age","18");
    setOperations.add("type","1");

    Set name = setOperations.members("name");
    name.forEach(e->{
        System.out.println(e);
    });
}

Hash(哈希)

Map集合 本质和String没有太大区别 还是一个简单的key-value

一般我们存储一个键,很自然的就会使用 get/set 去存储,实际上这并不是很好的做法。Redis 存储一个 key 会有一个最小内存,不管你存的这个键多小,都不会低于这个内存,因此合理的使用 Hash 可以帮我们节省很多内存。

Hash Set 就在哈希表 Key 中的域(Field)的值设为 value。如果 Key 不存在,一个新的哈希表被创建并进行 HSET 操作;如果域(field)已经存在于哈希表中,旧值将被覆盖。

  • 字段值

    • 设置一个具体的key-value hset 键 值
    • 设置多个具体的key-value hmset 键 值1 值2
    • 获取多个字段值 hmget 键 ....
    • 获取所有的字段 hgetall 键
    • 删除指定字段 hdel 键 字段名
  • 字符长度

    • 获取哈希的字符长度 hlen 键
  • 判断hash中的指定字段是否存在 hexists 键 字段名

  • 自增自减

    • 指定增量 hsetnx 键 字段 数
    • 如果不存在则可以设置 如果存在则不能设置

    使用场景:经常变动信息.做一些经常变动的信息

@Resource
private RedisTemplate<Object,Object> redisTemplate;

@Test
void contextLoads() {

    HashOperations hashOperations = redisTemplate.opsForHash();
    hashOperations.put("user","name","admin");
    hashOperations.put("user","age","18");


    ListOperations listOperations = redisTemplate.opsForList();
    listOperations.leftPush("sort",1);
    listOperations.leftPush("sort",2);
    listOperations.leftPush("sort",3);

    Object sort = listOperations.leftPop("sort");
    // 通过下标找联表数据,下标从零开始 往后找几位
    List sort1 = listOperations.range("sort", 0, 2);
    sort1.forEach(e -> {
        System.out.println(e);
    });
    System.out.println(sort);
}

zSet(有序集合)

Redis Sorted Set 的使用场景与 Set 类似,区别是 Set 不是自动有序的,而 Sorted Set 可以通过用户额外提供一个优先级(Score)的参数来为成员排序,并且是插入有序,即自动排序。

如在使用 Zset 的时候需要额外的输入一个参数 Score,Zset 会自动根据 Score 的值对集合进行排序,我们可以利用这个特性来做具有权重的队列,比如普通消息的 Score 为 1,重要消息的 Score 为 2,然后工作线程可以选择按 Score 的倒序来获取工作任务。

  • 添加一个值 zadd 键 值
  • 显示全部数据 从小到大 zrangebyscore key min max( 负无穷 正无穷 -inf +inf)
  • 移除元素
    • 移除有序集合中的指定元素 zrem 键 字段名
    • 获取有序集合中的个数 zcard 键
    • 获取指定区间的成员数量 zcount 键 数1 数2
@Resource
private RedisTemplate<Object,Object> redisTemplate;

@Test
public void testZset() {
    final String key = "lz";
    ZSetOperations<Object,Object> zset = redisTemplate.opsForZSet();
    zset.add(key, "hello", 1);
    zset.add(key, "world", 6);
    zset.add(key, "good", 4);
    zset.add(key, "bye", 3);

    Set<Object> zsets = zset.range(key, 0, 3);
    for (Object v : zsets) {
        System.out.println("zset-A value :"+v);
    }

    System.out.println("=======");
    Set<Object> zsetB = zset.rangeByScore(key, 0, 3);
    for (Object v : zsetB) {
        System.out.println("zset-B value :"+v);
    }
}