简介
Redis是一个采用C语言编写的开源、基于内存、可选持久化的键值对(key-value)NoSQL数据库。与很多键值对数据库不同的是,Redis中的值可以是由string(字符串)、hash(哈希表)、list(列表)、set(集合)、zset(SortedSet(有序集合))、Bitmaps(位图)、HyperLogLog、GEO(地理位置信息)等多种数据结构和算法组成,因此Redis可以满足很多的应用场景,而且因为Redis会将所有数据都存放在内存中,所以它的读写性能非常惊人。不仅如此,Redis还可以将内存的数据利用快照和日志的形式保存到硬盘上,这样在发生类似断电或者机器故障时,内存中的数据不会"丢失"。
除了上述功能以外,Redis还提供了键过期、Pub/Sub(发布/订阅)、Transaction(事务)、流水线(Pipeline)、Lua脚本等附加功能。
Redis 特性
Redis之所以广受好评,主要有如下8个重要特性。
- 速度快:正常情况下,Redis执行命令的速度非常快,官方给出的数字是读写性能可以达到10w/秒,当然这也取决于机器的性能。
- 基于键值对的数据结构服务器
- 丰富的功能
- 简单稳定
- 客户端支持多种语言
- 持久化
- 主从复制
- 高可用和分布式
全局命令
- 查看所有键
keys *
- 键总数
dbsize
- 检查键是否存在
exists key
如果键存在返回1,不存在返回0
- 删除键
del key [key ...]
del是一个通用命令,无论值是什么数据结构,del命令都可以将它删除。
- 键过期
expire key seconds
Redis支持对键添加过期时间,当超过过期时间后,会自动删除键。
- 键的数据结构类型
type key
单线程架构
Redis使用了单线程架构和I/O多路复用模型 来实现高性能的内存数据库服务。
Redis客户端与服务器的模型可以简化为图2-3,每次客户端调用都经历了发生命令、执行命令、返回结果 三个过程。
其中,第二步是重点要讨论的,因为Redis是单线程来处理命令的,所以一条命令从客户端到达服务器端不会立刻被执行,所有命令都会进入一个队列中,然后逐个被执行,这就是Redis单线程的基本模型。但是像发送命令、返回结果、命令排队肯定不会像描述的这么简单,Redis使用了 I/O多路复用技术来解决I/O的问题。
为什么单线程还能这么快
通常来讲,单线程处理能力要比多线程差,那么为什么Redis使用单线程模型会达到每秒万级别的处理能力呢?可以将其归结为三点:
第一,纯内存访问,Redis将所有数据放在内存中,内存的响应时长大约为100纳秒,这是Redis达到每秒万级别访问的基础。
第二,非阻塞I/O,Redis使用epoll作为I/O多路复用技术的实现,再加上Redis自身的事件处理模型将epoll中的连接、读写、关闭等都转换为事件,不在网络上I/O上浪费过多的时间。
第三,单线程避免了线程切换和竞态产生的消耗。
字符串
字符串是Redis最基础的数据结构。字符串类型的值实际可以是字符串(简单的字符串、复杂的字符串(例如JSON、XML)、数字(整数、浮点数),甚至是二进制(图片、音频、视频),但是最大值不能超过512MB。
1.设置值
set key value [ex seconds] [px milliseconds] [nx|xx]
set命令有几个选项:
- ex seconds:为键设置秒级过期时间
- px milliseconds:为键设置毫秒级过期时间
- nx:键必须不存在,才可以设置成功,用户添加
- xx:与nx相反,键必须存在,才可以设置成功,用户更新
setnx 和 setxx在实际使用中有什么应用场景吗?以setnx 为例,由于Redis的单线程命令处理机制,如果有多个客户端同时执行 setnx key value
,根据setnx的特性只有一个客户端能设置成功,setnx可以作为分布式锁的一种实现方案,Redis官方给出了使用setnx实现分布式锁的方法:Distributed locks with Redis:https://redis.io/topics/distlock
2.获取值
get key
3.批量设置值
mset key value [ key value ...]
例如:
mset a 1 b 2 c 3 d 4
4.批量获取值
mget key [key ...]
例如批量获取键 a、b、c、d的值:
mget a b c d
5.计数
incr key
incr 命令用于对值做自增操作,返回结果分为3种情况:
- 值不是整数,返回错误
- 值是整数,返回自增后结果
- 键不存在,按照值为0自增,返回结果为1.
6.追加值
append key value
append 可以向字符串尾部追加值。
哈希(hash)
几乎所有的编程语言都提供了哈希(hash)类型,它们的叫法可能是哈希、字典、关联数组。在Redis中,哈希类型是指 键值 本身又是一个 键值对结构,形如value={field1:value1, ... , fieldN:valueN}。
1.设置值
hset key field value
例如,为user1添加一对field-value:
hset user1 name tom
2.获取值
hget key field
···
例如,获取user1 的name属性对应的值:
hget user1 name
### 3.删除field
hdel key field
### 4.计算field个数
hlen key
### 5.批量设置或获取field-value
···
hmset key field value [field value ...]
hmget key field [field ...]
···
### 6.判断field 是否存在
hexists key field
### 7.获取所有field
hkeys key
### 8.获取所有value
hvals key
### 9. 获取所有的field-value
hgetall key
## 列表(list)
https://redis.io/commands#list
## 集合(set)
https://redis.io/commands#set
## 有序集合(sorted set)
https://redis.io/commands#sorted_set
## 参考资料
http://redisdoc.com/