一、Redis介绍

一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。可以满足很多应用场景。还提供了键过期,发布订阅,事务,流水线等附加功能


二、Redis使用场景

存储缓存、投票、会话session、排行榜、计数器、发布订阅、消息队列等


三、快速开始

下载

$ wget http://download.redis.io/releases/redis-5.0.5.tar.gz

解压

$ tar xzf redis-5.0.5.tar.gz

编译

$ cd redis-5.0.5

$ make


文件

说明

redis-server

启动redis

redis-cli

redis命令行客户端

redis-benchmark

测试工具

redis-check-aof

AOF持久化工具

redis-check-dump

DB持久化工具

redis-sentinel

哨兵相关

redis-trib

Redis cluster模式管理工具

redis.conf

Redis的配置文件

 

csredis分布式缓存 redis 分布式缓存_redis

缺点:单进程单线程(不足)命令慢 堵塞

优点:线程切换资源消耗

IO多路复用

1、redis安装在磁盘

2、redis数据运行在内存



启动


后台启动

 

csredis分布式缓存 redis 分布式缓存_csredis分布式缓存_02


查看redis进程,启动客户端

启动客户端 src/redis-cli

csredis分布式缓存 redis 分布式缓存_redis持久化_03

四、通讯原理:

csredis分布式缓存 redis 分布式缓存_redis数据结构_04

五、Redis日常操作

计数器:

CAS(Atomic原子操作)
incr age //必须为整数自加1,非整数返回错误,无age键从0自增返回1
decr age //整数age减1
incrby age 1 //整数age+1
decrby age 1//整数age -1
incrbyfloat score 3.3 //浮点型score+3.3

csredis分布式缓存 redis 分布式缓存_分布式缓存_05


字符串:

字符串类型:实际上可以是字符串(包括XML JSON),还有数字(整形 浮点数),二进制(图片 音频 视频),最大不能超过512MB

设值命令:



批量设值:mset name monkey sex boy

批量获取:mget name sex  (\r\n)

127.0.0.1:6379> set key yurz

OK

127.0.0.1:6379> get yurz

(nil)

127.0.0.1:6379> get key

"yurz"

127.0.0.1:6379> keys*

(error) ERR unknown command `keys*`, with args beginning with:

127.0.0.1:6379> keys *

1) "user:1"

2) "String"

3) "age"

4) "key"

5) "score"

127.0.0.1:6379> setnx name yurz ex 20

(error) ERR wrong number of arguments for 'setnx' command

127.0.0.1:6379> setnx name yurz

(integer) 1

127.0.0.1:6379> set age 18 xx

OK

127.0.0.1:6379> set age 18 xx

OK

127.0.0.1:6379> mset name yurz sex boy

OK

127.0.0.1:6379> mget name sec

1) "yurz"

2) (nil)

127.0.0.1:6379> mget name sex

1) "yurz"

2) "boy"

127.0.0.1:6379>


字符追加

append追加指令:
set name hello;
append name world //追加后成helloworld
字符串长度:

strlen monkey//结果6,每个中文占3个字节(utf-8)


截取字符串:

set name monkey;

getrange name 2 4//返回“nke”


127.0.0.1:6379> mset name yurz sex boy

OK

127.0.0.1:6379> mget name sec

1) "yurz"

2) (nil)

127.0.0.1:6379> mget name sex

1) "yurz"

2) "boy"

127.0.0.1:6379> set name hello

OK

127.0.0.1:6379> append name world

(integer) 10

127.0.0.1:6379> get name

"helloworld"

127.0.0.1:6379> set yurz 'mm'

OK

127.0.0.1:6379> strlen yurz

(integer) 2

127.0.0.1:6379> set name yurz

OK

127.0.0.1:6379> getrange name 1 3

"urz"

127.0.0.1:6379>


Hash类型


哈希hash是一个string类型的field和value的映射表,hash特适合用于存储对象

Id

Username

Sex

age

1

Monkey

Boy

18

2

Fox

Boy

 



命令  hset key field value



获取所有field: hkeys user:2            // 返回name age sex三个field
   获取user:2所有value:hvals user:2     // 返回monkey18 boy
   获取user:2所有field与value:hgetall user:2 //name age sex monkey18 18 boy值



