前言
在上篇文章中我们对Redis
进行了简单的介绍,其中有提到:Redis相较于其他的键值数据库有一个特性是支持丰富的数据类型。本篇文章将分别介绍Redis
支持的数据类型。
Redis支持五种数据类型:
string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)
。
string
string
是Redis
最基本的数据类型,和Memcached(也是一个NOSQL)
是一模一样的模型,一个key
对应着一个value
。同时string
是二进制安全的->也就是说它可以包含任意数据,比如图像或者任意一个被序列化了的对象。它是redis最基本的数据类型。它的值最大能够存储512M
。例如下面的简单的2个命令,set
一个键为name
,值为xiaoxiao
127.0.0.1:6379> set name "xiaoxiao"
OK
127.0.0.1:6379> get name
"xiaoxiao"
hash
redis
的哈希是一个string
类型的field
和value
的映射表,比较适合存储对象(因为一个对象有多个键,每个键都对应一个值,而hash的结构和这个对象是类似的)。如下,使用hmset
设置一个hash
,这个hash
的名字叫person
,它有2个field
一个叫age
一个叫name
。其中age
对应的value
为字符串18
,name
对应的value
为xiaoxiao
。当然,它可以设置多个field
,只要往后继续加就行了。hash
一般使用于存储读取修改用户属性。
127.0.0.1:6379> hmset person age 18 name "xiaoxiao"
OK
127.0.0.1:6379> hmget person age
1) "18"
127.0.0.1:6379> hmget person name
1) "xiaoxiao"
list
redis
的列表是一个简单的字符串列表,按照插入顺序,你可以把元素添加到列表的头部和列表的尾部,类似双向链表。如下脚本,lpush
代表从左边放入,rpush
代表从右边放入。lrange 0 10
代表从左边的第0
位开始,数到10
。list
一般适用于消息队列中
127.0.0.1:6379> lpush listtest node1
(integer) 1
127.0.0.1:6379> lpush listtest node2
(integer) 2
127.0.0.1:6379> lpush listtest node3
(integer) 3
127.0.0.1:6379> lpush listtest node4
(integer) 4
127.0.0.1:6379> lrange listtest 0 10
1) "node4"
2) "node3"
3) "node2"
4) "node1"
set集合
redis
的set集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1),非常类似于Java
中的Set
集合。sadd
命令为set
一个元素到集合中,如果元素原来不存在就添加成功返回1
,如果存储就添加失败返回0
。这是set
集合无序不可重复的特性,因为相同的key
计算出来的hash
值时一样的,所以不允许重复添加。set
适用于共同好友等场景
127.0.0.1:6379> sadd settest 123
(integer) 1
127.0.0.1:6379> sadd settest 123
(integer) 0
127.0.0.1:6379> smembers settest
1) "123"
zset命令
redis
的zset
和set
一样不允许有重复元素,也是一个string
类型的集合。不同的是每个元素都会关联一个double
类型的分数。redis
正是通过分数来为集合中的成员进行从小到大的排序。zset
的成员是唯一的,但分数(score)
却可以重复。命令为zadd key score member
。如下 根据分数排序从小到大。分数是可以重复的。zset
适用于排行榜,有优先级的消息队列。
127.0.0.1:6379> zadd person 0 redis
(integer) 1
127.0.0.1:6379> zadd person 1 rocketmq
(integer) 1
127.0.0.1:6379> zadd person 1 java
(integer) 1
127.0.0.1:6379> zadd person 0 xiaoxiao
(integer) 1
127.0.0.1:6379> zadd person 0 work
(integer) 1
127.0.0.1:6379> zrangebyscore person 0 10
1) "redis"
2) "work"
3) "xiaoxiao"
4) "java"
5) "rocketmq"
127.0.0.1:6379>
HyperLogLog
Redis 在
2.8.9
版本添加了HyperLogLog
结构,HyperLogLog
是用来做基数统计的算法,HyperLogLog
的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。在Redis 里面
,HyperLogLog
键只需要花费12 KB
内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比.但是,因为HyperLogLog
只会根据输入元素来计算基数,而不会储存输入元素本身,所以HyperLogLog
不能像集合那样,返回输入的各个元素。
关于基数举个例子:数据集{3,5,2,1,2,3,5}
那么这个数据集的基数集就是{3,5,2,1}
,基数是4。基数估计就是在误差可接受的范围内,快速计算基数。
pfadd
添加元素到HyperLogLog
中,pfcount
为基数的估算值
127.0.0.1:6379> pfadd person "name"
(integer) 1
127.0.0.1:6379> pfadd person "age"
(integer) 1
127.0.0.1:6379> pfadd person "age"
(integer) 0
127.0.0.1:6379> pfadd person "name"
(integer) 0
127.0.0.1:6379> pfcount person
(integer) 2
发布和订阅
Redis 发布订阅
Redis订阅.png(pub/sub)
是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。Redis 客户端可以订阅任意数量的频道。如下图所示:客户端c1、c2、c3同时订阅了s1
当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端,如下图所示
Redis发布.png
在上面我们演示了redis的订阅和发布的流程,下面再来看下如何实现和使用。
我们在一个客户端订阅一个通道叫channel1
,然后再开一个窗口链接redis客户端,
## 客户端A订阅一个名字叫channel1的通道
127.0.0.1:6379> subscribe channel1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel1"
3) (integer) 1
1) "message"
2) "channel1"
3) "day day up"
## 客户端B往通道channel1发布一个消息,回车之后 客户端A会出现:3) "day day up"
127.0.0.1:6379> publish channel1 "day day up"
(integer) 1
如图所示.
发布演示.png
同时 一个客户端可以订阅多个通道,也可以退订这些通道。
redis对事物的支持
Redis 事务可以一次执行多个命令, 并且带有以下两个重要的保证
- 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
- 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行
事物分为三个阶段
a: 开始事物
b: 命令入队
c: 执行事物
关于事物的命令
命令 | 描述 |
---|---|
MULTI | 标记事物开始 |
DISCARD | 取消事务,放弃执行事务块内的所有命令 |
EXEC | 执行所有事务块内的命令 |
UNWATCH | 取消 WATCH 命令对所有 key 的监视。 |
WATCH key [key ...] | 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。 |
附上一个小Demo
:
## 开启事物
127.0.0.1:6379> multi
OK
## 第1个
127.0.0.1:6379> set name "xiaoming"
QUEUED
## 第2个
127.0.0.1:6379> set age "18"
QUEUED
## 第3个
127.0.0.1:6379> sadd person "1" "2" "3"
QUEUED
## 执行里面的语句
127.0.0.1:6379> exec
1) OK
2) OK
3) (integer) 3
127.0.0.1:6379>
附录
Redis
常用的string的命令
命令 | 返回值 | 描述 |
---|---|---|
set key value | OK | 设置一个键值对 |
get key | string | 返回key对应的value |
del key | 0/1 | 删除key,成功1,失败0 |
getrange key start end | string | 返回key的第start开始到end的字符 |
setnx key value | 0/1 | key存在设置,不存在不设置 |
incr key | value | 对key原子+1,返回加完的值 |
setex key seconds value | OK | 设置一个值为value的key,过期时间seconds |
decr key | value | 返回减1之后的值 |
总结
这篇文章简单介绍了Redsi的基本数据类型和常见的一些命令,实际上redis本身就是从简单的设计来考虑的。然后我们学习了基于Redis的订阅和发布特性和redis对事物的支持,并各举出了一个小例子。当然,本篇的内容还是比较浅显的,实际上redsi还有一些高级一点的特性,我们在下篇文章中介绍。现在是国庆节即将一半,前面陪家人和同事在杭州玩了几天,后面几天静心学习,保持更新自己的知识。
网友评论