Redis教程

简介

Redis简介

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

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

Redis 是完全开源的,遵守 BSD 协议,是一个高性能的 key-value 数据库。
Redis 与其他 key - value 缓存产品有以下三个特点:

  1. Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
  2. Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
  3. Redis支持数据的备份,即master-slave模式的数据备份

Redis 优势

  1. 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
  2. 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
  3. 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
  4. 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性

Redis与其他key-value存储有什么不同?

Redis有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象。

Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样Redis可以做很多内部复杂性很强的事情。同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。

Redis安装

window下安装

下载地址https://github.com/tporadowski/redis/releases
Redis 支持 32 位和 64 位。这个需要根据你系统平台的实际情况选择,这里我们下载 Redis-x64-xxx.zip压缩包到 C 盘,解压后,将文件夹重新命名为 redis。
在这里插入图片描述
在这里插入图片描述
打开一个 cmd 窗口 使用 cd 命令切换目录到 C:\redis 运行:

redis-server.exe redis.windows.conf

如果想方便的话,可以把 redis 的路径加到系统的环境变量里,这样就省得再输路径了,后面的那个 redis.windows.conf 可以省略,如果省略,会启用默认的。输入之后,会显示如下界面:
在这里插入图片描述
这时候另启一个 cmd 窗口,原来的不要关闭,不然就无法访问服务端了。

切换到 redis 目录下运行:

redis-cli.exe -h 127.0.0.1 -p 6379

设置键值对:

set myKey abc

取出键值对:

get myKey

在这里插入图片描述

Linux下安装

下载地址:http://redis.io/download,下载最新稳定版本。

$ wget http://download.redis.io/releases/redis-6.0.6.tar.gz
$ tar xzf redis-6.0.6.tar.gz
$ cd redis-6.0.6
$ make

进入到解压后的 src 目录,通过如下命令启动Redis:

$ src/redis-server

您可以使用内置的客户端与Redis进行交互:

$ src/redis-cli
redis> set foo bar
OK
redis> get foo
"bar"

ubuntu 下安装

在 Ubuntu 系统安装 Redis 可以使用以下命令:

$sudo apt-get update
$sudo apt-get install redis-server

启动 Redis

$ redis-server

查看 redis 是否启动?

$ redis-cli

以上命令将打开以下终端:

redis 127.0.0.1:6379>

127.0.0.1 是本机 IP ,6379 是 redis 服务端口。现在我们输入 PING 命令。

redis 127.0.0.1:6379> ping
PONG

以上说明我们已经成功安装了redis。

Redis配置

Redis 的配置文件位于 Redis 安装目录下,文件名为 redis.conf(Windows 名为 redis.windows.conf)。

你可以通过 CONFIG 命令查看或设置配置项。

语法
Redis CONFIG 命令格式如下:

redis 127.0.0.1:6379> CONFIG GET CONFIG_SETTING_NAME

实例

redis 127.0.0.1:6379> CONFIG GET loglevel

1) "loglevel"
2) "notice"

使用 * 号获取所有配置项:
实例

redis 127.0.0.1:6379> CONFIG GET *

  1) "dbfilename"
  2) "dump.rdb"
  3) "requirepass"
  4) ""
  5) "masterauth"
  6) ""
  7) "unixsocket"
  8) ""
  9) "logfile"
 10) ""
 11) "pidfile"
 12) "/var/run/redis.pid"
 13) "maxmemory"
 14) "0"
 15) "maxmemory-samples"
 16) "3"
 17) "timeout"
 18) "0"
 19) "tcp-keepalive"
 20) "0"
 21) "auto-aof-rewrite-percentage"
 22) "100"
 23) "auto-aof-rewrite-min-size"
 24) "67108864"
 25) "hash-max-ziplist-entries"
 26) "512"
 27) "hash-max-ziplist-value"
 28) "64"
 29) "list-max-ziplist-entries"
 30) "512"
 31) "list-max-ziplist-value"
 32) "64"
 33) "set-max-intset-entries"
 34) "512"
 35) "zset-max-ziplist-entries"
 36) "128"
 37) "zset-max-ziplist-value"
 38) "64"
 39) "hll-sparse-max-bytes"
 40) "3000"
 41) "lua-time-limit"
 42) "5000"
 43) "slowlog-log-slower-than"
 44) "10000"
 45) "latency-monitor-threshold"
 46) "0"
 47) "slowlog-max-len"
 48) "128"
 49) "port"
 50) "6379"
 51) "tcp-backlog"
 52) "511"
 53) "databases"
 54) "16"
 55) "repl-ping-slave-period"
 56) "10"
 57) "repl-timeout"
 58) "60"
 59) "repl-backlog-size"
 60) "1048576"
 61) "repl-backlog-ttl"
 62) "3600"
 63) "maxclients"
 64) "4064"
 65) "watchdog-period"
 66) "0"
 67) "slave-priority"
 68) "100"
 69) "min-slaves-to-write"
 70) "0"
 71) "min-slaves-max-lag"
 72) "10"
 73) "hz"
 74) "10"
 75) "no-appendfsync-on-rewrite"
 76) "no"
 77) "slave-serve-stale-data"
 78) "yes"
 79) "slave-read-only"
 80) "yes"
 81) "stop-writes-on-bgsave-error"
 82) "yes"
 83) "daemonize"
 84) "no"
 85) "rdbcompression"
 86) "yes"
 87) "rdbchecksum"
 88) "yes"
 89) "activerehashing"
 90) "yes"
 91) "repl-disable-tcp-nodelay"
 92) "no"
 93) "aof-rewrite-incremental-fsync"
 94) "yes"
 95) "appendonly"
 96) "no"
 97) "dir"
 98) "/home/deepak/Downloads/redis-2.8.13/src"
 99) "maxmemory-policy"
100) "volatile-lru"
101) "appendfsync"
102) "everysec"
103) "save"
104) "3600 1 300 100 60 10000"
105) "loglevel"
106) "notice"
107) "client-output-buffer-limit"
108) "normal 0 0 0 slave 268435456 67108864 60 pubsub 33554432 8388608 60"
109) "unixsocketperm"
110) "0"
111) "slaveof"
112) ""
113) "notify-keyspace-events"
114) ""
115) "bind"
116) ""

编辑配置
你可以通过修改 redis.conf 文件或使用 CONFIG set 命令来修改配置。

