1.Redis基础知识

一、概述

1.1 Redis是什么

Redis全称是Remote Dictionary Server,是一种基于键值对(key-value)的NoSQL数据库,与很多键值对数据库不同的是,Redis中的值可以是由string、hash、list、set、zset、Bitmaps、HyperLogLog、GEO等多种数据结构和算法组成,因此Redis可以满足很多的应用场景,而且因为Redis会将所有数据都存放在内存中,所以它的读写性能非常惊人。不仅如此,Redis还可以将内存的数据利用快照和日志的形式保存到硬盘上,这样在发生类似断电或者机器故障的时候,内存中的数据不会丢失。Redis提供了许多在数据库中很常见的功能,例如复制、可调的持久性级别、集群和高可用性。

1.2 特性

  1. 速度快

    正常情况下,Redis执行命令的速度非常快,官方给出的数字是读写性能可以达到10万/秒,但是这个肯定是取决于机器的性能。我们这里主要关注Redis为什么如此之快:

    • Redis所有数据都是存放在内存中的,这是最主要的原因。
    • Redis是用C语言实现的,距离操作系统更近,执行速度相对会更快。
    • Redis使用了单线程架构,预防了多线程可能产生的竞争问题
    • 作者对于Redis源代码的精打细磨。
  2. 基于KV的数据结构服务器

    与很多kv数据库不同的是,Redis中的值不仅可以是字符串,而且还可以是具体的数据结构。

  3. 丰富的功能

    除了5种数据结构,Redis还提供了许多额外的功能:

    • 提供了key过期的功能,可以用来实现缓存
    • 提供了发布订阅功能,可以用来实现消息系统。
    • 支持Lua脚本功能,可以利用Lua创造出新的Redis命令
    • 提供了简单的事务功能,能在一定程度上保证事务特性(注意:这里只能在一定程度上保证事务性,不能像关系型数据库那样实现ACID)
    • 提供了流水线功能,这样客户端能将一批命令一次性传到Redis,减少了网络的开销。
  4. 简单稳定

    Redis的简单主要体现在三个方面:

    • Redis源码很少,早起版本的代码只有2万行左右,3.0版本以后由于添加了集群特性,代码增至5万行左右,相对于很多NoSQL数据库来说代码量要少很多。
    • Redis使用单线程模型,这样不仅使得Redis服务端处理模型变得简单,而且也使得客户端开发变得简单。
    • Redis不需要依赖于操作系统的类库(例如Memcache需要依赖libevent这样的类库),Redis自己实现了事件处理的相关功能
  5. 客户端语言多

    Redis提供了简单的TCP通信协议,很多编程语言可以很方便地接入到Redis,并且由于Redis受到社区和各大公司的广泛认可,所以支持Redis的客户端语言也非常多,几乎覆盖了主流的编程语言。

  6. 持久化

    通常,将数据放在内存中是不安全的,一旦发生断电或者机器故障,重要的数据可能就会丢失,因此Redis提供了两种持久化方式:RDB和AOF,即可以使用两种策略将数据保存到磁盘中。

  7. 主从复制

    Redis提供了复制功能,实现了多个相同数据的Redis副本,复制功能是分布式Redis的基础。

  8. 高可用和分布式

    Redis从2.8版本正式提供了高可用的Redis Sentinel,它能够保证Redis节点的故障发现和故障自动转移。Redis从3.0版本正式提供了分布式实现Redis Cluster,它是Redis真正的分布式实现,提供了高可用、读写和容量的扩展性。

二、API的理解和使用

2.1 String

2.2 List

2.3 Set

2.4 Zset

2.5 Hash

2.6 HyperLogLog

2.7 Bitmap

2.8 Geo

2.9 Stream

2.10 Bitfield

2.11 键管理

三、Pipeline

3.1 Pipeline概念

Redis客户端执行一条命令分为如下四个过程:
1. 发送命令
2. 命令排队
3. 命令执行
4. 返回结果

其中1和4称为Round Trip Time(RTT,往返时间)