127.0.0.1:6379> hset user:1 name monkey

(integer) 0

127.0.0.1:6379> hget user:1 name

"monkey"

127.0.0.1:6379> hdel user:1 name

(integer) 1

127.0.0.1:6379> hset user:1 name monkey; hset user:1 age 18;

(integer) 1

127.0.0.1:6379> hlen user:1

(integer) 3

127.0.0.1:6379> hmset user 2:name monkey age 18 sex boy;

OK

127.0.0.1:6379> hmget user:2 name age sex

1) (nil)

2) (nil)

3) (nil)

127.0.0.1:6379> hmget  name age sex

(error) WRONGTYPE Operation against a key holding the wrong kind of value

127.0.0.1:6379> hmset user:2 name monkey age 18 sex boy;

OK

127.0.0.1:6379> hmget user:2 name age sex

1) "monkey"

2) "18"

3) "boy;"

127.0.0.1:6379> hexists user:2 name age sex

(error) ERR wrong number of arguments for 'hexists' command

127.0.0.1:6379> hexists user:2 name

(integer) 1

127.0.0.1:6379> field:hkeys user:2

(error) ERR unknown command `field:hkeys`, with args beginning with: `user:2`,

127.0.0.1:6379> field:hkeys

(error) ERR unknown command `field:hkeys`, with args beginning with:

127.0.0.1:6379> field:hkeys user:2

(error) ERR unknown command `field:hkeys`, with args beginning with: `user:2`,

127.0.0.1:6379> hkeys user:2

1) "name"

2) "age"

3) "sex"

127.0.0.1:6379> hvals user:2

1) "monkey"

2) "18"

3) "boy;"

127.0.0.1:6379> hgetall user:2

1) "name"

2) "monkey"

3) "age"

4) "18"

5) "sex"

6) "boy;"

127.0.0.1:6379> hincrby user:2 age 1

(integer) 19

127.0.0.1:6379> hincrbyfloat user:2 age 2

"21"


List集合

用来存储多个有序的字符串,一个列表最多可存2的32次方减1个元素

添加命令:



查找命令:



执行结果:

 

csredis分布式缓存 redis 分布式缓存_redis持久化_06

 Set集合

用户标签,社交,查询有共同兴趣爱好的人,智能推荐

保存多元素,与列表不一样的是不允许有重复元素,且集合是无序,一个集合最多可存2的32次方减1个元素,除了支持增删改查,还支持集合交集、并集、差集;





csredis分布式缓存 redis 分布式缓存_redis数据结构_07

有序集合ZSET

常用于排行榜,如视频网站需要对用户上传视频做排行榜,或点赞数与集合有联系,不能有重复的成员

指令:   
   zadd key score member [score member......]
例子:
   zadd user:zan 200 monkey //monkey的点赞数1, 返回操作成功的条数1
   zadd user:zan 200 monkey 120 fox 100 lion// 返回3
   zadd user:zan nx 100 monkey//键test:1必须不存在,主用于添加
   zadd user:zan xx incr 200 monkey//键test:1必须存在,主用于修改,此时为300
   zadd user:zan xx ch incr -299 monkey//返回操作结果1,300-299=1
zrange user:zan 0  -1 withscores//查看点赞(分数)与成员名
   zcard user:zan    //计算成员个数, 返回1
 
排名场景:
   zadd user:3 200 monkey120 fox 100 lee//先插入数据
   zrange user:3 0 -1 withscores //查看分数与成员
  zrank user:3 monkey//返回名次:第3名返回2,从0开始到2,共3名
  zrevrank user:3 monkey//返回0, 反排序,点赞数越高,排名越前

csredis分布式缓存 redis 分布式缓存_redis_08

csredis分布式缓存 redis 分布式缓存_分布式缓存_09

csredis分布式缓存 redis 分布式缓存_分布式缓存_10

Redis全局命令:

 

1,查看所有键:
keys *
2,键总数 :
dbsize       //2个键,如果存在大量键,线上禁止使用此指令
3,检查键是否存在:
exists key  //存在返回1,不存在返回0
4,删除键:
del key      //del key, 返回删除键个数,删除不存在键返回0
5,键过期:
expire key seconds        //set name test  expire name 10,表示10秒过期
ttl key                            // 查看剩余的过期时间
6,键的数据结构类型:
type key //type hello     //返回string,键不存在返回none

