【基础篇】一文带你掌握 Redis
一、摘要
谈起 Redis,相信大家都不会陌生,做过云平台开发的程序员多多少少会接触到它,Redis 英文全称:Remote Dictionary Server,也被称之为远程字典服务。
从官方的定义看,Redis 是一款开源的,遵守 BSD 协议,使用 C 语言开发的 key-value 存储系统。简单的说,它是一款跨平台的非关系型数据库,支持优先内存存储,并提供多种语言的 API 客户端。
Redis 由一个叫 Salvatore Sanfilippo 的人开发而闻名世界,此人来自意大利的西西里岛,网名叫 antirez,如果你有兴趣,可以去他的博客逛逛,地址是 antirez.com
。
不过从 2010 年起,Redis 的开发工作由 VMware 主持,到了 2013 年后,Redis 的开发由 Pivotal 赞助。
Redis 是当下互联网技术中使用最为广泛的缓存中间件之一,随着它在新浪微博中的使用而逐渐风靡国内。
虽然开源软件市场上也有很多优秀的缓存服务中间件,比如 memcache,但是和 redis 对比起来,redis 还是显得格外的突出,优势如下:
- 性能极高:Redis 能读的速度是 110000 次/s,写的速度是 81000次/s
- 数据类型丰富:支持 String,Hash,List,Set,Sorted Set 等数据类型的操作
- 支持原子性操作:Redis 的每条命令操作都是原子性的,Redis 的操作之所以是原子性的,是因为每条命令的执行都是单线程的,不存在线程竞争问题
- 存储方式多样化:memecache 把数据全部存在内存之中,断电后会挂掉;redis 支持数据的持久化,同时也支持数据的备份,即 master-slave 模式的数据备份
- 功能丰富:Redis 还支持 publish/subscribe,通知,key 过期等等特性
在分布式的架构环境下,Redis 基本上是缺一不可的缓存中间件,它能很好的解决服务与服务之间数据共享的问题,并且性能不受影响。
说了这么多,如何使用呢?我们一起来看看!
二、服务安装
2.1、Windows 环境
因为 redis 目前官方只支持 LINUX 系统,因此没有 Windows 版本的软件包,但是好在微软团队维护了开源的 windows 版本,虽然更新不算及时,但是对于普通测试使用足够了。
2.1.1、服务器安装
如果当前操作系统是 Windows 系统,访问如下的地址,获取对应的下载链接。
https://github.com/tporadowski/redis/releases
根据系统平台的实际情况选择,这里我们下载Redis-x64-xxx.zip
压缩包到 C 盘,解压后,将文件夹重新命名为redis
。
打开文件夹,内容如下:
然后,打开一个 cmd 窗口,使用 cd 命令切换目录到C:\redis
,并且输入如下命令:
redis-server.exe redis.windows.conf
出现以上界面,表示redis
服务器已经成功启动了。
2.1.2、客户端测试
如果想用安装包里面的客户端脚本测试一下服务,可以这样操作。
另启一个 cmd 窗口,原来的窗口不要关闭,不然就无法访问服务端了。
使用 cd 命令切换目录到C:\redis
,并且输入如下命令:
redis-cli.exe -h 127.0.0.1 -p 6379
连接到服务器之后,输入写命令和取命令,相关命令如下:
#写数据测试
set myKey abc
#取数据测试
get myKey
2.2、Linux 环境
如果当前操作系统是 Linux 系统,访问如下的官方地址,获取最新的下载链接。
http://redis.io/download
2.2.1、服务器安装
本教程使用的最新文档版本为 6.2.6,下载并安装:
# wget https://download.redis.io/releases/redis-6.2.6.tar.gz
# tar xzf redis-6.2.6.tar.gz
# cd redis-6.2.6
# make
执行完make
命令后,redis-6.2.6
目录下会出现编译后的 redis 服务程序 redis-server,还有用于测试的客户端程序 redis-cli,两个程序位于安装目录 src 目录下。
执行下面的脚本,启动 redis 服务器。
# cd src
# ./redis-server
需要注意的地方是,这种方式启动 redis 使用的是默认配置,也可以通过参数告诉 redis 使用指定配置文件来启动服务,其中redis.conf
是一个默认的配置文件,我们可以根据需要使用自己的自定义配置文件。
# cd src
# ./redis-server ../redis.conf
当出现Ready to accept connections
时,表示服务已经启动成功。
2.2.2、客户端测试
同样的,如果想用安装包里面的客户端脚本测试一下服务,新创建一个命令窗口,这样操作。
# cd src
# ./redis-cli
redis> set foo bar
OK
redis> get foo
"bar"
2.2.3、参数配置
可能有的同学会发出一个疑问,如何将 Redis 改成后台服务?
也就是将窗体关闭也能正常提供服务,答案就藏在redis.conf
这个配置文件里。
打开redis.conf
文件,常用配置如下:
#绑定ip
bind 0.0.0.0
#启动端口
port 6379
# 是否运行远程访问
protected-mode yes
# 是否允许后台运行,默认no,将其改成yes
daemonize yes
# redis访问密码,根据需要设置,如果要打开,将#去掉
# requirepass foobared
# 数据库的数量
databases 16
修改配置,然后重启服务即可生效,操作如下:
# 寻找redis相关进程
ps -ef|grep redis
# 杀掉进程
kill -9 <pid>
# 重新启动redis
./redis-server ../redis.conf
2.2.3、配置详解
redis.conf
详细配置项说明如下:
配置参数 | 说明 |
---|---|
bind 127.0.0.1 | 如果是内网可以直接绑定 127.0.0.1, 或者忽略, 0.0.0.0是外网 |
port 6379 | 指定 Redis 监听端口,默认端口为 6379 |
protected-mode yes | 是否运行远程访问,默认是yes |
daemonize no | Redis 默认不是以守护进程的方式运行,可以通过该配置项修改,使用 yes 启用守护进程 |
databases 16 | 设置数据库的数量,默认数据库为0,可以使用SELECT 命令在连接上指定数据库id |
requirepass foobared | 设置 Redis 连接密码,如果配置了连接密码,客户端在连接 Redis 时需要通过 AUTH password 命令提供密码,默认关闭 |
timeout 300 | 当客户端闲置多长秒后关闭连接,如果指定为 0 ,表示关闭该功能 |
maxclients 128 | 设置同一时间最大客户端连接数,默认无限制,Redis 可以同时打开的客户端连接数为 Redis 进程可以打开的最大文件描述符数,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis 会关闭新的连接并向客户端返回 max number of clients reached 错误信息 |
maxmemory <bytes> |
指定 Redis 最大内存限制,Redis 在启动时会把数据加载到内存中,达到最大内存后,Redis 会先尝试清除已到期或即将到期的 Key,当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis 新的 vm 机制,会把 Key 存放内存,Value 会存放在 swap 区 |
pidfile /var/run/redis.pid | 当 Redis 以守护进程方式运行时,Redis 默认会把 pid 写入 /var/run/redis.pid 文件,可以通过 pidfile 指定 |
loglevel notice | 指定日志记录级别,Redis 总共支持四个级别:debug、verbose、notice、warning,默认为 notice |
logfile stdout | 日志记录方式,默认为标准输出,如果配置 Redis 为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给 /dev/null |
save <seconds> <changes> |
指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合,比如save 900 1 ,表示 900 秒内有 1 个更改 |
rdbcompression yes | 指定存储至本地数据库时是否压缩数据,默认为 yes,Redis 采用 LZF 压缩,如果为了节省 CPU 时间,可以关闭该选项,但会导致数据库文件变的巨大 |
dbfilename dump.rdb | 指定本地数据库文件名,默认值为 dump.rdb |
dir ./ | 指定本地数据库存放目录 |
slaveof <masterip> <masterport> |
设置当本机为 slave 服务时,设置 master 服务的 IP 地址及端口,在 Redis 启动时,它会自动从 master 进行数据同步 |
masterauth <master-password> |
当 master 服务设置了密码保护时,slave 服务连接 master 的密码 |
appendonly no | 指定是否在每次更新操作后进行日志记录,Redis 在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为 redis 本身同步数据文件是按上面 save 条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为 no |
appendfilename appendonly.aof | 指定更新日志文件名,默认为 appendonly.aof |
appendfsync everysec | 指定更新日志条件,共有 3 个可选值:no:表示等操作系统进行数据缓存同步到磁盘(快);always:表示每次更新操作后手动调用 fsync() 将数据写到磁盘(慢,安全);everysec:表示每秒同步一次(折中,默认值) |
vm-enabled no | 指定是否启用虚拟内存机制,默认值为 no,简单的介绍一下,VM 机制将数据分页存放,由 Redis 将访问量较少的页即冷数据 swap 到磁盘上,访问多的页面由磁盘自动换出到内存中 |
vm-swap-file /tmp/redis.swap | 虚拟内存文件路径,默认值为 /tmp/redis.swap,不可多个 Redis 实例共享 |
vm-max-memory 0 | 将所有大于 vm-max-memory 的数据存入虚拟内存,无论 vm-max-memory 设置多小,所有索引数据都是内存存储的(Redis 的索引数据 就是 keys),也就是说,当 vm-max-memory 设置为 0 的时候,其实是所有 value 都存在于磁盘。默认值为 0 |
vm-page-size 32 | Redis swap 文件分成了很多的 page,一个对象可以保存在多个 page 上面,但一个 page 上不能被多个对象共享,vm-page-size 是要根据存储的 数据大小来设定的,作者建议如果存储很多小对象,page 大小最好设置为 32 或者 64bytes;如果存储很大大对象,则可以使用更大的 page,如果不确定,就使用默认值 |
vm-pages 134217728 | 设置 swap 文件中的 page 数量,由于页表(一种表示页面空闲或使用的 bitmap)是在放在内存中的,,在磁盘上每 8 个 pages 将消耗 1byte 的内存 |
vm-max-threads 4 | 设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟。默认值为4 |
glueoutputbuf yes | 设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启 |
activerehashing yes | 指定是否激活重置哈希,默认为开启(后面在介绍 Redis 的哈希算法时具体介绍) |
include /path/to/local.conf | 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件 |
2.3、Mac 环境
如果当前操作系统是 Mac 系统,同样的访问官方地址http://redis.io/download
,下载最新的安装包。
然后本地解压,后续的操作跟linux
一样,在此就不过多的介绍了!
三、命令行客户端
如果想要在 redis 服务上执行命令,需要一个 redis 客户端,而 Redis 客户端在我们下载的的 redis 的安装包里面,其实已经有了。
3.1、连接 redis
Redis 客户端的基本语法为
$ ./redis-cli
比如,连接本地的 redis 服务器(前提是已经启动成功)。
$ ./redis-cli
redis 127.0.0.1:6379>
redis 127.0.0.1:6379> PING
PONG
如果 redis 设置了密码,通过AUTH
命令输入密码即可进入,方式如下:
$ ./redis-cli
redis 127.0.0.1:6379> AUTH "password"
redis 127.0.0.1:6379> PING
PONG
如果我们想连接远程 redis 服务器,可以通过如下语法方式实现。
$ ./redis-cli -h host -p port -a password
比如连接192.168.121.1
,命令如下:
$redis-cli -h 192.168.121.1 -p 6379 -a "mypass"
redis 192.168.121.1:6379>
redis 192.168.121.1:6379> PING
PONG
默认连接的数据库是0
,如果我们想切换数据库,可以通过如下方式实现切换!
# 使用 1 号数据库
redis 192.168.121.1:6379>SELECT 1
如果想要关闭当前连接,通过如下方式即可实现!
redis 192.168.121.1:6379>QUIT
3.2、常用的 crud 操作
以字符串为例,增删改查操作如下!
1、设置指定 key 的值, SET 在设置操作成功完成时,返回 OK。
redis 127.0.0.1:6379>SET mykey redis
OK
2、查询指定 key 的值,操作完成时,如果 key 不存在时,返回 (nil)
redis 127.0.0.1:6379>GET mykey
"redis"
3、检查指定 key 的值是否存在,操作完成时,若 key 存在返回 1 ,否则返回 0
redis 127.0.0.1:6379>EXISTS mykey
(integer) 1
4、删除指定 key 的值,操作完成时,返回被删除 key 的数量。
redis 127.0.0.1:6379>DEL mykey
(integer) 1
5、设置 key 的过期时间,以秒为单位,操作完成时,若成功返回 1 ,否则返回 0。
# 设置 mykey,60秒过期
redis 127.0.0.1:6379>EXPIRE mykey 60
(integer) 1
6、获取 key 的剩余过期时间,以秒为单位,操作完成时,当 key 不存在时,返回 -2;当 key 存在但没有设置剩余生存时间时,返回 -1;否则,以秒为单位,返回 key 的剩余生存时间。
redis 127.0.0.1:6379>TTL mykey
(integer) 60
7、通过 Incr 命令,实现指定的 key 原子性自增操作,每执行一次 Incr 命令,key 中储存的数字值增一,操作完成时,如果 key 不存在,那么 key 的值会先被初始化为 0,然后加 1,返回最后的结果。
redis 127.0.0.1:6379>INCR mykey
(integer) 1
当然,也可以在设置阶段,指定某个初始值数字,比如将mykey
的自增初始值设置为10
。
redis 127.0.0.1:6379>INCR mykey 10
(integer) 11
3.3、事务操作
Redis 也支持事务操作,Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:
- 1.批量操作在发送 EXEC 命令前被放入队列缓存
- 2.收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行
- 3.在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中
一个事务从开始到执行会经历以下三个阶段:
- 1.开始事务
- 2.命令入队
- 3.执行事务
以某个事务操作为例, 我们先以 MULTI 开始一个事务, 然后将多个命令入队到事务中, 最后由 EXEC 命令触发事务, 一并执行事务中的所有命令,过程如下:
redis 127.0.0.1:6379> multi
OK
redis 127.0.0.1:6379> set a aaa
QUEUED
redis 127.0.0.1:6379> set b bbb
QUEUED
redis 127.0.0.1:6379> set c ccc
QUEUED
redis 127.0.0.1:6379> exec
1) OK
2) OK
3) OK
特别注意的地方是:单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。
事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。
也就是说,如果在set b bbb
处失败,set a aaa
已成功不会回滚,set c ccc
还会继续执行,当set b bbb
处执行失败,这个事务是不会回滚的。
但是如果执行过程中,命令不存在或者是命令参数不对,这个时候 redis 的事务执行会失败,并返回错误信息给客户端;如果是命令逻辑上的执行失败,redis 的事务无法感知,会继续执行下去。
3.4、Lua 脚本操作
在上面我们也介绍到了,Redis 事务的执行并不能完全保证原子性,那么如何将一批命令操作做到原子性操作呢?
Redis 支持通过 Lua 脚本来实现一批命令原子性操作,执行脚本的常用命令为 EVAL。
Eval 命令的基本语法如下:
redis 127.0.0.1:6379> EVAL script numkeys key [key ...] arg [arg ...]
比如简单的赋值操作如下:
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"
比如我们给指定的key
设置指定值value
,并且设置过期时间60
秒,实现原子性操作,如果操作成功就返回 1,否则返回 0,内容如下:
redis 127.0.0.1:6379>EVAL "if redis.call('setnx', KEYS[1], ARGV[1]) == 1 then return redis.call('expire', KEYS[1], ARGV[2]) else return 0 end" 1 key1 hello 60
(integer) 1
获取指定key
的值,如果存在就删除key
,实现原子性操作,如果操作成功就返回 1,否则返回 0,内容如下:
redis 127.0.0.1:6379>EVAL "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end" 1 key1 hello
(integer) 1
以上就是实现常用的分布式加锁、解锁原子性操作的 lua 脚本。
四、可视化客户端
对于开发者来说,使用客户端命令来操作 redis 非常不便捷,因此诞生了很多的基于 redis 的可视化客户端,今天我们就一起来看看有哪些免费又好用的客户端工具。
4.1、Redis Desktop Manager
Redis Desktop Manager 应该是现在使用率最广的可视化工具了,存在时间很久,经过了数次迭代,基于 Qt 5 开发,支持跨平台支持。
以前是免费的,不过现在改成收费工具,试用期可以有半个月的时间,最新版的访问地址如下!
https://github.com/uglide/RedisDesktopManager/releases
测评:界面看着比较简洁,该有的功能都有,功能很全,key 的显示可以支持按冒号分割的键名空间。
免费版本的下载地址如下!
百度网盘:https://pan.baidu.com/s/1rMWR-OQnfsxJ3_HSqEE8xw
提取码:tebu
4.2、medis2
medis2 是 mac 系统中使用率最高的 redis 可视化工具,布局简洁,界面美观,关键还免费,最新版的访问地址如下!
https://getmedis.com/
测评:软件颜值挺高,功能符合日常使用要求,对 key 有颜色鲜明的图标标识,在key的搜索上挺方便的,可以模糊搜索出匹配的 key,渐进式的 scan,无明显卡顿,在搜索的体验上还是比较出色的,不过对操作系统要求很高,要求 MacOS 11.0 以上才能安装,如果当前你的操作系统低于以上,只有升级或者换别的软件!
4.3、AnotherRedisDesktopManager
AnotherRedisDesktopManager 是一款比较稳定简洁的 redis UI工具,国人开发,支持跨平台,完全免费,最新版的访问地址如下!
https://github.com/qishibo/AnotherRedisDesktopManager
测评:基本的功能都有,有监控统计,支持暗黑主题,还支持集群的添加,是一款非常不错的可视化客户端。
4.4、Redis Insight
Redis Insight 是目前官方推荐的一款 redis 可视化工具,功能非常丰富,支持跨平台,完全免费,最新版的访问地址如下!
https://redis.com/redis-enterprise/redis-insight/
测评:相比于其他可视化工具,RedisInsight 实现的功能更强大、执行效率更改,通用性更好,出了 CRUD 基本功能的支持,还支持内存分析、指标监控、发布/订阅、慢命令日志查询等等。
五、小结
本文主要围绕redis
的一些基本知识,做了一次简单的总结,包括软件安装、基本命令操作、可视化客户端介绍。
内容难免有些遗漏和不足,欢迎网友留言指出!