缓存学习---redis

简介

官网公布数据:读的速度是110000次/s,写的速度是81000次/s

redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。(来自百度百科)

同类比较 memcache和redis

懒得自己写了,拷贝自’真实的归宿’博客
- 性能方面:没有必要过多的关心性能,因为二者的性能都已经足够高了。由于Redis只使用单核,而Memcached可以使用多核,所以在比较上,平均每一个核上Redis在存储小数据时比Memcached性能更高。而在100k以上的数据中,Memcached性能要高于Redis,虽然Redis最近也在存储大数据的性能上进行优化,但是比起Memcached,还是稍有逊色。说了这么多,结论是,无论你使用哪一个,每秒处理请求的次数都不会成为瓶颈。(比如瓶颈可能会在网卡)
- 内存使用效率:使用简单的key-value存储的话,Memcached的内存利用率更高,而如果Redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于Memcached。当然,这和你的应用场景和数据特性有关。
- 数据持久化:如果你对数据持久化和数据同步有所要求,那么推荐你选择Redis,因为这两个特性Memcached都不具备。即使你只是希望在升级或者重启系统后缓存数据不会丢失,选择Redis也是明智的。
- 数据结构:当然,最后还得说到你的具体应用需求。Redis相比Memcached来说,拥有更多的数据结构和并支持更丰富的数据操作,通常在Memcached里,你需要将数据拿到客户端来进行类似的修改再set回去。这大大增加了网络IO的次数和数据体积。在Redis中,这些复杂的操作通常和一般的GET/SET一样高效。所以,如果你需要缓存能够支持更复杂的结构和操作,那么Redis会是不错的选择。
- 网络IO模型方面:Memcached是多线程,分为监听线程、worker线程,引入锁,带来了性能损耗。Redis使用单线程的IO复用模型,将速度优势发挥到最大,也提供了较简单的计算功能
- 内存管理方面:Memcached使用预分配的内存池的方式,带来一定程度的空间浪费,并且在内存仍然有很大空间时,新的数据也可能会被剔除,而Redis使用现场申请内存的方式来存储数据,不会剔除任何非临时数据 Redis更适合作为存储而不是cache
- 数据的一致性方面:Memcached提供了cas命令来保证.而Redis提供了事务的功能,可以保证一串命令的原子性,中间不会被任何操作打断

redis数据类型

redis有5种数据类型:string(字符串)、hash(哈希表)、list(链表)、set(集合)、zset(有序集合)
redis编码方式:raw(简单动态字符串)、int(long整数)、ht(字典)、linkedlist(双端链表)、ziplist(压缩链表)、skiplist(跳跃表)、intset(整数集合)

类型编码方式对应关系

缓存学习---redis_第1张图片

简单动态字符串

缓存学习---redis_第2张图片

链表

缓存学习---redis_第3张图片

字典

缓存学习---redis_第4张图片
redis字典的使用哈希表最为底层实现,如图
缓存学习---redis_第5张图片

redis数据库键空间是的一个字典保存了数据库所有键值对

键是数据库的键,为字符串对象
值是数据库的值,可能是5种数据类型的一种
缓存学习---redis_第6张图片

事物

redis事物包含三个阶段:

  • 事物开始 命令multi
  • 命令入队 事物队列先进先出(FIFO)
  • 事物执行 命令exec
    redis的事物不能回滚,如三条命令1、2、3,顺新执行,当2出现问题是,1不会被回滚

持久化

快照rdb

默认使用的持久化方式
命令 SAVE BGSAVE
SAVE会阻塞服务器进程,直到rdb文件创建完成
BGSAVE不会阻塞,会派出一个线程实现

缓存学习---redis_第7张图片

redis默认使用BGSAVE方式,配置文件指定执行间隔
save 900 1 #900秒内有一次变更
save 300 10 #300秒内有10次变更
save 60 10000 #60秒内有10000次变更

启动服务器自动导入rdb文件,若有aof文件优先导入aof文件

aof(append only file)持久化

通过保存redis服务器所执行的写命令来记录数据库状态
aof持久化分为:命令追加、文件写入文件同步

  • 命令追加:服务器执行一条写命令后,会以协议格式(纯文本格式)将命令追加到aof_buf缓冲区末尾
  • 文件写入文件同步: 通过ServerCron定时函数,调用flushAppendOnlyFile函数确定是否将缓冲区内容写入aof文件

缓存学习---redis_第8张图片

aof文件载入还原

创建一个不带网络链接的虚拟客户端,执行aof文件中命令
注:redis命令只能在客户端上下文执行

aof重写