语法
CONFIG SET 命令基本语法:

redis 127.0.0.1:6379> CONFIG SET CONFIG_SETTING_NAME NEW_CONFIG_VALUE

实例

redis 127.0.0.1:6379> CONFIG SET loglevel "notice"
OK
redis 127.0.0.1:6379> CONFIG GET loglevel

1) "loglevel"
2) "notice"

参数说明

redis.conf 配置项说明如下:

序号配置项说明
1daemonize noRedis 默认不是以守护进程的方式运行,可以通过该配置项修改,使用 yes 启用守护进程(Windows 不支持守护线程的配置为 no )
2pidfile /var/run/redis.pid当 Redis 以守护进程方式运行时,Redis 默认会把 pid 写入 /var/run/redis.pid 文件,可以通过 pidfile 指定
3port 6379指定 Redis 监听端口,默认端口为 6379,作者在自己的一篇博文中解释了为什么选用 6379 作为默认端口,因为 6379 在手机按键上 MERZ 对应的号码,而 MERZ 取自意大利歌女 Alessia Merz 的名字
4bind 127.0.0.1绑定的主机地址
5timeout 300当客户端闲置多长秒后关闭连接,如果指定为 0 ,表示关闭该功能
6loglevel notice指定日志记录级别,Redis 总共支持四个级别:debug、verbose、notice、warning,默认为 notice
7logfile stdout日志记录方式,默认为标准输出,如果配置 Redis 为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给 /dev/null
8databases 16设置数据库的数量,默认数据库为0,可以使用SELECT 命令在连接上指定数据库id
9save <seconds> <changes> Redis 默认配置文件中提供了三个条件:save 900 1 , save 300 10 , save 60 10000 分别表示 900 秒(15 分钟)内有 1 个更改,300 秒(5 分钟)内有 10 个更改以及 60 秒内有 10000 个更改。指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合
10rdbcompression yes指定存储至本地数据库时是否压缩数据,默认为 yes,Redis 采用 LZF 压缩,如果为了节省 CPU 时间,可以关闭该选项,但会导致数据库文件变的巨大
11dbfilename dump.rdb指定本地数据库文件名,默认值为 dump.rdb
12dir ./指定本地数据库存放目录
13slaveof 设置当本机为 slave 服务时,设置 master 服务的 IP 地址及端口,在 Redis 启动时,它会自动从 master 进行数据同步
14masterauth 当 master 服务设置了密码保护时,slav 服务连接 master 的密码
15requirepass foobared设置 Redis 连接密码,如果配置了连接密码,客户端在连接 Redis 时需要通过 AUTH 命令提供密码,默认关闭
16maxclients 128设置同一时间最大客户端连接数,默认无限制,Redis 可以同时打开的客户端连接数为 Redis 进程可以打开的最大文件描述符数,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis 会关闭新的连接并向客户端返回 max number of clients reached 错误信息
17maxmemory 指定 Redis 最大内存限制,Redis 在启动时会把数据加载到内存中,达到最大内存后,Redis 会先尝试清除已到期或即将到期的 Key,当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis 新的 vm 机制,会把 Key 存放内存,Value 会存放在 swap 区
18appendonly no指定是否在每次更新操作后进行日志记录,Redis 在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为 redis 本身同步数据文件是按上面 save 条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为 no
19appendfilename appendonly.aof指定更新日志文件名,默认为 appendonly.aof
20appendfsync everysec指定更新日志条件,共有 3 个可选值:no:表示等操作系统进行数据缓存同步到磁盘(快)//always:表示每次更新操作后手动调用 fsync() 将数据写到磁盘(慢,安全)//everysec:表示每秒同步一次(折中,默认值)
21vm-enabled no指定是否启用虚拟内存机制,默认值为 no,简单的介绍一下,VM 机制将数据分页存放,由 Redis 将访问量较少的页即冷数据 swap 到磁盘上,访问多的页面由磁盘自动换出到内存中(在后面的文章我会仔细分析 Redis 的 VM 机制)
22vm-swap-file /tmp/redis.swap虚拟内存文件路径,默认值为 /tmp/redis.swap,不可多个 Redis 实例共享
23vm-max-memory 0将所有大于 vm-max-memory 的数据存入虚拟内存,无论 vm-max-memory 设置多小,所有索引数据都是内存存储的(Redis 的索引数据 就是 keys),也就是说,当 vm-max-memory 设置为 0 的时候,其实是所有 value 都存在于磁盘。默认值为 0
24vm-page-size 32Redis swap 文件分成了很多的 page,一个对象可以保存在多个 page 上面,但一个 page 上不能被多个对象共享,vm-page-size 是要根据存储的 数据大小来设定的,作者建议如果存储很多小对象,page 大小最好设置为 32 或者 64bytes;如果存储很大大对象,则可以使用更大的 page,如果不确定,就使用默认值
25vm-pages 134217728设置 swap 文件中的 page 数量,由于页表(一种表示页面空闲或使用的 bitmap)是在放在内存中的,,在磁盘上每 8 个 pages 将消耗 1byte 的内存
26vm-max-threads 4设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟。默认值为4
27glueoutputbuf yes设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启
28hash-max-zipmap-entries 64 //hash-max-zipmap-value 512指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法
29activerehashing yes指定是否激活重置哈希,默认为开启(后面在介绍 Redis 的哈希算法时具体介绍
30include /path/to/local.conf指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件

什么是守护进程

守护进程(Daemon Process),也就是通常说的 Daemon 进程(精灵进程),是 Linux 中的后台服务进程。它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。

守护进程是个特殊的孤儿进程,这种进程脱离终端,为什么要脱离终端呢?之所以脱离于终端是为了避免进程被任何终端所产生的信息所打断,其在执行过程中的信息也不在任何终端上显示。由于在 linux 中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端就称为这些进程的控制终端,当控制终端被关闭时,相应的进程都会自动关闭。

配置redis外网可访问

由于 redis 采用的安全策略,默认会只准许本地访问。需要通过简单配置,完成允许外网访问。

修改 redis 的配置文件,将所有 bind 信息全部屏蔽。

# bind 192.168.1.100 10.0.0.1 
# bind 192.168.1.8 
# bind 127.0.0.1

修改完成后,需要重新启动 redis 服务。

修改 Linux 的防火墙(iptables),开启你的 redis 服务端口,默认是 6379。

-A INPUT -m state –state NEW -m tcp -p tcp –dport 6379 -j ACCEPT 
…… 
-A INPUT -j REJECT –reject-with icmp-host-prohibited

请注意,一定要将 redis 的防火墙配置放在 REJECT 的前面。然后执行 service iptables restart。

至此,就能够链接到 redis 服务,并且能够正确显示了。

详情请见: 配置 redis 外网可访问

强烈建议不要在公网访问 redis,因为 redis 的处理速度非常快,所以如果你的密码比较简单,很容易就会通过暴力破解破解出密码:

Redis数据类型

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

string(字符串)

string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。

string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。

string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。

实例

127.0.0.1:6379> SET runoob "yuzhenyang"
OK
127.0.0.1:6379> GET runoob
"yuzhenyang"

在以上实例中我们使用了 Redis 的 SET 和 GET 命令。键为 runoob,对应的值为 菜鸟教程。

注意:一个键最大能存储 512MB。

Hash(哈希)

Redis hash 是一个键值(key=>value)对集合。

Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。

实例
DEL runoob 用于删除前面测试用过的 key,不然会报错:(error) WRONGTYPE Operation against a key holding the wrong kind of value
在这里插入图片描述

redis 127.0.0.1:6379> DEL runoob
redis 127.0.0.1:6379> HMSET runoob field1 "Hello" field2 "World"
"OK"
redis 127.0.0.1:6379> HGET runoob field1
"Hello"
redis 127.0.0.1:6379> HGET runoob field2
"World"

实例中我们使用了 Redis HMSET, HGET 命令,HMSET 设置了两个 field=>value 对, HGET 获取对应 field 对应的 value。

每个 hash 可以存储 232 -1 键值对(40多亿)。

List(列表)

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。

实例

redis 127.0.0.1:6379> DEL runoob
redis 127.0.0.1:6379> lpush runoob redis
(integer) 1
redis 127.0.0.1:6379> lpush runoob mongodb
(integer) 2
redis 127.0.0.1:6379> lpush runoob rabitmq
(integer) 3
redis 127.0.0.1:6379> lrange runoob 0 10
1) "rabitmq"
2) "mongodb"
3) "redis"
redis 127.0.0.1:6379>

