Redis 数据类型list、hash、zset 原理、使用场景说明
面试中常会被问到Redis 的数据类型用过哪些,被问的多了就想整理一下,以被下次再被问时可以很好的回复,现在对redis中list、hash、zset进行梳理。
一、list
Redis list的实现为一个双向链表 ; List 列表是简单的字符串列表,按照插入顺序排序,可以从头部或尾部向 List 列表添加元素。
1.1说明:
1、 Redis的列表允许用户从序列的两端推入或者弹出元素
2、可以做消息队列,以完成多程序之间的消息交换。可以用push操作将任务存在list中(生产者), 然后线程在用pop操作将任务取出进行执行。(消费者)
1.2 使用场景:
需要的存储结构:一个存储空间保存多个数据,且通过数据可以体现进入顺序
list类型:保存多个数据,底层使用双向链表存储结构实现
ps: lpop、rpop 会将list元素取出并移出,和队列特性一样;
lrange、rrange 取出元素但不移除
1.3 可实现常用数据结构
Stack(栈) = LPUSH + LPOP
Queue(队列)= LPUSH + RPOP
Blocking MQ(阻塞队列)= LPUSH + BRPOP
1.4常用命令:
lpush,rpush,lpop,rpop,lrange,BLPOP(阻塞版)等。
1.5代码实例
/** * redis 数据类型list测试 * Redis list的实现为一个双向链表 * List 列表是简单的字符串列表,按照插入顺序排序,可以从头部或尾部向 List 列表添加元素。 * 使用场景 * list类型:保存多个数据,底层使用双向链表存储结构实现 * <p> * ps: lpop、rpop 会将list元素取出并移出,和队列特性一样; * lrange、rrange 取出元素但不移除 */ @Test public void redisList() { //1.连接redis Jedis jedis = new Jedis("127.0.0.1", 6379); //2.操作redis jedis.lpush("list1", "a", "b", "c"); jedis.rpush("list1", "x"); // 取出所有数据 不会将元素移除 List<String> list1 = jedis.lrange("list1", 0, -1); System.out.println("list1 = " + list1); // 可以从两边取数据插入,也可以从左右两边取数据--Redis的列表允许用户从序列的两端推入或者弹出元素 System.out.println("jedis.lpop(\"list1\") = " + jedis.lpop("list1")); System.out.println("jedis.rpop(\"list1\") = " + jedis.rpop("list1")); List<String> list2 = jedis.lrange("list1", 0, -1); list2.forEach(x -> { System.out.println("jedis.lpop(\"list2\") = " + jedis.lpop("list1")); }); //(2)消息队列,以完成多程序之间的消息交换。可以用push操作将任务存在list中(生产者),然后线程在用pop操作将任务取出进行执行。(消费者) // blpop 阻塞弹出 // jedis.blpop("list1"); jedis.close(); }
二、 hash 类型
2.1 说明:hash 存储可以存储一个对象-多个属性,取时直接取出成 转换成一个Map,
省去了像存放json字符串序列化和反序列化也便于修改
新的存储需求:对一系列存储的数据进行编组,方便管理,典型应用存储对象信息
需要的存储结构:一个存储空间保存多个键值对数据
ps: hash类型:底层使用哈希表结构实现数据存储
hash类型下的value只能存储字符串
2.2常用命令
hset、hget、hgetall、hkeys、hvals、hsetnx
hmget key field1,feild2 :可以获取多个filed
2.3 代码实例
/** * redis 数据类型hash测试 * 说明:hash 存储可以存储一个对象-多个属性,取时直接取出成 转换成一个Map, * 省去了像存放json字符串序列化和反序列化也便于修改 * 新的存储需求:对一系列存储的数据进行编组,方便管理,典型应用存储对象信息 * 常用命令 * hset、hget、hgetall、hkeys、hvals、hsetnx * hmget key field1,feild2 :可以获取多个filed */ @Test public void redisHash() { Jedis jedis = new Jedis("127.0.0.1", 6379); jedis.set("liyanbo", "777"); System.out.println("jedis.get(\"liyanbo\") = " + jedis.get("liyanbo")); //1、 hash 存储可以存储一个对象-多个属性,取时直接取出成 转换成一个Map,省去了像存放json字符串序列化和反序列化也便于修改 jedis.hset("hashKey", "keyO1", "key1"); jedis.hset("hashKey", "keyO2", "key2"); jedis.hset("hashKey", "keyO3", "key3"); Map<String, String> map02 = jedis.hgetAll("hashKey"); System.out.println("map02 = " + map02);// 可以直接使用 map 取对应的值 //1.3 jedis.close(); }
3、zSet 数据类型
zSetdiceng底层数据结构是跳跃表(skipList),因为skiplist算法实现的难度要低于平衡树
3.1 说明:Redis zset和set一样也是string类型元素的集合,且不允许重复的成员。不同之处在于,
每个元素都与双类型的分数相关联
Redis 有序集合和集合一样也是 string 类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。
有序集合的成员是唯一的,但分数(score)却可以重复
3.2 场景:
1、实现积分排行榜功能,就采用了redis zset有序集合来实现
2、学生ID,学生分数,存放后可排序
Redis zset和set一样也是string类型元素的集合,且不允许重复的成员。不同之处在于,每个元素都与双类型的分数相关联
3.3常用命令:
zadd:新增成员, zadd:新增成员
zrangebylex:指定集合区间,获取列表
zrangebyscore:指定分数区间,获取列表
zrevrange:倒序展示列表
3.4 代码实例
/** * redis 数据类型ZSet测试 * 说明:Redis zset和set一样也是string类型元素的集合,且不允许重复的成员。不同之处在于, * 每个元素都与双类型的分数相关联 * Redis 有序集合和集合一样也是 string 类型元素的集合,且不允许重复的成员。 * 不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。 * 有序集合的成员是唯一的,但分数(score)却可以重复 * 场景: * 1、实现积分排行榜功能,就采用了redis zset有序集合来实现 * 2、学生ID,学生分数,存放后可排序 * Redis zset和set一样也是string类型元素的集合,且不允许重复的成员。不同之处在于,每个元素都与双类型的分数相关联 */ @Test public void redisZSet() { //1.连接redis Jedis jedis = new Jedis("127.0.0.1", 6379); jedis.zadd("zSetKey", 10, "liyanbo"); jedis.zadd("zSetKey", 9, "yanda"); jedis.zadd("zSetKey", 15, "zhiyuan"); jedis.zadd("zSetKey", 12, "chengqiang"); // 从高到底排序输出指定范围的数据 Set<String> setSort = jedis.zrevrange("zSetKey", 0, 4); System.out.println("setSort = " + setSort); // 取出最高分数信息 // System.out.println("jedis.zpopmax(\"zSetKey\") = " + jedis.zpopmin("zSetKey")); jedis.close(); }
看到的小伙伴如有疑问或问题可以评论回复一起讨论沟通。