Redis基础数据结构

以Docker的方式运行redis实例

#拉取redis镜像
docker pull redis
#运行redis容器
docker run --name myredis  -d -p6379:6379 redis
#以交互式的终端的方式运行
docker exec -it myredis redis-cli

Redis基本数据结构

Redis 有5种基本数据结构,分别是String, list, hash, set, zset,下面我们就这5种基本类型简单介绍一下用法

String (字符串)

与ArrayList类似的是,string是一种动态字符串的形式,它采用了跟ArrayList相同的扩容机制来减少内存的平凡修改。
字符串的使用非常广泛,我们可以将对象转成JSON字符串的格式塞进Redis做缓存。

【键值对】

127.0.0.1:6379> set name haliaddel
OK
127.0.0.1:6379> get name
"haliaddel"
127.0.0.1:6379> EXISTS name
(integer) 1
127.0.0.1:6379> del name
(integer) 1
127.0.0.1:6379> get name
(nil)

【批量键值对】

127.0.0.1:6379> set name1 happy
OK
127.0.0.1:6379> set name2 bubble
OK
127.0.0.1:6379> mget name1 name2
1) "happy"
2) "bubble"
127.0.0.1:6379> mset name1 haliaddel name2 lsy
OK
127.0.0.1:6379> mget name1 name2
1) "haliaddel"
2) "lsy"

【过期和set命令扩展】

127.0.0.1:6379> set name h
OK
127.0.0.1:6379> expire name 5
(integer) 1
127.0.0.1:6379> get name
(nil)

#等价于set+expire
127.0.0.1:6379> setex name 5 h
OK
127.0.0.1:6379> get name
"h"
127.0.0.1:6379> get name
(nil)

#如果存在对应的key,就不会覆盖
127.0.0.1:6379> setnx name h
(integer) 1
127.0.0.1:6379> get name
"h"
127.0.0.1:6379> setnx name hello
(integer) 0
127.0.0.1:6379> get name
"h"

【计数】
如果value是一个整数,我们可以对其进行加减操作

127.0.0.1:6379> set age 30
OK
127.0.0.1:6379> incr age
(integer) 31
127.0.0.1:6379> incrby age 5
(integer) 36
127.0.0.1:6379> incrby age -19
(integer) 17

list(列表)

Redis的list相当于Java语言里面的LinkedList,它是链表而不是数组。这意味着list的插入和删除操作都是o(1),但是索引是o(n)。列表中的每个节点都是个双向指针。因此list是个双向队列,我们可以选择右进左出,或者左进右出的方式来消费缓存数据。

Redis的列表结构常用来做异步队列。

【右进左出:队列】

127.0.0.1:6379> rpush books java golang
(integer) 2
127.0.0.1:6379> llen books
(integer) 2
127.0.0.1:6379> lpop books
"java"
127.0.0.1:6379> lpop books
"golang"
127.0.0.1:6379> lpop books
(nil)

【右进右出:栈】

127.0.0.1:6379> rpush books python java c
(integer) 3
127.0.0.1:6379> rpop books
"c"
127.0.0.1:6379> rpop books
"java"
127.0.0.1:6379> rpush books c++
(integer) 2
127.0.0.1:rpop books
"c++"

【慢操作】
lindex相当于Java链表的get(int index),它需要对整个链表进行遍历,性能随着index的增大而增大。
ltrim start_index end_index 两个参数定义了一个空间,保留这空间里面的数据,其余全部砍掉。我们可以用ltrim来实现一个定长的链表。
index可以是复数,他表示倒数第N个元素。

127.0.0.1:6379> rpush books py java c c++
(integer) 4
127.0.0.1:6379> lindex books 1
"java"
127.0.0.1:6379> lindex books 0
"py"
127.0.0.1:6379> lindex books -1
"c++"
#遍历所有数据,0(n),慎用
127.0.0.1:6379> lrange books 0 -1
1) "py"
2) "java"
3) "c"
4) "c++"
#截取固定区间
127.0.0.1:6379> ltrim books 1 2
OK
127.0.0.1:6379> lrange books 0 -1
1) "java"
2) "c"

【快速列表】
Redis list的底层存储的不是一个简单的linkedList, 而是一种“快速列表”。
首先,在元素较少的情况下,会使用一块连续内存,这个接口是ziplist,即压缩列表。他将所有元素彼此挨着一起存储,分配的是一块连续的内存; 当元素较多的情况下,才会改成quicklsit。普通的链表需要存储指针的空间,quicklist是一群连着的ziplist,各个ziplist之间通过双向指针指定,节省了ziplist内部元素的指针空间。

hash (字典)

Redis的字典相当于Java 的HashMap,都是采用的数组加链表的方式。不同的是Redis采用的渐进式的rehash方式,它没有一次性将所有数据都rehash。
渐进式rehash会在rehash的同时,保留新旧两个hash结构。查询会同时查询两个hash结构,然后在后续的定时任务及hash操作指令中,循序渐进地将旧hash的内容一点点迁移到新的hash结构中。

