2. Redis基本操作及数据结构

2018-10-04  本文已影响0人  都是浮云啊

前言

在上篇文章中我们对Redis进行了简单的介绍,其中有提到:Redis相较于其他的键值数据库有一个特性是支持丰富的数据类型。本篇文章将分别介绍Redis支持的数据类型。

Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)

string

stringRedis最基本的数据类型,和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类型的fieldvalue的映射表,比较适合存储对象(因为一个对象有多个键,每个键都对应一个值,而hash的结构和这个对象是类似的)。如下,使用hmset设置一个hash,这个hash的名字叫person,它有2个field一个叫age一个叫name。其中age对应的value为字符串18,name对应的valuexiaoxiao。当然,它可以设置多个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位开始,数到10list一般适用于消息队列中

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命令

rediszsetset一样不允许有重复元素,也是一个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 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。Redis 客户端可以订阅任意数量的频道。如下图所示:客户端c1、c2、c3同时订阅了s1

Redis订阅.png
当有新消息通过 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 事务可以一次执行多个命令, 并且带有以下两个重要的保证

  1. 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  2. 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行

事物分为三个阶段
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还有一些高级一点的特性,我们在下篇文章中介绍。现在是国庆节即将一半,前面陪家人和同事在杭州玩了几天,后面几天静心学习,保持更新自己的知识。

上一篇下一篇

猜你喜欢

热点阅读