csredis分布式缓存 redis 分布式缓存_redis_11

csredis分布式缓存 redis 分布式缓存_redis_12

六、Redis持久化

 作用:


RDB:

RDB持久化把当前进程数据生成快照(.rdb)文件保存到硬盘的过程,有手动触发和自动触发手动触发有save和bgsave两命令


Save:

由于 save 命令是同步命令,会占用Redis的主进程。若Redis数据非常多时,save命令执行速度会非常慢,阻塞所有客户端的请求。

因此很少在生产环境直接使用SAVE 命令,可以使用BGSAVE 命令代替。如果在BGSAVE命令的保存数据的子进程发生错误的时,用 SAVE命令保存最新的数据是最后的手段。

 

csredis分布式缓存 redis 分布式缓存_redis数据结构_13

Bgsave:

bgsave 命令执行一个异步操作,以RDB文件的方式保存所有数据的快照。

127.0.0.1:6379> bgsave Background saving started

 

csredis分布式缓存 redis 分布式缓存_分布式缓存_14

save 与 bgsave 对比

命令

save

bgsave

IO类型

同步

异步

阻塞?

是(阻塞发生在fock(),通常非常快)

复杂度

O(n)

O(n)

优点

不会消耗额外的内存

不阻塞客户端命令

缺点

阻塞客户端命令

需要fock子进程,消耗内存

操作:

命令:config set dir /usr/local  //设置rdb文件保存路径



RDB优点:

一、压缩后的二进制文,适用于备份、全量复制,用于灾难恢复



二、与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些。

RDB缺点:



做,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能。

csredis分布式缓存 redis 分布式缓存_redis_15

csredis分布式缓存 redis 分布式缓存_csredis分布式缓存_16

AOF(存命令)

快照功能(RDB)并不是非常耐久(durable): 如果 Redis 因为某些原因而造成故障停机, 那么服务器将丢失最近写入、且仍未保存到快照中的那些数据。 从 1.1 版本开始, Redis 增加了一种完全耐久的持久化方式: AOF 持久化。

打开AOF后, 每当 Redis 执行一个改变数据集的命令时(比如 SET), 这个命令就会被追加到 AOF 文件的末尾。这样的话, 当 Redis 重新启时, 程序就可以通过重新执行 AOF 文件中的命令来达到重建数据集的目的。

csredis分布式缓存 redis 分布式缓存_redis持久化_17

操作: 

开启:redis.conf设置:appendonly yes  (默认不开启,为no)


 

csredis分布式缓存 redis 分布式缓存_redis持久化_18

三种策略always、everysecno对比


命令

优点

缺点

描述

always

不丢失数据

IO开销大,一般SATA磁盘只有几百TPS

每次有新命令追加到 AOF 文件时就执行一次 fsync :非常慢,也非常安全。

everysec

每秒进行与fsync,最多丢失1秒数据

可能丢失1秒数据

每秒 fsync 一次:足够快(和使用 RDB 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。

推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性。

 

no

不用管

不可控

从不 fsync :将数据交给操作系统来处理,由操作系统来决定什么时候同步数据。更快,也更不安全的选择。


 

csredis分布式缓存 redis 分布式缓存_分布式缓存_19

AOF的优点

1、使用AOF 会让你的Redis更加耐久: 你可以使用不同的fsync策略:无fsync,每秒fsync,每次写的时候fsync。使用默认的每秒fsync策略,Redis的性能依然很好(fsync是由后台线程进行处理的,主线程会尽力处理客户端请求),一旦出现故障,你最多丢失1秒的数据。


2、AOF文件是一个只进行追加的日志文件,即使由于某些原因(磁盘空间已满,写的过程中宕机等等)未执行完整的写入命令,你也也可使用redis-check-aof工具修复这些问题。


3、Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。


3、AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也非常简单: 举个例子, 如果你不小心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要停止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就可以将数据集恢复到 FLUSHALL 执行之前的状态。

AOF的缺点:

1、对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。

2、根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)

RDB 和 AOF 对比

-

RDB

AOF

启动优先级

体积

恢复速度

数据安全性

丢数据

根据策略决定