127.0.0.1:6379> hset books java "think in java"
(integer) 1
127.0.0.1:6379> hset books golang "concurrency in go"
(integer) 1
127.0.0.1:6379> hset books python "python book"
(integer) 1
127.0.0.1:6379> hgetall books							#获取所有key value, entries()
1) "java"
2) "think in java"
3) "golang"
4) "concurrency in go"
5) "python"
6) "python book"
127.0.0.1:6379> hlen books
(integer) 3
127.0.0.1:6379> hget books java
"think in java"
127.0.0.1:6379> hset books golang "learning go programming"				#更新操作返回0
(integer) 0
127.0.0.1:6379> hget books golang
"learning go programming"
127.0.0.1:6379> hmset books java "effective java" python "py"
OK
127.0.0.1:6379> hgetall books
1) "java"
2) "effective java"
3) "golang"
4) "learning go programming"
5) "python"
6) "py"

同字符串一样,hash结构中单个子key也可以用来计数

127.0.0.1:6379> hset user-laoqian age 30
(integer) 1
127.0.0.1:6379> hincrby user-laoqian age 1
(integer) 31

set (集合)

与JAVA的Set一致,它的内容是唯一的,无序的。

127.0.0.1:6379> sadd books python
(integer) 1
127.0.0.1:6379> sadd books java
(integer) 1
127.0.0.1:6379> sadd books java					#重复添加
(integer) 0
127.0.0.1:6379> smembers books					#查看所有对象
1) "java"
2) "python"
127.0.0.1:6379> sismember books java				#判断是不是存在
(integer) 1
127.0.0.1:6379> scard books						#相当于count
(integer) 2
127.0.0.1:6379> spop books
"python"

zset (有序集合)

有序集合相是一个SortSet 和HashMap的结合体,一方面他是个set,保证了数据的唯一性,另一方面,他可以给每个value赋予一个score,这个score可以用作排序的评分。他的内部实现是一种叫跳跃列表的数据结构。
zset是一种应用广泛的数据结构,比如,我们可以用它来存储粉丝列表,value表示粉丝的信息,score表示粉丝的加入时间。又或是考试成绩,value用来存储学生的id,score是他的考试成绩。
跳跃列表的原理在后续会介绍,在这里我们简单了解一下。他是一种资源快速定位的结构,通过层级的确定一步步往下潜,与B-Tree有点相同,但是它是身兼数值,且是一种链表结构。

跳跃列表

127.0.0.1:6379> zadd books 9.0 "think in java"
(integer) 1
127.0.0.1:6379> zadd books 8.5 "java concurrency"
(integer) 1
127.0.0.1:6379> zadd books 8.6 "java book"
(integer) 1
127.0.0.1:6379> zrange books 0 -1
1) "java concurrency"
2) "java book"
3) "think in java"
127.0.0.1:6379> zrevrange books 0 -1					#按score逆序排列,参数名指定排序的范围
1) "think in java"
2) "java book"
3) "java concurrency"
127.0.0.1:6379> zcard books								#相当于count
(integer) 3
127.0.0.1:6379> zscore books "java book"			#获取指定value的score,内部score使用double类型进行存储,因此会存在精度问题
"8.5999999999999996"
127.0.0.1:6379> zrank books "java book"			#获取排名
(integer) 1
127.0.0.1:6379> zrangebyscore books 0 9			#获取指定score范围之内的数据
1) "java concurrency"
2) "java book"
3) "think in java"
127.0.0.1:6379> zrangebyscore books 0 8.7
1) "java concurrency"
2) "java book"
127.0.0.1:6379> zrangebyscore books -inf 8.7 withscores			# -inf 无穷小, withcores 返回分值
1) "java concurrency"
2) "8.5"
3) "java book"
4) "8.5999999999999996"
127.0.0.1:6379> zrem books "java book"				#删除
(integer) 1
127.0.0.1:6379> zrange books 0 -1
1) "java concurrency"
2) "think in java"

容器型数据

list, set ,zset, hash都是容器型数据,他们存在如下特性:

  1. create if not exists: 若在操作时发现容器不存在,则会创建一个容器进行操作。
  2. drop if no elements: 如果移除内部所有数据,则会自主删除容器。

过期时间

redis所有数据结构都是可以设置过期时间的,需要注意的是,redis的过期时间是针对于对象的,譬如建了一个名为names的hash对象,设置其过期时间为24h,则其将会在24h之后生效,不是单个key的时间。
如果对某个设了过期时间的数据进行更新操作,那么这个过期时间就被无效化了

127.0.0.1:6379> set name h
OK
127.0.0.1:6379> expire name 600
(integer) 1
127.0.0.1:6379> ttl name
(integer) 594
127.0.0.1:6379> set name a
OK
127.0.0.1:6379> ttl name
(integer) -1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值