NoSQL数据库——Redis(2)

上篇我们讲了非关系型数据库的简介,有兴趣的朋友可以点击链接:

NoSQL数据库——简介(1)

这篇我们就详细说说redis是什么。

一、Redis数据结构

REmote DIctionary Server(Redis) 是一个由 Salvatore Sanfilippo 写的 key-value 存储系统,是跨平台的非关系型数据库。Redis 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库,并提供多种语言的 API。

Redis 通常被称为数据结构服务器,因为值(value)可以是字符串(String)、哈希(Hash)、列表(list)、集合(sets)和有序集合(sorted sets)等类型。

String(字符串)

redis的string 是 与 Memcached 一样的最基本的类型,一个 key 对应一个 value,string 类型的值最大能存储 512MB,包含任何数据。比如jpg图片或者序列化的对象。

//SET/GET命令:
redis 127.0.0.1:6379> SET keyName "value"
OK
redis 127.0.0.1:6379> GET keyName
"value"

//将给定 key 的值设为 value ,并返回 key 的旧值(old value)。
GETSET key value

//只有在 key 不存在时设置 key 的值。存在就返回0
SETNX key value

//将值 value 关联到 key ,并将 key 的过期时间设为 seconds (以秒为单位)。
SETEX key seconds value

//将 key 中储存的数字值增一。
INCR key

//将 key 中储存的数字值减一。
DECR key

Hash(哈希)

Redis hash 是一个键值(key=>value)对集合,也是string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象,每个 hash 可以存储 2^{32} -1 键值对(40多亿)。

//SET命令
redis 127.0.0.1:6379> HMSET keyName field1 "Hello" field2 "World"
"OK"
//GET field1
redis 127.0.0.1:6379> HGET keyName field1
"Hello"
//GET field2
redis 127.0.0.1:6379> HGET keyName field2
"World"
//删除
redis 127.0.0.1:6379> DEL keyName

List(列表)

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边),列表最多可存储 2^{32}- 1 元素 

redis 127.0.0.1:6379> lpush keyName redis
(integer) 1
redis 127.0.0.1:6379> lpush keyName mongodb
(integer) 2
redis 127.0.0.1:6379> lpush keyName rabbitmq
(integer) 3
redis 127.0.0.1:6379> lrange keyName 0 10
1) "rabbitmq"
2) "mongodb"
3) "redis"

SET(集合)

Redis 的 Set 是 string 类型的无序集合。集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1),集合中最大的成员数为 2^{32} - 1

//添加一个 string 元素到 key 对应的 set 集合中,成功返回 1,如果元素已经在集合中返回 0。
sadd key member
示例:
redis 127.0.0.1:6379> sadd keyName redis
(integer) 1
redis 127.0.0.1:6379> sadd keyName mongodb
(integer) 1
redis 127.0.0.1:6379> sadd keyName rabbitmq
(integer) 1
redis 127.0.0.1:6379> sadd keyName rabbitmq
(integer) 0
redis 127.0.0.1:6379> smembers keyName
1) "redis"
2) "rabbitmq"
3) "mongodb"

//获取集合的成员数
SCARD key

zset(sorted set:有序集合)

Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复。

redis 127.0.0.1:6379> zadd keyName 1 redis
(integer) 1
redis 127.0.0.1:6379> zadd keyName 0 mongodb
(integer) 1
redis 127.0.0.1:6379> zadd keyName 2 rabbitmq
(integer) 1
redis 127.0.0.1:6379> zadd keyName 0 rabbitmq
(integer) 0
redis 127.0.0.1:6379> ZRANGEBYSCORE keyName 0 1000
 1)  "mongodb"
 2)  "rabbitmq"
 3)  "redis"

Stream

Redis Stream 是 Redis 5.0 版本新增加的数据结构。Redis Stream 主要用于消息队列(MQ,Message Queue),Redis 本身是有一个 Redis 发布订阅 (pub/sub) 来实现消息队列的功能,但它有个缺点就是消息无法持久化,如果出现网络断开、Redis 宕机等,消息就会被丢弃。

Stream结构:

  • Consumer Group :消费组,使用 XGROUP CREATE 命令创建,一个消费组有多个消费者(Consumer)。
  • last_delivered_id :游标,每个消费组会有个游标 last_delivered_id,任意一个消费者读取了消息都会使游标 last_delivered_id 往前移动。
  • pending_ids :消费者(Consumer)的状态变量,作用是维护消费者的未确认的 id。 pending_ids 记录了当前已经被客户端读取的消息,但是还没有 ack (Acknowledge character:确认字符)。