Redis提供了批量操作命令(如mget、mset等),有效地节约RTT,但大部分命令是不支持批量操作的,例如要执行n次hgetall命令,并没有mhgetall命令存在,需要消耗n次RTT。Redis的客户端和服务端可能部署在不同的机器上。例如客户端在北京,Redis服务端在上海,两地直线距离约为1300公里,光在真空中传输速度为每秒30万公里,这里假设光纤为光速的2/3,那么
一次 R T T 时间 = 1300 ∗ 2 / ( 300000 ∗ 2 / 3 ) = 13 毫秒 一次RTT时间=1300 * 2 / (300000 * 2 / 3)=13毫秒 一次RTT时间=13002/(3000002/3)=13毫秒
那么客户端在1秒内大约只能执行80次左右的命令,这个和Redis的高并发高吞吐特性背道而驰。

Pipeline(流水线)机制能改善上面这类问题,它能将一组Redis命令进行组装,通过一次RTT传输给Redis,再将这组Redis的执行结果按顺序返回给客户端

Pipeline并不是什么新的技术,很多技术上都用过而且RTT在不同的网络环境下会有不同,例如同机房和同机器会比较快,跨机房跨地区会比较慢。Redis命令真正执行的时间通常在微妙级别,所以才会有Redis性能瓶颈时网络这样的说法

3.2 原生批量命令与Pipeline对比

可以使用Pipeline模拟出批量操作的效果,但是在使用时要注意它与原生批量命令的区别,具体包含一下几点:

  • 原生批量命令是原子的,Pipeline是非原子的
  • 原生批量命令是一个命令对应多个key,Pipeline支持多个命令。
  • 原生批量命令是Redis服务端支持实现的,而Pipeline需要服务端和客户端的共同实现。

3.3 最佳实践

Pipeline虽然好用,但是每次Pipeline组装的命令个数不能没有节制,否则一次组装Pipeline数据量过大,一方面会增加客户端的等待时间,另一方面会造成一定的网络阻塞,可以将一次包含大量命令的Pipeline拆分成多次较小的Pipeline来完成。

Pipeline只能操作一个Redis实例,但是即使在分布式Redis场景中,也可以作为批量操作的重要优化手段

四、事务

在关系型数据库中,事务表示一组动作,要么全部执行,要么全部不执行。

Redis提供了简单的事务功能,将一组需要一起执行的命令放到multi和exec两个命令之间。multi命令代表事务开始,exec命令代表事务结束,它们之间的命令是原子顺序执行的

例如,下面的操作实现了用户关注相关的问题:

127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> sadd user:a:follow user:b
QUEUED
127.0.0.1:6379(TX)> sadd user:b:fans user:a
QUEUED

可以看到sadd命令此时的返回结果是QUEUED,代表命令并没有真正执行,而是暂时保存在Redis中。如果此时另一个客户端执行sismember user🅰️follow user:b,返回的结果应该为0。

127.0.0.1:6379> sismember user:a:follow user:b
(integer) 0

只有当exe执行后,用户A关注用户b的行为才算完成。

如果要停止事务的执行,可以使用discard命令代替exec即可。

如果事务中的命令出现错误,Redis的处理机制也不尽相同:

  1. 命令错误

    例如,下面操作错将set写成了sett,属于语法错误,会造成整个事务无法执行,key和counter的值未发生变化:

    127.0.0.1:6379> mget key counter
    1) "hello"
    2) "100"
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379(TX)> sett key word
    (error) ERR unknown command 'sett', with args beginning with: 'key' 'word'
    127.0.0.1:6379(TX)> incr counter
    QUEUED
    127.0.0.1:6379(TX)> exec
    (error) EXECABORT Transaction discarded because of previous errors.
    127.0.0.1:6379> mget key counter
    1) "hello"
    2) "100"
    
  2. 运行时错误

    例如用户B在添加粉丝列表时,误把sadd命令写成了zadd命令,这种就是运行时错误,因为语法时正确的:

    127.0.0.1:6379(TX)> sadd user:a:follow user:b
    QUEUED
    127.0.0.1:6379(TX)> zadd user:b:fans 1 user:a
    QUEUED
    127.0.0.1:6379(TX)> exec
    1) (integer) 0
    2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
    127.0.0.1:6379> sismember user:a:follow user:b
    (integer) 1
    

​ 可以看到Redis并不支持回滚功能,sadd user:\a:follow user:b命令已经执行成功,开发人员需要自己修复这 类问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值