列表最多可存储 232 - 1 元素 (4294967295, 每个列表可存储40多亿)。

Set(集合)

Redis 的 Set 是 string 类型的无序集合。

集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。

sadd 命令
添加一个 string 元素到 key 对应的 set 集合中,成功返回 1,如果元素已经在集合中返回 0。

sadd key member

实例

redis 127.0.0.1:6379> DEL runoob
redis 127.0.0.1:6379> sadd runoob redis
(integer) 1
redis 127.0.0.1:6379> sadd runoob mongodb
(integer) 1
redis 127.0.0.1:6379> sadd runoob rabitmq
(integer) 1
redis 127.0.0.1:6379> sadd runoob rabitmq
(integer) 0
redis 127.0.0.1:6379> smembers runoob

1) "redis"
2) "rabitmq"
3) "mongodb"

注意:以上实例中 rabitmq 添加了两次,但根据集合内元素的唯一性,第二次插入的元素将被忽略。

集合中最大的成员数为 232 - 1(4294967295, 每个集合可存储40多亿个成员)

zset(sorted set :有序集合)

Redis zset 和set 一样也是string类型元素的集合,且不允许重复的成员

不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。

zset的成员是唯一的,但分数(score)却可以重复。

zadd 命令
添加元素到集合,元素在集合中存在则更新对应score

zadd key score member 

实例

redis 127.0.0.1:6379> DEL runoob
redis 127.0.0.1:6379> zadd runoob 0 redis
(integer) 1
redis 127.0.0.1:6379> zadd runoob 0 mongodb
(integer) 1
redis 127.0.0.1:6379> zadd runoob 0 rabitmq
(integer) 1
redis 127.0.0.1:6379> zadd runoob 0 rabitmq
(integer) 0
redis 127.0.0.1:6379> > ZRANGEBYSCORE runoob 0 1000
1) "mongodb"
2) "rabitmq"
3) "redis"

各个数据类型应用场景

类型简介特性场景
String(字符串)二进制安全可以包含任何数据,比如jpg图片或者序列化的对象,一个键最大能存储512M
Hash(字典)键值对集合,即编程语言中的Map类型适合存储对象,并且可以像数据库中update一个属性一样只修改某一项属性值(Memcached中需要取出整个字符串反序列化成对象修改完再序列化存回去)存储、读取、修改用户属性
List(列表)链表(双向链表)增删快,提供了操作某一段元素的API1,最新消息排行等功能(比如朋友圈的时间线) 2,消息队列
Set(集合)哈希表实现,元素不重复1、添加、删除,查找的复杂度都是O(1) 2、为集合提供了求交集、并集、差集等操作1、共同好友 2、利用唯一性,统计访问网站的所有独立ip 3、好友推荐时,根据tag求交集,大于某个阈值就可以推荐
Sorted Set(有序集合)将Set中的元素增加一个权重参数score,元素按score有序排列数据插入集合时,已经进行天然排序1、排行榜 2、带权重的消息队列

Redis支持多个数据库

Redis支持多个数据库,并且每个数据库的数据是隔离的不能共享,并且基于单机才有,如果是集群就没有数据库的概念。

Redis是一个字典结构的存储服务器,而实际上一个Redis实例提供了多个用来存储数据的字典,客户端可以指定将数据存储在哪个字典中。这与我们熟知的在一个关系数据库实例中可以创建多个数据库类似,所以可以将其中的每个字典都理解成一个独立的数据库。

每个数据库对外都是一个从0开始的递增数字命名,Redis默认支持16个数据库(可以通过配置文件支持更多,无上限),可以通过配置databases来修改这一数字。客户端与Redis建立连接后会自动选择0号数据库,不过可以随时使用SELECT命令更换数据库,如要选择1号数据库:

redis> SELECT 1
OK
redis [1] > GET foo
(nil)