//追加消息
XADD key ID field string [field string ...]
//ID,最常使用*,表示由Redis生成消息ID,这也是强烈建议的方案。
// field string [field string], 就是当前消息内容,由1个或多个key-value构成。
//示例:
127.0.0.1:6379> XADD memberMessage * user kang msg Hello
"1553439850328-0"
127.0.0.1:6379> XADD memberMessage * user zhong  msg nihao
"1553439858868-0"

//获取消息  XREAD
127.0.0.1:6379> XREAD streams memberMessage 0
1) 1) "memberMessage"
   2) 1) 1) "1553439850328-0"
         2) 1) "user"
            2) "kang"
            3) "msg"
            4) "Hello"
      2) 1) "1553439858868-0"
         2) 1) "user"
            2) "zhong"
            3) "msg"
            4) "nihao"

还有三种高级数据结构,简略介绍一下:

Bitmap 位图

以bit位来管理的string类型数据,基于string定义了一组bit位操作,存储成本低,1属性~1bit

GEO 地理位置

GeoHash 利用 Z阶曲线,将二维点转换为一阶曲线,地球二维经纬度坐标转化为一维52bit整数编码,整数编码(score)反向解码获得经纬度

HyperLogLog

HyperLogLog是Redis的高级数据结构,是统计基数的利器。每个 HyperLogLog 键只需要花费 12 KB 内存,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。

主要的命令有三个:

//添加指定元素到 HyperLogLog 中。
PFADD key element [element ...]

//返回给定 HyperLogLog 的基数估算值。
PFCOUNT key [key ...]

//将多个 HyperLogLog 合并为一个 HyperLogLog
PFMERGE destkey sourcekey [sourcekey ...]

基于Reids的消息队列实现有很多种,例如:PUB/SUB(订阅/发布模式)、基于List的 LPUSH+BRPOP 的实现、基于Sorted-Set的实现。Stream类型的出现,几乎满足了消息队列的全部内容,包括:消息ID的序列化生成、消息遍历、消息的阻塞和非阻塞读取、消息的分组消费、未完成消息的处理、消息队列监控等。上面的示例只是两个基础功能,对redis用作消息队列的方案,感兴趣的朋友可以看看下面的文章,本文不过多赘述。

基于Redis的Stream类型的完美消息队列解决方案

注意,Redis支持多个数据库,并且每个数据库的数据是隔离的不能共享,并且基于单机才有,如果是集群就没有数据库的概念。每个数据库对外都是一个从0开始的递增数字命名,Redis默认支持16个数据库(可以通过配置文件支持更多,无上限),可以通过配置databases来修改这一数字。

二、Redis命令

我们上面演示了基础数据类型的使用命令,下面演示其他的几种redis命令Redis 发布订阅

Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。例如:你订阅了一份报纸,每天有新的新闻登载在报纸上,你就能接收到报纸并且读取消息。

//订阅一个或多个符合给定模式的频道。
PSUBSCRIBE pattern [pattern ...]

//查看订阅与发布系统状态。
PUBSUB subcommand [argument [argument ...]]

//将信息发送到指定的频道
PUBLISH channel message

//退订所有给定模式的频道。
PUNSUBSCRIBE [pattern [pattern ...]]

//订阅给定的一个或多个频道的信息
SUBSCRIBE channel [channel ...]

//退订给定的频道。
UNSUBSCRIBE [channel [channel ...]]

事务

Redis 事务可以一次执行多个命令, 以下三个阶段:

  • 开始事务。批量操作在发送 EXEC 命令前被放入队列缓存
  • 命令入队。收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行
  • 执行事务。在事务执行时,其他客户端提交的命令请求不会插入到事务执行命令序列中。
//标记一个事务块的开始。
MULTI

//取消事务,放弃执行事务块内的所有命令。
DISCARD

//执行所有事务块内的命令。
EXEC

//取消 WATCH 命令对所有 key 的监视。
UNWATCH

//监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。
WATCH key [key ...]

三、Redis 协议

RESP Redis Serialization Protocol (Redis序列化协议) RESP 二进制安全,供redis 或 其他Client-Server使用 Redis内部。

请求响应模型

  • Ping-Pong 模式 几乎所有命令响应模式
  • Pipeline 模式  一次发送多个请求,然后等待多个响应
  • Pub/Sub 模式 client订阅channel,push协议响应

四、redis可视化工具

类似于mysql数据库的可视化工具Navicat,redis也有可视化工具。

我们常用的主要有

Redis Desktop Manager

Another Redis Desktop Manager

当然,redis的用法远不止这些,我们下期继续探讨redis。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值