为什么需要重写

aof命令追加会导致aof文件越来越大,影响性能

原理
  • redis服务器是单线程,为防止aof重写时阻塞redis主线程,redis将aof重写放到子进程执行,这样不会影响redis服务器处理命令请求
  • aof重写,创建一个新的aof文件,从redis数据库读取当期值,用一条命令去记录键值对
  • 在aof重写进行中,服务器还在处理请求,为防止数据不一致,增加一个aof重写缓冲区,等待子进程处理完成是,向服务器发送信号,这时会阻塞服务器,将aof重写缓冲区内容写入新的aof文件,完成后修改文件名替换原来aof文件,完成aof重写
触发时机

触发AOF后台重写的条件

1、AOF重写可以由用户通过调用BGREWRITEAOF手动触发。

2、服务器在AOF功能开启的情况下,会维持以下三个变量:

  • 记录当前AOF文件大小的变量aof_current_size。
  • 记录最后一次AOF重写之后,AOF文件大小的变量aof_rewrite_base_size。
  • 增长百分比变量aof_rewrite_perc。

每次当serverCron(服务器常规操作)函数执行时,它会检查以下条件是否全部满足,如果全部满足的话,就触发自动的AOF重写操作:
1)、没有BGSAVE命令(RDB持久化)/AOF持久化在执行;
2)、没有BGREWRITEAOF在进行;
3)、当前AOF文件大小要大于server.aof_rewrite_min_size(默认为1MB),或者在redis.conf配置了auto-aof-rewrite-min-size大小;
4)、当前AOF文件大小和最后一次重写后的大小之间的比率等于或者等于指定的增长百分比(在配置文件设置了auto-aof-rewrite-percentage参数,不设置默认为100%)

如果前面三个条件都满足,并且当前AOF文件大小比最后一次AOF重写时的大小要大于指定的百分比,那么触发自动AOF重写。

复制

slaveof命令让一个服务器复制另一个服务器

  • 被复制的服务器称为主服务器(master)
  • 进行复制的服务器称为从服务器(slave)

redis复制功能分为同步、命令传播

同步实现

缓存学习---redis_第9张图片

命令传播

主从服务器达到一致以后,主服务器执行写命令后,会将命令发送给从服务器,确保状态一致
注:老版的SYNC复制,不能解决断线重连问题(断线重连后会整个复制一次,性能很低),新版复制使用PSYNC增加部分复制功能,通过偏移量实现(详情见:redis设计与实现第二版)

哨兵

是redis高可用性的一种解决方案

实现

由一个或多个sentinel实例组成sentinel系统,监视任意多个主服务器及主服务器的从服务器,当主服务器下线时将其从服务器升级为新的主服务器,继续处理命令(详情见:redis设计与实现第二版)

集群

redis使用集群后,就没有那个数据库的概念了,集群将整个数据库分为16384个槽(slot),每个节点管理0-16384个槽,当所有槽都有节点处理的时候集群处于上线状态,否则集群是下线状态

计算key属于那一个槽算法

CRC16(key) & 16383 CRC16(key)计算CRC-16校验和, & 16383 计算出一个介于0-16383的整数做为key的槽号

发布订阅

没有使用过(详情见:redis设计与实现第二版)

常用命令

redis命令

keys key*
ttl key
type key
del key
exists key
info 打印redis服务器信息
flushdb 删除当前db的所有key
flushall 删除所有db的所有key

字符串、hash、list、set、zset有序集合等

命令可以参考https://www.cnblogs.com/luoxn28/p/5790313.html

redis使用场景

普通字符串缓存(如:token、用户id、session等)

计数器

排名

假定有一个实时的竞技场评分,在玩家结束操作后打分,并动态显示玩家的排行榜
zadd rank 100 biki 87 zhibin 72 ming 64 fen 98 cat
(integer) 5
显示得分最高的前三名玩家
ZREVRANGE rank 0 2 WITHSCORES
1) “biki”
2) 100.0
3) “cat”
4) 98.0
5) “zhibin”
6) 87.0

分布式锁

通过setnx命令实现
成功设置值返回1,否则返回0

127.0.0.1:6379> setnx test value
(integer) 1
127.0.0.1:6379> setnx test value
(integer) 0
127.0.0.1:6379> 

注意:使用redis实现分布式锁,需要设置过期时间,防止产生死锁

参考资料
官网https://redis.io/
redis设计与实现(第二版)
http://blog.csdn.net/hguisu/article/details/8836819
https://baike.baidu.com/item/Redis/6549233?fr=aladdin

你可能感兴趣的:(缓存学习,redis)