然而这些以数字命名的数据库又与我们理解的数据库有所区别。首先Redis不支持自定义数据库的名字,每个数据库都以编号命名,开发者必须自己记录哪些数据库存储了哪些数据。另外Redis也不支持为每个数据库设置不同的访问密码,所以一个客户端要么可以访问全部数据库,要么连一个数据库也没有权限访问。最重要的一点是多个数据库之间并不是完全隔离的,比如FLUSHALL命令可以清空一个Redis实例中所有数据库中的数据。综上所述,这些数据库更像是一种命名空间,而不适宜存储不同应用程序的数据。比如可以使用0号数据库存储某个应用生产环境中的数据,使用1号数据库存储测试环境中的数据,但不适宜使用0号数据库存储A应用的数据而使用1号数据库B应用的数据,不同的应用应该使用不同的Redis实例存储数据。由于Redis非常轻量级,一个空Redis实例占用的内在只有1M左右,所以不用担心多个Redis实例会额外占用很多内存。

Redis命令

Redis 命令用于在 redis 服务上执行操作。

要在 redis 服务上执行命令需要一个 redis 客户端。Redis 客户端在我们之前下载的的 redis 的安装包中。

语法
Redis 客户端的基本语法为:

$ redis-cli

实例
以下实例讲解了如何启动 redis 客户端:
启动 redis 服务器,打开终端并输入命令 redis-cli,该命令会连接本地的 redis 服务。

$ redis-cli
redis 127.0.0.1:6379>
redis 127.0.0.1:6379> PING

PONG

在以上实例中我们连接到本地的 redis 服务并执行 PING 命令,该命令用于检测 redis 服务是否启动。

在远程服务上执行命令
如果需要在远程 redis 服务上执行命令,同样我们使用的也是 redis-cli 命令。

语法

$ redis-cli -h host -p port -a password

实例
以下实例演示了如何连接到主机为 127.0.0.1,端口为 6379 ,密码为 mypass 的 redis 服务上。

$redis-cli -h 127.0.0.1 -p 6379 -a "mypass"
redis 127.0.0.1:6379>
redis 127.0.0.1:6379> PING

PONG

有时候会有中文乱码。

要在 redis-cli 后面加上 --raw

redis-cli --raw

就可以避免中文乱码了。

Redis 键(key)

Redis 键命令用于管理 redis 的键。
语法
Redis 键命令的基本语法如下:

redis 127.0.0.1:6379> COMMAND KEY_NAME

实例

redis 127.0.0.1:6379> SET runoobkey redis
OK
redis 127.0.0.1:6379> DEL runoobkey
(integer) 1

在以上实例中 DEL 是一个命令, runoobkey 是一个键。 如果键被删除成功,命令执行后输出 (integer) 1,否则将输出 (integer) 0

Redis keys命令
下表给出了与Redis键相关的基本命令

序号命令描述
1DEL key该命令用于在 key 存在时删除 key。
2DUMP key序列化给定 key ,并返回被序列化的值。
3EXISTS key检查给定 key 是否存在。
4EXPIRE key seconds为给定 key 设置过期时间,以秒计。
5EXPIREAT key timestampEXPIREAT 的作用和 EXPIRE 类似,都用于为 key 设置过期时间。 不同在于 EXPIREAT 命令接受的时间参数是 UNIX 时间戳(unix timestamp)。
6PEXPIRE key milliseconds设置 key 的过期时间以毫秒计。
7PEXPIREAT key milliseconds-timestamp设置 key 过期时间的时间戳(unix timestamp) 以毫秒计
8KEYS pattern查找所有符合给定模式( pattern)的 key
9MOVE key db将当前数据库的 key 移动到给定的数据库 db 当中。
10PERSIST key移除 key 的过期时间,key 将持久保持。
11PTTL key以毫秒为单位返回 key 的剩余的过期时间。
12TTL key以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。
13RANDOMKEY从当前数据库中随机返回一个 key 。
14RENAME key newkey修改 key 的名称
15RENAMENX key newkey仅当 newkey 不存在时,将 key 改名为 newkey 。
16SCAN cursor [MATCH pattern] [COUNT count]迭代数据库中的数据库键。
17TYPE key返回 key 所储存的值的类型。

Redis字符串(string)

Redis 字符串数据类型的相关命令用于管理 redis 字符串值,基本语法如下:

语法

redis 127.0.0.1:6379> COMMAND KEY_NAME

实例

redis 127.0.0.1:6379> SET runoobkey redis
OK
redis 127.0.0.1:6379> GET runoobkey
"redis"

在以上实例中我们使用了 SET 和 GET 命令,键为 runoobkey。

Redis 字符串命令
下表列出了常用的 redis 字符串命令:

序号命令描述
1SET key value设置指定 key 的值
2GET key获取指定 key 的值。
3GETRANGE key start end返回 key 中字符串值的子字符
4GETSET key value将给定 key 的值设为 value ,并返回 key 的旧值(old value)。
5GETBIT key offset对 key 所储存的字符串值,获取指定偏移量上的位(bit)。
6MGET key1 [key2…]获取所有(一个或多个)给定 key 的值。
7SETBIT key offset value对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。
8SETEX key seconds value将值 value 关联到 key ,并将 key 的过期时间设为 seconds (以秒为单位)。
9SETNX key value只有在 key 不存在时设置 key 的值。
10SETRANGE key offset value用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始。
11STRLEN key返回 key 所储存的字符串值的长度。
12MSET key value [key value …]同时设置一个或多个 key-value 对。
13MSETNX key value [key value …]同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。
14PSETEX key milliseconds value这个命令和 SETEX 命令相似,但它以毫秒为单位设置 key 的生存时间,而不是像 SETEX 命令那样,以秒为单位。
15INCR key将 key 中储存的数字值增一。
16INCRBY key increment将 key 所储存的值加上给定的增量值(increment) 。
17INCRBYFLOAT key increment将 key 所储存的值加上给定的浮点增量值(increment) 。
18DECR key将 key 中储存的数字值减一。
19DECRBY key decrementkey 所储存的值减去给定的减量值(decrement) 。
20APPEND key value如果 key 已经存在并且是一个字符串, APPEND 命令将指定的 value 追加到该 key 原来值(value)的末尾。

更多命令请参考:https://redis.io/commands

Redis 哈希(Hash)

Redis hash 是一个 string 类型的 field(字段) 和 value(值) 的映射表,hash 特别适合用于存储对象。

Redis 中每个 hash 可以存储 232 - 1 键值对(40多亿)。

实例

127.0.0.1:6379>  HMSET runoobkey name "redis tutorial" description "redis basic commands for caching" likes 20 visitors 23000
OK
127.0.0.1:6379>  HGETALL runoobkey
1) "name"
2) "redis tutorial"
3) "description"
4) "redis basic commands for caching"
5) "likes"
6) "20"
7) "visitors"
8) "23000

