[TOC]
redis是什么
官方解释:
redis 是一个开源的,内存中的K-V数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 redis内置了复制(replication),LUA脚本(Lua scripting),LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。
redis是remote dictionary server的简写,这样可以明显地了解Redis的定位。redis简单来看就是一个内存中(运行时)的hashtable,所有的数据都在内存中,它支持最基础的put和get操作对hash表内的数据进行修改。这是它最为基础的功能,因为是基于内存,所以支持高效的读写(官方给出的数据为10w次/s的读写性能),很容易想到最常见的使用场景:缓存。另外因为它支持数据的持久化(有两种持久化策略),所以也可以作为nosql的解决方案。
除了基础的数据存取之外,redis支持分布式,所以可以构建分布式缓存和分布式的消息中间件以及分布式数据库,来提供高可用性。
redis的主要特性
- 速度快
- 数据存储在内存中
- 基于键值对的数据结构服务器
- 支持多种数据类型
- 功能丰富,如复制、HyperLogLog、事务、发布订阅、持久化等
- 简单稳定
- 客户端支持大量的语言
- 支持高可用和分布式
单线程架构
Redis服务是单线程的进程,底层是使用了IO多路复用模型来支撑高性能的内存数据库服务。
所有发送到redis的命令都会进入一个命令队列中,一个一个执行,所以如果某个命令执行了很久,就会影响整个redis的性能表现。
redis为什么这么快
官方给的redis的读写性能能够达到数万到数十万次每秒,How fast is Redis?,具体性能和系统以及硬件是相关的。
redis的性能很好有几个主要的原因:
- 基于内存,和磁盘读写不是一个数量级
- 使用C语言这个近操作系统的语言,有较好的执行性能
- 单线程的架构设计,没有并发控制的开销
- redis源码十分优秀
- 使用epoll作为IO多路复用技术来实现NIO(NonBlocking IO)
Redis基于单线程模型,使用中一定要注意线程阻塞的情况。
redis使用场景
- 缓存
- 排行榜系统
- 计数器应用
- 社交网络
- 消息队列
redis环境搭建
redis使用了很多操作系统的特性,且是基于Linux系统的,官方是不支持Windows系统的,Windows版本的是Windows团队开发的一个分支。
下载安装
wget http://download.redis.io/releases/redis-4.0.10.tar.gz
tar xzf redis-4.0.10.tar.gz
cd redis-4.0.10
make && make install
安装成功后,redis相关运行文件在/usr/local/bin中。
[root@aliyun bin]# ll /usr/local/bin/
total 21872
-rwxr-xr-x 1 root root 2451088 Sep 22 16:19 redis-benchmark
-rwxr-xr-x 1 root root 5773320 Sep 22 16:19 redis-check-aof
-rwxr-xr-x 1 root root 5773320 Sep 22 16:19 redis-check-rdb
-rwxr-xr-x 1 root root 2617168 Sep 22 16:19 redis-cli
lrwxrwxrwx 1 root root 12 Sep 22 16:19 redis-sentinel -> redis-server
-rwxr-xr-x 1 root root 5773320 Sep 22 16:19 redis-server
[root@aliyun bin]#
这里面就是redis内建的shell。
redis shell
- redis-server redis的服务端,作用是启动redis服务
- redis-cli 是redis的命令行客户端,用于连接redis服务操作redis
- redis-benchmark 是redis的性能测试工具
- redis-check-aof 是RedisAOF持久化文件检测和修复工具
- redis-check-rdb 是redis RDB持久化文件的检测和修复工具
- redis-sentinel 是redis哨兵功能模式,用于分布式
启动和关闭
启动使用redis-server
命令,支持读配置文件和指定命令行参数的方式,一般包含的配置有:
- 绑定的端口号
- 日志文件
- redis的工作目录
- 是否以deamon的方式运行
启动服务
redis-server
帮助文档:
[root@aliyun ~]# redis-server -h
Usage: ./redis-server [/path/to/redis.conf] [options] # 指定配置文件和option
./redis-server - (read config from stdin)
./redis-server -v or --version
./redis-server -h or --help
./redis-server --test-memory <megabytes>
Examples:
./redis-server (run the server with default conf)
./redis-server /etc/redis/6379.conf
./redis-server --port 7777
./redis-server --port 7777 --slaveof 127.0.0.1 8888 # 作为127.0.0.1:8888实例的从实例
./redis-server /etc/myredis.conf --loglevel verbose
Sentinel mode:
./redis-server /etc/sentinel.conf --sentinel
连接和使用服务
使用redis-cli这个内建的cli工具,或者使用官方提供的各种编程语言的api连接redis服务。
- 使用redis cli连接
[root@aliyun ~]# redis-cli
127.0.0.1:6379> set foo "hello redis"
OK
127.0.0.1:6379> get foo
"hello redis"
127.0.0.1:6379> exit
redis-cli有很多的参数,支持交互方式执行命令和非交互方式。
- redis-cli帮助文档:
[root@aliyun ~]# redis-cli -h
redis-cli 4.0.10
Usage: redis-cli [OPTIONS] [cmd [arg [arg ...]]]
-h <hostname> Server hostname (default: 127.0.0.1). 也就是说可以连接远程的server
-p <port> Server port (default: 6379). 指定端口号连接,具体根据server的端口号
-s <socket> Server socket (overrides hostname and port).
-a <password> Password to use when connecting to the server.
-u <uri> Server URI.
-r <repeat> Execute specified command N times. 重复N次执行某个命令
-i <interval> When -r is used, waits <interval> seconds per command.
It is possible to specify sub-second times like -i 0.1.
-n <db> Database number.
-x Read last argument from STDIN.
-d <delimiter> Multi-bulk delimiter in for raw formatting (default: \n).
-c Enable cluster mode (follow -ASK and -MOVED redirections).
--raw Use raw formatting for replies (default when STDOUT is
not a tty).
--no-raw Force formatted output even when STDOUT is not a tty.
--csv Output in CSV format.
--stat Print rolling stats about server: mem, clients, ...
--latency Enter a special mode continuously sampling latency.
If you use this mode in an interactive session it runs
forever displaying real-time stats. Otherwise if --raw or
--csv is specified, or if you redirect the output to a non
TTY, it samples the latency for 1 second (you can use
-i to change the interval), then produces a single output
and exits.
--latency-history Like --latency but tracking latency changes over time.
Default time interval is 15 sec. Change it using -i.
--latency-dist Shows latency as a spectrum, requires xterm 256 colors.
Default time interval is 1 sec. Change it using -i.
--lru-test <keys> Simulate a cache workload with an 80-20 distribution.
--slave Simulate a slave showing commands received from the master.
--rdb <filename> Transfer an RDB dump from remote server to local file.
--pipe Transfer raw Redis protocol from stdin to server.
--pipe-timeout <n> In --pipe mode, abort with error if after sending all data.
no reply is received within <n> seconds.
Default timeout: 30. Use 0 to wait forever.
--bigkeys Sample Redis keys looking for big keys.
--hotkeys Sample Redis keys looking for hot keys.
only works when maxmemory-policy is *lfu.
--scan List all keys using the SCAN command.
--pattern <pat> Useful with --scan to specify a SCAN pattern.
--intrinsic-latency <sec> Run a test to measure intrinsic system latency.
The test will run for the specified amount of seconds.
--eval <file> Send an EVAL command using the Lua script at <file>.
--ldb Used with --eval enable the Redis Lua debugger.
--ldb-sync-mode Like --ldb but uses the synchronous Lua debugger, in
this mode the server is blocked and script changes are
are not rolled back from the server memory.
--help Output this help and exit.
--version Output version and exit.
Examples:
cat /etc/passwd | redis-cli -x set mypasswd
redis-cli get mypasswd
redis-cli -r 100 lpush mylist x
redis-cli -r 100 -i 1 info | grep used_memory_human:
redis-cli --eval myscript.lua key1 key2 , arg1 arg2 arg3
redis-cli --scan --pattern '*:12345*'
(Note: when using --eval the comma separates KEYS[] from ARGV[] items)
When no command is given, redis-cli starts in interactive mode.
Type "help" in interactive mode for information on available commands
and settings.
- 后台启动
[root@aliyun ~]# redis-server &
或者在配置文件中将daemonize设置为yes,然后启动时指定配置文件。
从使用方式可以看出redis整体上是一个C-S架构的组件,其实和mysql等DB看上去差不多,一个作为服务端的数据容器,客户端经由网络(实际上是基于TCP协议的RDBP)连接server,执行操作数据或者元数据的命令。
停止服务
- redis-cli shutdown
- 系统的kill命令(不要使用)
redis-cli shutdown命令是友好的停止命令,停止的过程包含三个阶段:
- 断开与客户端的连接
- 持久化数据 (可以指定save|nosave选项来选择是否进行持久化,默认会持久化)
- 退出
使用kill命令会强制杀死进程,不会保存数据。
redis的K-V数据类型
key
key为string类型,是redis中的hashtable的key。
常用操作和命令
- 判断key是否存在
exists foo
- 设置可以值
set foo bar
- 获取可以的value
get foo
- 获取key的value的类型
type foo
- 设置key的过期时间,单位是秒
expire foo seconds
- 设置key的过期时刻,UNIX 时间戳,从UTC到时刻的秒数
expireat foo timestamp
- 设置key的过期时间,单位毫秒
pexpire foo milliseconds
- 取消key的过期设置,直接持久化,过期时间为-1,默认的都是持久的
persist key
- 查看key的过期时间,单位秒
pttl key
- 查看key的过期时间,单位毫秒
ttl key
- 随机返回一个key
randomkey
- 重命名一个key名
rename key newkey
- 重命名key名为新的key名,要求新key不存在
renamenx key newkeynoexists
- 返回匹配模式的key
keys pattern
- 删除key
del foo
- key的数量
dbsize
- 测试
127.0.0.1:6379> set m 100
OK
127.0.0.1:6379> get m
"100"
127.0.0.1:6379> ttl m
(integer) -1
127.0.0.1:6379> expire m 3
(integer) 1
127.0.0.1:6379> ttl m
(integer) 1
127.0.0.1:6379> ttl m
(integer) -2
127.0.0.1:6379> get m
(nil)
127.0.0.1:6379> set m hello
OK
127.0.0.1:6379> del m
(integer) 1
127.0.0.1:6379> get m
(nil)
127.0.0.1:6379>
value
value分多种数据类型包括:
- string(基础)
- hash(string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象)
- list (字符串列表)
- set(无序不重复的字符串集合)
- Sorted set(有序集合)
可以通过命令
type key
来查看key对应的value的类型。
string
string是redis的基础数据类型,key的数据类型就是string,其他复合类型的数据也基于string。string最大能存储512MB的数据。
hash
即HashMap,和redis的基础结构类似,是一个key-value的数据类型。hash的key和value都是string类型(不支持嵌套的数据结构,如hash的value是hash这种事不存在的),hash的size为4字节空间,即32位有符号整形数的取值范围。
hash适合描述对象,类似于json的简化格式,因为不支持数据类型的嵌套,所有不能描述对象的属性还是对象这种模型。
只能支持类似:key field1 value1 field2 value2 ...
list
底层是双向链表实现的线性数据结构,所以在头尾追加节点的效率很高,但是随机访问效率就差了。容量空间也是32位。内部元素类型为string。可以在两端添加元素。
类似key e1 e2 e3
set
redis的Set是string类型的无序集合,元素不重复,重复添加的直接忽略。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
集合提供了求交集、并集、差集等操作。
sorted set
将Set中的元素增加一个权重参数score,元素按score有序排列。
由hash表和skiplist实现,所以即使读取中间位置的数据速度也很快(O(lgN))。
Skip List是一种随机化的数据结构,基于并联的链表,其效率可比拟于二叉查找树(对于大多数操作需要O(log n)平均时间)。基本上,跳跃列表是对有序的链表增加上附加的前进链接,增加是以随机化的方式进行的,所以在列表中的查找可以快速的跳过部分列表(因此得名)。所有操作都以对数随机化的时间进行。Skip List可以很好解决有序链表查找特定值的困难。
参考资料
- [1] Redis 教程
- [2] 李子骅.Redis入门指南
- [3] 付磊,张益军.Redis开发与运维