什么是 Redis
Redis 是完全开源的,遵守 BSD 协议,是一个高性能的 key-value 数据库。
Redis 与其他 key - value 缓存产品有以下三个特点:
- Redis 支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
- Redis 不仅仅支持简单的 key-value 类型的数据,同时还提供 list,set,zset,hash 等数据结构的存储。
- Redis 支持数据的备份,即 master-slave 模式的数据备份。
Redis 的特性
特性一:速度快
官网声称可以达到:10 万 QPS
- 数据是存在内存中的。
- 使用 C 语言编写。
- 单线程模型。
Redis 速度快的主要原因就是内存
从快到慢依次是:
- Register 寄存器
- L1 Cache 一级缓存
- L2 Cache 二级缓存
- Main Memory 主存
- Local Disk 本地磁盘
- Remote Disk 远程磁盘
类型 | 每秒读写次数 | 随机读写延迟 | 访问带宽 |
---|---|---|---|
内存 | 千万级 | 80ns | 5GB |
SSD 盘 | 35000 | 0.1-02ms | 100~300MB |
机械盘 | 100 左右 | 10ms | 100MB 左右 |
特性二:持久化
Redis 所有数据保存在内存当中,对数据的更新将以异步方式保存到磁盘上。
Redis 支持两种持久化方式:
- RDB
- AOF
特性三:多种数据结构
另外在 Redis 从 2.2.0 版本开始新增了三种数据结构:
Bitmaps 和 HyperLogLog 其实本质上是字符串,并不算是真实的数据结构,而 GEO 本质上有序集合实现的。
• BitMaps:可以实现对位的操作。可以把 Bitmaps 想象成一个以位为单位数组,数组中的每个单元只能存 0 或者 1,数组的下标在 bitmaps 中叫做偏移量。单个 bitmaps 的最大长度是 512MB,即 2^32 个比特位。
• HyperLogLog:超小内存唯一值计数。特点是速度快,占用空间小。
• GEO:地理信息定位。
特性四:支持多种客户端语言
- Java
- PHP
- Python
- Ruby
- Lua
- Node
- …
特性五:功能丰富
- 提供发布订阅功能。
- 支持事务。
- 支持 Lua 脚本。
- Pipeline。
特性六:“简单”
- Redis 的单机核心代码只有 23.000 行左右。
- Redis 不依赖外部库。
- Redis 是单线程模型。
特性七:主从复制
主从复制是 Redis 保证高可用的基础
Redis 提供了复制功能,实现了多个相同数据的 Redis 副本。
特性八:高可用、分布式
Redis 从 2.8 版本正式提供了高可用实现 Redis Sentinel,它能够保证 Redis 节点的故障发现和故障自动转移。
Redis 从 3.0 版本正式提供了分布式实现 Redis Cluster,它是 Redis 真正的分布式实现,提供了高可用、读写和容量的扩展性。
Redis 典型应用场景
- 缓存系统
- 计数器
- 消息队列
- 排行榜
- 社交网络,例如:粉丝数、关注数、共同关注、时间轴列表
- 实时系统,Redis 使用 Bitmap 位图来实现布隆过滤功能,例如:垃圾邮件过滤实时处理
安装 Redis(Linux)
wget http://download.redis.io/releases/redis-3.0.7.tar.gz
tar -xzf redis-3.0.7.tar.gz
ln -s redis-3.0.7 redis
cd redis
make && make install
Redis 可执行文件说明
进入 src 目录下:
- redis-server :Redis 服务器
- redis-cli :Redis 命令行客户端
- redis-benchmark :Redis 基准测试工具
- redis-check-aof :AOF 文件修复工具
- redis-check-dump:RDB 文件检查工具
- redis-sentinel :Sentinel 服务器
三种启动方式
- 最简启动:可以直接使用
redis-server
命令以默认参数进行启动。 - 动态启动:
redis-server –port 6380
- 配置文件启动:
redis-server configPath
验证:
ps -ef | grep redis
:(检查 redis 进程是否启动)netstat -antpl | grep redis
:(检查 redis 服务端口是否存在)redis-cli -h ip -p port ping
:(检查 redis 客户端到 redis 服务端连通性)
三种启动方式比较
生产环境选择配置启动。
单机多实例配置文件可以用端口区分。
启动 Redis
使用下面命令进行启动:
redis-server
连接 Redis
redis-cli -h 127.0.0.1 -p 6379
连接成功后我们就可以做一些操作。
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> get hello
"world"
127.0.0.1:6379> ping
PONG
127.0.0.1:6379>exit
Redis API 使用和理解
通用命令
KEYS
KEYS [pattern]
查找所有符合给定模式 pattern
的 key
, 比如说:
KEYS *
匹配数据库中所有key
。KEYS h?llo
匹配hello
,hallo
和hxllo
等。KEYS h*llo
匹配hllo
和heeeeello
等。KEYS h[ae]llo
匹配hello
和hallo
,但不匹配hillo
。
keys 是 O(n)复杂度所以一般不在生产环境使用,因为 Redis 是单线程架构,使用不当会导致 Redis 阻塞。
DBSIZE
返回当前数据库的 key 的数量。在 Redis 内部有一个计数器来维护 Key 的数量,所以它的复杂度是 O(1)。
EXISTS
检查给定 key
是否存在。
若 key
存在,返回 1
,否则返回 0
。
DEL
删除给定的一个或多个 key
。
返回被删除 key
的数量。
EXPIRE
为给定 key
设置生存时间,当 key
过期时(生存时间为 0
),它会被自动删除。
设置成功返回 1
。 当 key
不存在或者不能为 key
设置生存时间时,返回 0
。
TTL
以秒为单位,返回给定 key
的剩余生存时间(TTL, time to live)。
当 key
不存在时,返回 -2
。 当 key
存在但没有设置剩余生存时间时,返回 -1
。 否则,以秒为单位,返回 key
的剩余生存时间。
PERSIST
移除给定 key
的生存时间,并变为永不过期的key
。
当生存时间移除成功时,返回 1
. 如果 key
不存在或 key
没有设置生存时间,返回 0
。
TYPE
返回 key
所储存的值的类型。
返回值
none
(key 不存在)string
(字符串)list
(列表)set
(集合)zset
(有序集)hash
(哈希表)stream
(流)
数据结构和内部编码
redis 对外展现五种数据类型:
- string
- hash
- set
- zset
- list
每种数据结构,redis 都提供了不同的内部编码实现方式(内部编码可以通过object encoding key
查看),以便使用不同的场景。
127.0.0.1:6379> object encoding hello
"embstr"
string
- raw:大于 39 个字节的字符串,用简单动态字符串(SDS)来保存,将这个字符串的对象编码设置为 raw。
- int:8 个字节的长整型,如果一个字符串保存的类型是整数值,并且这个值可以用 long 类型来表示,name 字符串对象会将整数值保存在字符串对象结构的 ptr 属性里面,并将字符串对象的编码设置为 int。
- embstr:小于等于 39 个字节的字符串,embstr 编码是专门用于保存短字符串的优化编码方式。
embstr 相较于 raw 有以下好处:
- embstr 编码将创建字符串对象所需的空间分配的次数从 raw 编码的两次降低为一次。
- 释放 embstr 编码的字符串对象只需要调用一次内存释放函数,而释放 raw 编码对象的字符串对象需要调用两次内存释放函数
- 因为 embstr 编码的字符串对象的所有数据都保存在一块连续的内存里面,所以这种编码的字符串对象比起 raw 编码的字符串对象能更好地利用缓存带来的优势。
hash
- ziplist(压缩列表):当哈希类型元素小于
has-max-ziplist-entries
配置(默认 512 个),同时所有值都小于hash-max-ziplist-value
配置(默认 64 个字节)时,redis 会使用 ziplist 作为哈希的内部实现。ziplist 使用更加紧凑的结构实现多个元素的连续存储,所以在节省内存方面比 hashtable 更加优秀。 - hashtable(哈希表):当哈希类型无法满足 ziplist 的条件时,redis 会使用 hashtable 作为哈希的内部实现。因为 ziplist 的读写效率会下降,而 hashtable 的读写时间复杂度为 O(1)。
list
- ziplist(压缩列表):当列表类型元素个数小于 hash-max-ziplist-entries 配置(默认 512 个)同时所有值都小于 hash-max-ziplist-value 配置(默认 64 个字节)时,Redis 会使用 ziplist 作为列表的内部实现。
- linkedlist(链表):当列表类型无法满足条件的时候,redis 会使用 linkedlist 作为列表的内部实现。
set
- intset(整数集合):当集合中的元素都是整数且元素个数小于
set-max-intset-entries
配置(默认 512 个)是,redis 会选 intset 作为集合的内部实现,从而减少内存使用。 - hashtable(哈希表):当集合元素无法满足 intset 的条件时,redis 会使用 hashtable 作为集合的内部实现。
zset
- ziplist:当有序集合的元素个数小于
zset-max-ziplist-entries
配置(默认 128 个)同时每个元素的值小于zset-max-ziplist-value
配置(默认 64 个字节)时,Redis 会用 ziplist 来作为有序集合的内部实现,ziplist 可以有效减少内存使用。 - skiplist(跳跃表):当 ziplist 条件不满足的时候,有序集合会使