在以上实例中,我们设置了 redis 的一些描述信息(name, description, likes, visitors) 到哈希表的 runoobkey 中。

Redis hash 命令
下表列出了 redis hash 基本的相关命令:

序号命令描述
1HDEL key field1 [field2]删除一个或多个哈希表字段
2HEXISTS key field查看哈希表 key 中,指定的字段是否存在。
3HGET key field获取存储在哈希表中指定字段的值。
4HGETALL key获取在哈希表中指定 key 的所有字段和值
5HINCRBY key field increment为哈希表 key 中的指定字段的整数值加上增量 increment 。
6HINCRBYFLOAT key field increment为哈希表 key 中的指定字段的浮点数值加上增量 increment 。
7HKEYS key获取所有哈希表中的字段
8HLEN key获取哈希表中字段的数量
9HMGET key field1 [field2]获取所有给定字段的值
10HMSET key field1 value1 [field2 value2 ]同时将多个 field-value (域-值)对设置到哈希表 key 中。
11HSET key field value将哈希表 key 中的字段 field 的值设为 value 。
12HSETNX key field value只有在字段 field 不存在时,设置哈希表字段的值。
13HVALS key获取哈希表中所有值。
14HSCAN key cursor [MATCH pattern] [COUNT count]迭代哈希表中的键值对。

更多命令请参考:https://redis.io/commands

Redis 列表(List)

Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)

一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。

实例

redis 127.0.0.1:6379> LPUSH runoobkey redis
(integer) 1
redis 127.0.0.1:6379> LPUSH runoobkey mongodb
(integer) 2
redis 127.0.0.1:6379> LPUSH runoobkey mysql
(integer) 3
redis 127.0.0.1:6379> LRANGE runoobkey 0 10

1) "mysql"
2) "mongodb"
3) "redis"

在以上实例中我们使用了 LPUSH 将三个值插入了名为 runoobkey 的列表当中。

Redis 列表命令
下表列出了列表相关的基本命令:

序号命令描述
1BLPOP key1 [key2 ] timeout移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
2BRPOP key1 [key2 ] timeout移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
3BRPOPLPUSH source destination timeout从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
4LINDEX key index通过索引获取列表中的元素
5LINSERT key BEFOREAFTER pivot value
6LLEN key获取列表长度
7LPOP key移出并获取列表的第一个元素
8LPUSH key value1 [value2]将一个或多个值插入到列表头部
9LPUSHX key value将一个值插入到已存在的列表头部
10LRANGE key start stop获取列表指定范围内的元素
11LREM key count value移除列表元素
12LSET key index value通过索引设置列表元素的值
13LTRIM key start stop对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
14RPOP key移除列表的最后一个元素,返回值为移除的元素。
15RPOPLPUSH source destination移除列表的最后一个元素,并将该元素添加到另一个列表并返回
16RPUSH key value1 [value2]在列表中添加一个或多个值
17RPUSHX key value为已存在的列表添加值

Redis 集合(Set)

Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。

Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。

集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。

实例

redis 127.0.0.1:6379> SADD runoobkey redis
(integer) 1
redis 127.0.0.1:6379> SADD runoobkey mongodb
(integer) 1
redis 127.0.0.1:6379> SADD runoobkey mysql
(integer) 1
redis 127.0.0.1:6379> SADD runoobkey mysql
(integer) 0
redis 127.0.0.1:6379> SMEMBERS runoobkey

1) "mysql"
2) "mongodb"
3) "redis"

在以上实例中我们通过 SADD 命令向名为 runoobkey 的集合插入的三个元素。

Redis 集合命令
下表列出了 Redis 集合基本命令:

序号命令描述
1SADD key member1 [member2]向集合添加一个或多个成员
2SCARD key获取集合的成员数
3SDIFF key1 [key2]返回第一个集合与其他集合之间的差异。
4SDIFFSTORE destination key1 [key2]返回给定所有集合的差集并存储在 destination 中
5SINTER key1 [key2]返回给定所有集合的交集
6SINTERSTORE destination key1 [key2]返回给定所有集合的交集并存储在 destination 中
7SISMEMBER key member判断 member 元素是否是集合 key 的成员
8SMEMBERS key返回集合中的所有成员
9SMOVE source destination member将 member 元素从 source 集合移动到 destination 集合
10SPOP key移除并返回集合中的一个随机元素
11SRANDMEMBER key [count]返回集合中一个或多个随机数
12SREM key member1 [member2]移除集合中一个或多个成员
13SUNION key1 [key2]返回所有给定集合的并集
14SUNIONSTORE destination key1 [key2]所有给定集合的并集存储在 destination 集合中
15SSCAN key cursor [MATCH pattern] [COUNT count]迭代集合中的元素

Redis 有序集合(sorted set)

后续补充

Redis HyperLogLog

后续补充

Redis 发布订阅

Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。

Redis 客户端可以订阅任意数量的频道。

下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:
在这里插入图片描述
当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:
在这里插入图片描述
实例
以下实例演示了发布订阅是如何工作的。在我们实例中我们创建了订阅频道名为 redisChat:

redis 127.0.0.1:6379> SUBSCRIBE redisChat

Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
3) (integer) 1

现在,我们先重新开启个 redis 客户端,然后在同一个频道 redisChat 发布两次消息,订阅者就能接收到消息。

redis 127.0.0.1:6379> PUBLISH redisChat "Redis is a great caching technique"

(integer) 1

redis 127.0.0.1:6379> PUBLISH redisChat "Learn redis by runoob.com"

(integer) 1

# 订阅者的客户端会显示如下消息
1) "message"
2) "redisChat"
3) "Redis is a great caching technique"
1) "message"
2) "redisChat"
3) "Learn redis by runoob.com"

Redis 发布订阅命令
下表列出了 redis 发布订阅常用命令:

序号命令描述
1PSUBSCRIBE pattern [pattern …]订阅一个或多个符合给定模式的频道。
2PUBSUB subcommand [argument [argument …]]查看订阅与发布系统状态。
3PUBLISH channel message将信息发送到指定的频道。
4PUNSUBSCRIBE [pattern [pattern …]]退订所有给定模式的频道。
5SUBSCRIBE channel [channel …]订阅给定的一个或多个频道的信息。
6UNSUBSCRIBE [channel [channel …]]指退订给定的频道。

