1. 简介
Redis 全称:Remote Dictionary Server(远程字典服务器),是一款开源的,遵守 BSD 协议,使用 C 语言开发的 key-value 存储系统。简单的说,它是一款跨平台的非关系型数据库,支持优先内存存储,并提供多种语言的 API 客户端
虽然开源软件市场上也有很多优秀的缓存服务中间件,比如 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. 服务安装
因为 Redis 目前官方只支持 LINUX 系统,因此没有 Windows 版本的软件包,但是好在微软团队维护了开源的 windows 版本,虽然更新不算及时,但是对于普通测试使用足够了。
Redis Windows 版下载地址
windows 版安装教程
3. Redis 的常用操作命令
3.1 公共命令
// 1.客户端连接 redis
redis-cli -h localhost -p 6379
// 2.切换数据库
select 3
// 3.查看 DB 大小
DBSIZE
// 4.查看 DB 中所有的 key
keys *
// 5.清空当前数据库
flushdb
// 6. 清空全部数据库内容
flushdb
3.2 Key 的命令
keys * # 查看所有的 key
exists key # 判断某个 key 是否存在
move key 1 # 移除某个 key 1 表示当前数据库
expire key 10 # 给 key 设置过期时间(10s)
persist key # 移除 key 的过期时间
ttl key # 查看 key 的过期时间(s)
type key # 查看 key 对应的 value 的类型
3.3 String 命令
set key value # 给 key 设置 value
get key # 获取 key 对应的 value
exists key # 判断key 是否存在
append key value # 如果 key 存在,则追加;否则,相当于 set 命令
strlen key
incr key # 自增 1
decr key # 自减
incrby key step # 设置步长
decrby key step
getrange key startIndex stopIndex # 截取字符串(下标从0开始)
setrange key index value # 将索引对应的值替换成value
setex key time value # 设置key为value,并且设置过期时间time(s)
setnx key value # 如果 key 不存在,就设置
mset k1 v1 k2 v2 # 批量设置
mget k1 k2 # 批量获取
msetnx # 批量设置(原子操作)
getset key value # 先 get,再 set
String 的应用场景:
- 计数器
- 统计数量
- 粉丝数
- 对象缓存
3.4 List 命令
lpush list value1 [value2] # 将一个值(或多个值)添加到 list 的头部(左)
lpop list # 移除 list 头部的值(左)
lrange list lIndex rIndex # 获取 list 中的某个范围的值
lindex list index # 通过下标获取值(左)
llen list # 获取 list 的长度
lrem list count value # 移除 list 中 count 个 value
ltrim list lIndex rIndex # 通过下标返回部分 list
rpoplpush list list2 # 移除 list 中最后一个元素,并将它添加到 list2 中去
exists list # 判断 list 是否存在
lset list index value # 将 list 中下标为 index 的值修改为 value
linsert list before|after pivot value # 往 list 中在某个元素 pivot 之前|后插入value
rpush list value # 将一个值(或多个值)添加到 list 的尾部(右)
rpop list # 移除 list 尾部的值(右)
list 实际上是一个链表:before Node after,left、right 都可以插值
两边插入或修改,效率最高
消息队列(lpush、rpop)、栈(lpush、lpop)
3.5 Set 命令
sadd set value1 [value2] # 给 set 设置值
smembers set # 查看 set 中的成员
sismember set value # 查看 set 中是否有 value
scard set # 获取 set 中元素的个数
srem set value # 移除 set 中指定的 value
srandmember set count # 随机抽选出 count 个元素
spop set # 随机删除 set 中的元素
sdiff set1 set2 # 返回 set1、set2 的差集
sinter set1 set2 # 返回 set1、set2 的交集(共同好友)
sunion set1 set2 # 返回 set1、set2 的并集
3.6 Hash 命令
hset hash key value # 设置 hash 的一个 key-value
hget hash key # 根据 hash 的一个 key,获取 value
hmset hash key1 value1 key2 value2 # 设置 hash 的多个 key-value
hmget hash key1 key2 # 根据多个 key 来获取多个 value
hgetall hash # 获取所有的 key-value
hdel hash key # 删除 hash 中指定的 key
hlen hash # 获取 hash 的长度(有多少个 key-value)
exists hash key # 判断 hash 中某个 key 是否存在
hkeys hash # 只获取 hash 中的所有的 key
hvals hash # 只获取 hash 中的所有的 value
hincrby hash key count # 给 hash 中的 key 加 count
hsexnx hash key value # 如果 key 存在,则,可以设置;如果不存在,则,不可以设置
hash 用来存储经常变更的数据:user (name、age)
hash 更加适合对象的存储,string 更加适合字符串的存储
3.7 ZSet 命令
zadd zset score value # 添加一个值
zrangebyscore zset -inf +inf # 显示全部数据(负无穷-正无穷)
zrangebyscore zset -inf +inf withsocres # 显示全部数据并且附带 score
zrange zset 0 -1 withsocres # 显示所有成员及其 score 值
zrange zset 0 -1 # 显示全部(正序)
zrevrange zset 0 -1 # 显示全部(倒序)
zrem zset value # 移除某个 value
zcard zset # 返回 zset 中的元素个数
zcount zset value1 value2 # 获取指定成员之间的数量
zrank zset value # 返回有序集中指定成员的排名(从小到大)
zset 应用于带权重的,如:排行榜。
3.8 事务操作
Redis 也支持事务操作,Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:
- 批量操作在发送 EXEC 命令前被放入队列缓存
- 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行
- 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中
一个事务从开始到执行会经历以下三个阶段:
- 开始事务:MULTI
- 命令入队:QUEUE
- 执行/丢弃事务:EXEC 或者 DISCARD
以某个事务操作为例:我们先以 MULTI 开始一个事务, 然后将多个命令入队到事务中, 最后由 EXEC 命令触发事务, 一并执行事务中的所有命令。过程如下:
特别注意的地方是:单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的
事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。
3.9 Lua 脚本操作
在上面我们也介绍到了,Redis 事务的执行并不能完全保证原子性,那么如何将一批命令操作做到原子性操作呢?
==Redis 支持通过 Lua 脚本来实现一批命令原子性操作,==执行脚本的常用命令为 EVAL
。
Eval 命令的基本语法如下:
EVAL script numkeys key [key ...] arg [arg ...]
参数含义:
- script:Lua 5.1版本的脚本,这个脚本并不需要定义一个 Lua 函数或者说是不应该这样做。它可以仅仅是一个 Lua 语法,这个语法运行在 Redis 服务器上下文
- numkeys:Redis键的数量,Lua采用基于数组形式(KEYS全局变量)访问这些参数(KEYS[1]、KEYS[2] …)
- arg:不代表redis键,它们可以通过ARGV全部变量定义的数组访问,与KEYS数组设置类似,形式为 ARGV[1]、ARGV[2] …
如:
EVAL "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
lua 脚本中调用 redis 命令
案例1:
给指定的 key 设置指定值 value,并且设置过期时间 60 秒,实现原子性操作,如果操作成功就返回 1,否则返回 0
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
案例2:
获取指定 key 的值,如果存在就删除 key,实现原子性操作,如果操作成功就返回 1,否则返回 0
EVAL "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end" 1 key1 hello
4. 可视化客户端
对于开发者来说,使用客户端命令来操作 redis 非常不便捷,因此诞生了很多的基于 redis 的可视化客户端。如下:
- Redis Desktop Manager 下载地址
- medis2(mac 系统)下载地址
- AnotherRedisDesktopManager 下载地址
- Redis Insight 下载地址