第一章 Redis简介
1.redis是个什么东西
- 一种键值对的kv-NOSQL数据库。
- string,hash,list(列表),set(集合),zset(有序集合)五种基本类型和bigmaps(位图),hyperloglog,geo(地理信息定位)组合类型。
- 数据都存放在内存中所以读写性能惊人,还可以通过快照和日志方式将数据保存在磁盘上。
- 提供键过期(用于实现缓存),发布订阅(实现消息系统),事务(简单事务功能),流水线pipeline(一次发送多个命令,减少网络开销提高并发。),lua脚本(创造新的redis命令)。
2.redis为什么快
- 官方10万OPS(读写),实际万级别是可以的。因为数据存在内存中。
- 用C语言来实现(更接近操作系统),由单线程来实现(预防多线程竞争问题)。
- 内存可以达到千万级别的读写,读写的延迟也可以在80纳秒,宽带也有5G。
- SSD可以达到35000的每秒读写,延迟在0.1-0.2毫秒,带宽在100-300mb
- 机械盘可以达到100每秒读写,延迟在10毫毛,带宽在100mb左右。
- redis所有的数据保持在内存中,对数据的更新是异步的保存在磁盘上。
3.特性总结
- redis 3.0提供集群功能。23000行代码。
- redis不依赖外部库。单线程模型。
- 提供主从复制功能。为高可用和分布式提供基础。
- 2.8使用redis-sentinel实现高可用
- 3.0使用redis-cluster支持分布式
- hyperloglog 用小内存唯一值计数。上亿也是12k。 2.8支持
- GEO 存储地理位置信息 3.2版本支持
- 支持java php python ruby lua node.js
4.适合做什么
- 缓存系统(提高数据访问速度,减少底层数据源压力,通过键过期,最大内存和淘汰策略。)
- 计数器(微博点赞,转发计数)
- 消息队列系统(发布订阅和阻塞队列功能,一般消息基本满足。但比不上MQ等消息中间件。)
- 排行榜(列表和有序集合可以构建排行榜),社交系统(赞/踩,粉丝,喜欢,下拉刷新比较容易实现)
- 实时系统是redis的典型使用场景。
5.不适合做什么
- 数据放在内存中,对于几亿用户的行为数据。redis存储经济成本太高。虽然内存很便宜。
- 对于不经常访问或者不访问的冷数据,放入redis则浪费redis。
第二章 Redis的部署
1.安装
- 奇数版本号为非稳定版本。
- 偶数版本号为稳定版本。生产使用稳定版本。如3.0,3.2等等
- 虽然当前redis6.0已经发布了稳定版本,但大多数公司使用3.0以上的版本。
- 不同数据库又不同的作用和领域。不是最新版本的数据库就是最好的数据库。
redis的安装(以当前学习时候最新版本为例子)
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固定在指定版本上。用于以后升级方便。
make install 用于将运行文件放到/usr/local/bin下。可以再任意目录下执行redis的相关命令。
使用配置文件启动,部署多个redis可以用多个配置文件用于端口分开。利于资源的合理运用。
2.参数配置
参数配置比较简单
daemonize 是否使用守护进程启动。默认是no。建议使用yes
port 端口,单机多实例要配置。默认6379
logfile 日志名称。
dir redis的工作目录,日志文件和持久化数据在哪里。
过滤掉注释,过滤掉空格
cat /root/redis-3.0.6/redis.conf |grep -v "#" |grep -v "^$" > 26379.conf
其余的不需要。只需要下列参数学习就可。
dir /redis/data
logfile "6379.log"
bind 127.0.0.1
port 6379
daemonize yes
pidfile /var/run/redis_6379.pid
3.可执行命令
redis-server 启动/关闭数据
redis-server redis.conf 来启动数据库进程使用
redis-server shutdown,来关闭数据库进程,断开客户端连接,持久化文件生成。
redis-server shutdown nosave|save 在关闭redis的时候是否生成持久化文件。
redis-cli 连接redis服务端
redis-benchmark 对redis性能测试
redis-check-aof aof的持久化。对aof进行修复。
redis-check-dump rdb的持久化,对rdb修复工具。
redis-sentinel 启动sentinel节点(2.8版本后支持)
4.redis shell
使用shell进行数据库的命令交互
使用redis-cli 进行数据库的连接
redis-cli -h -p 进入redis。默认不加h和p则进入的是 127.0.0.1:6379
redis-cli get heloo 可以直接输入命令并返回结果。
redis-cli info 打印数据库当前的信息
返回值类型
状态回复:ping -> pong
错误回复:get hello -> error
整数回复:incr hello -> 1 计数
字符串回复:get hello -> world
多行字串回复: mget heelo hello2 -> wolrd1 world2
第三章 Redis基础
1.全局命令
| 命令 | 作用 | 执行时间复杂度 |
|---|---|---|
| keys * | 查看所有键,返回所有key的名字。会遍历所有键,生产禁止使用,数据量越大越慢,会堵塞其他命令。使用scan来替代或者在丛节点上使用keys | o(n) |
| dbsize | 返回当前数据库中的键数,就是所有的key数,返回个数。不会遍历直接获取redis内置的键总数变量。 | o(1) |
| exists key | 检查key是否存在,存在返回1,不在返回0 | o(1) |
| del key | 删除key。成功返回删除的key数量。key不存在返回0。支持删除多个key比如 del a b c删除abc三个key。返回3。 | o(1) |
| expire key seconds | 键过期。超过指定时间会自动删除键 | o(1) |
| ttl | 查看key过期时间 | o(1) |
| 返回-2,表示已经删除。 | ||
| 返回-1,存在但是没有设置过期时间 | ||
| 返回大于0的整数,表示剩余过期时间 | ||
| type key | 计算key的类,存在返回类型,不存在返回none | o(1) |
| persist | 去掉过期时间。使key不过期。 | o(1) |
| get key | 获得key的值, | o(1) |
2.数据结构与内部编码
| 数据类型 | 内部编码 |
|---|---|
| obeject encoding key | 查询内部编码 |
| string | 字符串,有三种内部编码,raw,int,embstr。 |
| hash | 哈希,有两种内部编码,hashtable,ziplist。 |
| list | 列表,有两种内部编码,linkedlist,ziplist。 |
| set | 集合,有两种内部编码,hashtable,intset。 |
| zset | 有序集合,有两种内部编码,skiplist,ziplist。 |
优点:
- 好处是可以改进代码,当有更好的内部编码时,对外部的数据结构和命令没有影响。无需改动外部数据结构和命令。
- 3.2提供quicklist。结合了ziplist和linkedlist优势。为list列表类型提供更优秀的内部有编码实现。
- 每一种可以发挥自己的优势。ziplist比较节省内存,但是列表元素多的情况下性能会下降,redis这个时候回将类型内部转换为linkedlist。
3 redis命令执行过程
每次执行命令都是如下3个步骤。
1.client通过网络发送命令给server端。
2.redis收到请求,放入队列,按照顺序执行命令。
3.redis通过网络将结果返回给client。
因为redis是单线程处理命令的。
client发送过来的命令到了服务端不会立即执行。而是会放入队列里面,逐个执行。
多个客户端执行的顺序不一样。但确定不会有两条命令被同时执行。
io多路复用
单线程为什么处理迅速
纯内存访问,响应时间为100纳秒。每秒万级别访问的基础。
非阻塞io,通过epoll作为io多路复用的实现。
redis自身将epoll中的连接,读写,关闭转换为时间。不在网络io上浪费过多时间。
单线程避免了线程切换和竞争所耗费的时间。锁和线程切换是性能杀手。
单线程处理的缺点是,如果某个命令处理过慢,会阻塞其他命令的处理。
拒绝长慢的命令比如 keys,flushall,flushdb,slow lua script,operate,mutil/exec,
big value(collection)
在fysnc file descriptor和close file descriptor 的时候不是单线程。是有专门的线程去处理。