Redis 事务

Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:

· 批量操作在发送 EXEC 命令前被放入队列缓存。
· 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。
一个事务从开始到执行会经历以下三个阶段:

· 开始事务。
· 命令入队。
· 执行事务。

实例
以下是一个事务的例子, 它先以 MULTI 开始一个事务, 然后将多个命令入队到事务中, 最后由 EXEC 命令触发事务, 一并执行事务中的所有命令:

redis 127.0.0.1:6379> MULTI
OK

redis 127.0.0.1:6379> SET book-name "Mastering C++ in 21 days"
QUEUED

redis 127.0.0.1:6379> GET book-name
QUEUED

redis 127.0.0.1:6379> SADD tag "C++" "Programming" "Mastering Series"
QUEUED

redis 127.0.0.1:6379> SMEMBERS tag
QUEUED

redis 127.0.0.1:6379> EXEC
1) OK
2) "Mastering C++ in 21 days"
3) (integer) 3
4) 1) "Mastering Series"
   2) "C++"
   3) "Programming"

单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。

事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。

这是官网上的说明 From redis docs on transactions:
It’s important to note that even when a command fails, all the other commands in the queue are processed – Redis will not stop the processing of commands.

比如:

redis 127.0.0.1:7000> multi
OK
redis 127.0.0.1:7000> set a aaa
QUEUED
redis 127.0.0.1:7000> set b bbb
QUEUED
redis 127.0.0.1:7000> set c ccc
QUEUED
redis 127.0.0.1:7000> exec
1) OK
2) OK
3) OK

如果在 set b bbb 处失败,set a 已成功不会回滚,set c 还会继续执行。

Redis 事务命令
下表列出了 redis 事务的相关命令:

序号命令描述
1DISCARD取消事务,放弃执行事务块内的所有命令。
2EXEC执行所有事务块内的命令。
3MULTI标记一个事务块的开始。
4UNWATCH取消 WATCH 命令对所有 key 的监视。
5WATCH key [key …]监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。

Redis 脚本

Redis 脚本使用 Lua 解释器来执行脚本。 Redis 2.6 版本通过内嵌支持 Lua 环境。执行脚本的常用命令为 EVAL。

语法
Eval 命令的基本语法如下:

redis 127.0.0.1:6379> EVAL script numkeys key [key ...] arg [arg ...]

实例
以下实例演示了 redis 脚本工作过程:

redis 127.0.0.1:6379> EVAL "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second

1) "key1"
2) "key2"
3) "first"
4) "second"

Redis 脚本命令
下表列出了 redis 脚本常用命令:

序号命令描述
1EVAL script numkeys key [key …] arg [arg …]执行 Lua 脚本。
2EVALSHA sha1 numkeys key [key …] arg [arg …]执行 Lua 脚本。
3SCRIPT EXISTS script [script …]查看指定的脚本是否已经被保存在缓存当中。
4SCRIPT FLUSH从脚本缓存中移除所有脚本。
5SCRIPT KILL杀死当前正在运行的 Lua 脚本。
6SCRIPT LOAD script将脚本 script 添加到脚本缓存中,但并不立即执行这个脚本。

Redis 连接

Redis 连接命令主要是用于连接 redis 服务。

实例
以下实例演示了客户端如何通过密码验证连接到 redis 服务,并检测服务是否在运行:

redis 127.0.0.1:6379> AUTH "password"
OK
redis 127.0.0.1:6379> PING
PONG

Redis 连接命令
下表列出了 redis 连接的基本命令:

序号命令描述
1AUTH password验证密码是否正确
2ECHO message打印字符串
3PING查看服务是否运行
4QUIT关闭当前连接
5SELECT index切换到指定的数据库

Redis 服务器

Redis 服务器命令主要是用于管理 redis 服务。
实例
以下实例演示了如何获取 redis 服务器的统计信息:

redis 127.0.0.1:6379> INFO

# Server
redis_version:2.8.13
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:c2238b38b1edb0e2
redis_mode:standalone
os:Linux 3.5.0-48-generic x86_64
arch_bits:64
multiplexing_api:epoll
gcc_version:4.7.2
process_id:3856
run_id:0e61abd297771de3fe812a3c21027732ac9f41fe
tcp_port:6379
uptime_in_seconds:11554
uptime_in_days:0
hz:10
lru_clock:16651447
config_file:

# Clients
connected_clients:1
client-longest_output_list:0
client-biggest_input_buf:0
blocked_clients:0

# Memory
used_memory:589016
used_memory_human:575.21K
used_memory_rss:2461696
used_memory_peak:667312
used_memory_peak_human:651.67K
used_memory_lua:33792
mem_fragmentation_ratio:4.18
mem_allocator:jemalloc-3.6.0

# Persistence
loading:0
rdb_changes_since_last_save:3
rdb_bgsave_in_progress:0
rdb_last_save_time:1409158561
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok

# Stats
total_connections_received:24
total_commands_processed:294
instantaneous_ops_per_sec:0
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
evicted_keys:0
keyspace_hits:41
keyspace_misses:82
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:264

# Replication
role:master
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

# CPU
used_cpu_sys:10.49
used_cpu_user:4.96
used_cpu_sys_children:0.00
used_cpu_user_children:0.01

# Keyspace
db0:keys=94,expires=1,avg_ttl=41638810
db1:keys=1,expires=0,avg_ttl=0
db3:keys=1,expires=0,avg_ttl=0

Redis 服务器命令
下表列出了 redis 服务器的相关命令:

序号命令描述
1BGREWRITEAOF异步执行一个 AOF(AppendOnly File) 文件重写操作
2BGSAVE在后台异步保存当前数据库的数据到磁盘
3CLIENT KILL [ip:port] [ID client-id]关闭客户端连接
4CLIENT LIST获取连接到服务器的客户端连接列表
5CLIENT GETNAME获取连接的名称
6CLIENT PAUSE timeout在指定时间内终止运行来自客户端的命令
7CLIENT SETNAME connection-name设置当前连接的名称
8CLUSTER SLOTS获取集群节点的映射数组
9COMMAND获取 Redis 命令详情数组
10COMMAND COUNT获取 Redis 命令总数
11COMMAND GETKEYS获取给定命令的所有键
12TIME返回当前服务器时间
13COMMAND INFO command-name [command-name …]获取指定 Redis 命令描述的数组
14CONFIG GET parameter获取指定配置参数的值
15CONFIG REWRITE对启动 Redis 服务器时所指定的 redis.conf 配置文件进行改写
16CONFIG SET parameter value修改 redis 配置参数,无需重启
17CONFIG RESETSTAT重置 INFO 命令中的某些统计数据
18DBSIZE返回当前数据库的 key 的数量
19DEBUG OBJECT key获取 key 的调试信息
20DEBUG SEGFAULT让 Redis 服务崩溃
21FLUSHALL删除所有数据库的所有key
22FLUSHDB删除当前数据库的所有key
23INFO [section]获取 Redis 服务器的各种信息和统计数值
24LASTSAVE返回最近一次 Redis 成功将数据保存到磁盘上的时间,以 UNIX 时间戳格式表示
25MONITOR实时打印出 Redis 服务器接收到的命令,调试用
26ROLE返回主从实例所属的角色
27SAVE同步保存数据到硬盘
28SHUTDOWN [NOSAVE] [SAVE]异步保存数据到硬盘,并关闭服务器
29SLAVEOF host port将当前服务器转变为指定服务器的从属服务器(slave server)
30SLOWLOG subcommand [argument]管理 redis 的慢日志
31SYNC用于复制功能(replication)的内部命令

Redis GEO

Redis GEO 主要用于存储地理位置信息,并对存储的信息进行操作,该功能在 Redis 3.2 版本新增。

Redis GEO 操作方法有:

geoadd:添加地理位置的坐标。
geopos:获取地理位置的坐标。
geodist:计算两个位置之间的距离。
georadius:根据用户给定的经纬度坐标来获取指定范围内的地理位置集合。
georadiusbymember:根据储存在位置集合里面的某个地点获取指定范围内的地理位置集合。
geohash:返回一个或多个位置对象的 geohash 值。

geoadd
geoadd 用于存储指定的地理空间位置,可以将一个或多个经度(longitude)、纬度(latitude)、位置名称(member)添加到指定的 key 中。

geoadd 语法格式如下:

GEOADD key longitude latitude member [longitude latitude member ...]

以下实例中 key 为 Sicily、Catania 为位置名称 :

redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
redis> GEODIST Sicily Palermo Catania
"166274.1516"
redis> GEORADIUS Sicily 15 37 100 km
1) "Catania"
redis> GEORADIUS Sicily 15 37 200 km
1) "Palermo"
2) "Catania"
redis>

geopos
geopos 用于从给定的 key 里返回所有指定名称(member)的位置(经度和纬度),不存在的返回 nil。

geopos 语法格式如下:

redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
redis> GEOPOS Sicily Palermo Catania NonExisting
1) 1) "13.36138933897018433"
   2) "38.11555639549629859"
2) 1) "15.08726745843887329"
   2) "37.50266842333162032"
3) (nil)
redis>

geodist
geodist 用于返回两个给定位置之间的距离。

geodist 语法格式如下:

GEODIST key member1 member2 [m|km|ft|mi]

member1 member2 为两个地理位置。

最后一个距离单位参数说明:

m :米,默认单位。
km :千米。
mi :英里。
ft :英尺。

计算 Palermo 与 Catania 之间的距离:

redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
redis> GEODIST Sicily Palermo Catania
"166274.1516"
redis> GEODIST Sicily Palermo Catania km
"166.2742"
redis> GEODIST Sicily Palermo Catania mi
"103.3182"
redis> GEODIST Sicily Foo Bar
(nil)
redis>

georadius、georadiusbymember
georadius 以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。

georadiusbymember 和 GEORADIUS 命令一样, 都可以找出位于指定范围内的元素, 但是 georadiusbymember 的中心点是由给定的位置元素决定的, 而不是使用经度和纬度来决定中心点。

georadius 与 georadiusbymember 语法格式如下:

GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]
GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]

参数说明:

m :米,默认单位。
km :千米。
mi :英里。
ft :英尺。
WITHDIST: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。
WITHCOORD: 将位置元素的经度和维度也一并返回。
WITHHASH:52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。 这个选项主要用于底层应用或者调试, 实际中的作用并不大。
COUNT 限定返回的记录数。
ASC: 查找结果根据距离从近到远排序。
DESC: 查找结果根据从远到近排序。

georadius 实例:

redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
redis> GEORADIUS Sicily 15 37 200 km WITHDIST
1) 1) "Palermo"
   2) "190.4424"
2) 1) "Catania"
   2) "56.4413"
redis> GEORADIUS Sicily 15 37 200 km WITHCOORD
1) 1) "Palermo"
   2) 1) "13.36138933897018433"
      2) "38.11555639549629859"
2) 1) "Catania"
   2) 1) "15.08726745843887329"
      2) "37.50266842333162032"
redis> GEORADIUS Sicily 15 37 200 km WITHDIST WITHCOORD
1) 1) "Palermo"
   2) "190.4424"
   3) 1) "13.36138933897018433"
      2) "38.11555639549629859"
2) 1) "Catania"
   2) "56.4413"
   3) 1) "15.08726745843887329"
      2) "37.50266842333162032"
redis>

georadiusbymember 实例:

redis> GEOADD Sicily 13.583333 37.316667 "Agrigento"
(integer) 1
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
redis> GEORADIUSBYMEMBER Sicily Agrigento 100 km
1) "Agrigento"
2) "Palermo"
redis>

geohash

Redis GEO 使用 geohash 来保存地理位置的坐标。

geohash 用于获取一个或多个位置元素的 geohash 值。

geohash 语法格式如下:

GEOHASH key member [member ...]

参考:https://www.runoob.com/redis/redis-geo.html

hiredis函数接口

安装

下载地址:https://github.com/redis/hiredis/releases
安装命令:make; make install

hiredis使用

hiredis是redis数据库的C接口,目前只能在linux下使用,几个基本的函数就可以操作redis数据库了

使用同步API

建立连接
// redisContext *redisConnect(const char *ip, int port);
redisContext *c = redisConnect("127.0.0.1", 6379);
if (c != NULL && c->err) 
{
    printf("Error: %s\n", c->errstr);
    // handle error
}

