0%

Redis技术分享

前言

以前做过一个有关redis的技术分享,这里将之前分享的内容做了抽减,来大概的介绍一下redis,以帮助快速入门,对redis有个概要性的了解,不会做深入的介绍。本文中代码由于是直接用以前PPT上的截图,所以没有贴源码,请谅解。

本文内容如有错误的地方,欢迎指正。

Redis是什么?

Redis是完全开源免费、遵守BSD协议的一个高性能的key-value数据库。据官方统计数据:redis读 110000次/秒,写 81000次/秒。目前已经有很多公司都在用redis,下面举几个例子:

redis-5-1

redis-5-2
redis-5-3
redis-5-4
redis-5-5

Redis的基本数据结构

Redis作为一个nosql数据库,支持五种基本的数据结构,可谓是相当丰富,能满足大部分使用场景。如下所示:

redis-5-6

虽然说redis是nosql数据库,但是实际业务场景中,我们也可以用redis实现关系型表结构,这都跟上面的五种基本数据结构是分不开的。当然,这里只针对每种数据结构的底层做了提点,并没有去深入探究;redis的底层是用C/C++实现的,足以体现其高性能;在使用中,redis其实还对其底层结构做了一次封装,封装厂特有的对象,以便于上层的操作。感兴趣的可以去浏览一下redis的源码:https://github.com/antirez/redis

安全与性能

持久化

redis支持两种持久化方式:AOF 和 RDB(SNAPSHOTTING)。

RDB持久化也俗称快照,是将redis数据库中某一时刻的数据写入硬盘,存一个副本,然后在数据库数据丢失后,执行这个快照文件即可恢复数据。RDB的核心配置如下:

1
2
3
4
save 60 1000  //60秒内有1000次更改操作则进行save
stop-writes-on-bgsave-error no //save的过程中出错是否停止
rdbcompress yes //是否对保存的文件进行压缩
dbfilename dump.rdb //定义生成的文件名

AOF持久化是将操作命令追加到aof文件的末尾,以此来达到数据备份,即数据库崩溃时,可以重新执行这个文件,来尽可能的恢复数据。AOF的核心配置如下:

1
2
3
4
5
appendonly yes  //是否追加
appendfsync everysec / always / no //追加方式:每秒写入并完成磁盘同步、总是写入并完成磁盘同步、写入不完成磁盘同步
no-appendfsync-on-rewrite no //当磁盘同步时是否进行对文件进行写入操作
auto-aof-rewrite-percentage 100 //设置当前文件夹的大小是上一次rewrite操作时文件的一倍时(即增长了100%)执行rewrite操作
auto-aof-rewrite-min-size 64m //设置文件到达一定大小后才执行rewrite操作

下面来对RDB和AOF两种持久化方式做一个对比:
redis-5-7

在实际应用中,基本上都是两种方式结合使用,这样能互相弥补缺点,尽量保证当出现数据丢失时达到最小。

事务

Redis的事务保证是通过WATCH、MULTI、EXEC、UNWATCH、DISCARD几个命令。下面给出一段代码(买卖关系)展示,主要讲几个命令综合起来运用,来探究redis事务。
这段代码很简单,当前,前提弄懂了这个几个命令的意思就更容易看懂了。
redis-5-8

当然也可以通过非事务流水线来达到事务效果,即要么全部执行,要么全部不执行。非事务流水线应用也是很广的,下面贴出一段代码:也是通过MULTI和EXEC命令包裹执行的
redis-5-9

集群

注:集群的两张图时参考其他资料借用而来的,由于看资料是很久以前,以不记得参考的资料的链接地址,故此未能贴出。
redis-5-10

  • 所有的redis节点彼此互联,内部使用二进制协议优化传输速度和带宽;
  • 节点的fail是通过集群中超过半数的节点检测失效时才生效;
  • 客户端与redis节点直连,不需要中间proxy,客户端不需要连接集群所有节点,连接集群中任何一个节点即可。
  • redis-cluster把所有的物理节点映射到[0-16383]slot上(哈希槽,由cluster负责维护)

redis-5-11
单个节点挂掉的情况:

  • 所有master参与,如果半数以上master节点与其中一个master节点通信超时认为当前master节点挂掉。

整个集群不可用情况:

  • 如果集群任意master挂掉,且当前master没有slave,集群进入fail状态,也可以理解成集群的slot映射[0- 16383]不完整时进入fail状态;
  • 如果集群超过半数以上的master挂掉,无论是否有slave集群进入fail状态。

当然在实际业务场景中,运用redis集群并不是上诉这么简单,基本上都是要加中间件以及代理,网上已有很多大佬对此提出了方案。

Redis特性

原子性

原子性大致就一句话,要么全部执行,要么全都不执行。Redis的原子性体现在:

  • Redis的所有操作都是原子性的;
  • Redis支持几个操作的原子性执行 [ MULTI和EXEC命令包裹的操作]。

键的过期时间设定

1
2
3
4
5
6
7
8
9
10
11
EXPIRE key-name seconds	设置多长时间后过期
conn.expire("key",100);

EXPIREAT key-name timestamp 设置某个特定的UNIX时间戳之后键过期
conn.expireAt("key",1508084022);

PTTL key-name 查看距过期时间还剩多少秒
conn.pttl("key");

PERSIST key-name 移除过期时间
conn.persist("key");

发布与订阅

redis-5-12
redis-5-13
发布与订阅

SUBSCRIBE channel [channel …]        订阅频道
UNSUBSCRIBE channel [channel …]    退订频道
PUBLISH channel message        向给频道发送消息
PSUBSCRIBE pattern [pattern]        订阅与给定模式相匹配的所有频道
PUNSUBSCRIBE pattern [pattern …]    退订给定的模式 

应用场景

String(可存储字符串、整数、浮点数)

  • 原子计数器 [比如网站的点击量];
  • 要对单个元素设置过期时间的情况下,只能使用String结构,不能使用哈希,因为hash的key不是redis的key;
    redis-5-14
  • 字符串 [串的追加、获取子串]
  • 二进制串的操作 [统计1的个数、按位操作等]

Hash

Hash可用于结构化存储,如下所示:
redis-5-15

List

redis的list并不是传统上的list,它类似与双端队列or双向链表。举一些常见的例子:

  • 最近联系人、最新评论、最新日志;
  • 消息队列;
  • 微博的时间线 [此方式也可用有序集合实现];
    redis-5-16

Set

这个结构的使用由于其结构的特性也很常见,比如:微博的共同关注、QQ的共同好友都可以用这种方式实现。
redis-5-17

ZSet

此数据结构的特性是:带有权重、有序性。因此,可以用来做排行榜相关业务场景(比如投票、微博的热搜)。又因为其权重的特性(权重一样时,按值来排序),可以用来做英文的自动补全。
redis-5-18

总结

Redis的基本数据结构有丰富的特性,可以在很多业务场景中使用,上面只是做一下提点,更多的需要我们在实际业务中思考去选择。笔者就喜欢用redis去解决实现一些业务场景,并且更喜欢用ZSet结构,这个结构很有魔性。

实际业务中,Redis觉大多数情况下都是用做缓存,且在缓存这方面,是可以完全替代Memcache的。

推荐资料

阿里开源 ApsaraCache :https://github.com/alibaba/ApsaraCache

资料链接:

推荐如下两本书:
redis-5-19
redis-5-20