建立连接后使用 redisContext 来保存连接状态。 redisContext 在每次操作后会修改其中的 err 和 errstr 字段来表示发生的错误码(大于0)和对应的描述。没有发生错误的话, err 会被设置为 REDIS_OK(等于0)。

redisContext不是线程安全的。

断开连接
void redisFree(redisContext *c);

该接口用来断开连接并释放 redisContext。

执行命令
void *redisCommand(redisContext *c, const char *format, ...);
void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);

这两个接口使用类似 printf 的风格格式化命令,如果需要传入二进制安全的字符串,需要使用 %b 并传入 size_t 类型的字符串长度。

redisCommandArgv 中可以默认使用 strlen 来求得字符串长度而不需要传入第四个参数,但如果是二进制安全的字符串,需要提供所有字符串参数的长度。

实例:

redisCommand(context, "SET foo bar");
redisCommand(context, "SET foo %s", value);
redisCommand(context, "SET foo %b", value, (size_t) valuelen);
管道

这两个API除了不返回 redisReply之外,与 redisCommand 一致。

void redisAppendCommand(redisContext *c, const char *format, ...);
void redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);

这个接口用来获取管道里的 redisReply,返回值是 REDIS_OK 或者 REDIS_ERR。发送错误时 redisContext的 err会被设置。

redisGetReply(context,&reply); // reply for SET

管道使用示例 —— 阻塞订阅者的一个实现:

reply = redisCommand(context,"SUBSCRIBE foo");
freeReplyObject(reply);
while(redisGetReply(context,&reply) == REDIS_OK) {
    // consume message
    freeReplyObject(reply);
}
错误

如果一个函数调用不成功,不同函数会返回 NULL 或 REDIS_ERR。 redisContext 中的 err 字段会被设置为以下的非零值:

REDIS_ERR_IO: 创建连接、通过socket读写数据时产生了错误。如果包括了 errno.h 头文件,可以使用 errno 检查出了什么错。

REDIS_ERR_EOF: 服务器关闭了连接导致的空读。

REDIS_ERR_PROTOCOL: 解析协议出错。

REDIS_ERR_OTHER: 任意其他错误。目前仅用于要连接的指定主机无法被解析的情况下。

每一种情况下, errstr 字段都会被设置为相应的文字说明。

redisReply

redisReply 是 redisCommand 返回值的实际类型。

redisReply 定义如下:

/* This is the reply object returned by redisCommand() */
typedef struct redisReply {
    int type; /* 返回值类型 */
    long long integer; /* 当返回类型为 REDIS_REPLY_INTEGER 时 */
    size_t len; /* 返回的字符串长度 */
    char *str; /* 当返回值类型为 REDIS_REPLY_ERROR 和 REDIS_REPLY_STRING */
    size_t elements; /* 返回的数组长度 */
    struct redisReply **element; /* 当返回值类型为 REDIS_REPLY_ARRAY */
} redisReply;

type 有以下几种类型:
  REDIS_REPLY_STRING  : 1 
  REDIS_REPLY_ARRAY : 2
  REDIS_REPLY_INTEGER :3 
  REDIS_REPLY_NIL  : 4
  REDIS_REPLY_STATUS : 5
  REDIS_REPLY_ERROR : 6

redisCommand 发生错误时返回 NULL,并设置 redisContext 错误。

一旦发生错误,这个 redisContext 就不能继续使用,必须建立新的连接。

可以通过 redisReply 的 type 字段来判断返回类型:

REDIS_REPLY_STATUS: 命令返回的是状态。可以用 reply->str 和 reply->len 获得描述字符串及其长度。

REDIS_REPLY_ERROR: 命令执行错误,错误字符串获取方法与 REDIS_REPLY_STATUS 一样。

REDIS_REPLY_INTEGER: 命令返回的是整数, 返回值是 long long 类型,通过 reply->integer 获取。

REDIS_REPLY_NIL: 命令返回的是 nil 对象,没有数据可取。

REDIS_REPLY_STRING: 命令返回字符串,可以通过 reply->str 和 reply->len 获得字符串及其长度。

REDIS_REPLY_ARRAY: 命令返回数组,元素个数存储在 reply->elements 中。 每个元素都是一个
redisReply , 并可以通过 reply->element[…index…] 的方法获取。

reply应该用 freeReplyObject 释放,数组和内嵌数组不需要被单独释放。

void freeReplyObject(void *reply);

hiredis(0.10.0)在异步api使用时自动释放replies。所以在调用异步api时不要调用freeReplyObject。hiredis会在回调返回之后释放reply。不过这个问题可能会在未来修改掉(issue
#39)。

异步API

异步API包含的头文件是 async.h

连接

redisAsyncConnect 用来进行异步连接,不是线程安全的。

redisAsyncContext *redisAsyncConnect(const char *ip, int port);
redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);
if (c->err) 
{
    printf("Error: %s\n", c->errstr);
    // handle error
}
连接相关的回调函数:
typedef void (redisConnectCallback)(const struct redisAsyncContext*, int status);    // 建立连接回调
typedef void (redisDisconnectCallback)(const struct redisAsyncContext*, int status);    // 断开连接回调

status 为 REDIS_OK 表示是用户自己断开 ,其他值代表连接被其他错误断开。
redisContext 会在断开连接回调中被释放,此时可以进行需要的重连。
每个 redisContext 只能设置一次断开连接回调,后面的调用会返回 REDIS_ERR。

设置断开连接的回调如下:
int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn);
断开连接的接口:
void redisAsyncDisconnect(redisAsyncContext *ac);
执行异步命令

用法与同步API类型,除了需要传入回调函数以及自定义数据的 void* 类型指针。

int redisAsyncCommand(
  redisAsyncContext *ac, redisCallbackFn *fn, void *privdata,
  const char *format, ...);
int redisAsyncCommandArgv(
  redisAsyncContext *ac, redisCallbackFn *fn, void *privdata,
  int argc, const char **argv, const size_t *argvlen);
typedef void (redisCallbackFn)(redisAsyncContext*, void* reply, void* privdata);

命令成功被到输入缓冲区后会返回 REDIS_OK,否则返回 REDIS_ERR。

当命令执行结果返回时会调用注册的回调函数并传入对应的 redisReply 结构和自定义数据。

命令返回后读空回调函数(NULL callback)会使reply立即释放。如果是非空回调,则会在回调函数执行完后释放reply。

参考链接:https://www.jianshu.com/p/466c76a60324

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值