详解Redis基

2018-11-22 SKY 互联网
浏览

Redis基础、高级特性与性能调优

本文将从Redis的基本特性入手,通过讲述Redis的数据结构和主要命令对Redis的基本能力进行直观介绍。之后概览Redis提供的高级能力,并在部署、维护、性能调优等多个方面进行更深入的介绍和指导。

本文适合使用Redis的普通开发人员,以及对Redis进行选型、架构设计和性能调优的架构设计人员。

目录

概述

Redis的数据结构和相关常用命令

数据持久化

内存管理与数据淘汰机制

Pipelining

事务与Scripting

Redis性能调优

主从复制与集群分片

Redis Java客户端的选择

概述

Redis是一个开源的,基于内存的结构化数据存储媒介,可以作为数据库、缓存服务或消息服务使用。

Redis支持多种数据结构,包括字符串、哈希表、链表、集合、有序集合、位图、Hyperloglogs等。

Redis具备LRU淘汰、事务实现、以及不同级别的硬盘持久化等能力,并且支持副本集和通过Redis Sentinel实现的高可用方案,同时还支持通过Redis Cluster实现的数据自动分片能力。

Redis的主要功能都基于单线程模型实现,也就是说Redis使用一个线程来服务所有的客户端请求,同时Redis采用了非阻塞式IO,并精细地优化各种命令的算法时间复杂度,这些信息意味着:

Redis是线程安全的(因为只有一个线程),其所有操作都是原子的,不会因并发产生数据异常

Redis的速度非常快(因为使用非阻塞式IO,且大部分命令的算法时间复杂度都是O(1))

使用高耗时的Redis命令是很危险的,会占用唯一的一个线程的大量处理时间,导致所有的请求都被拖慢。(例如时间复杂度为O(N)的KEYS命令,严格禁止在生产环境中使用)

Redis的数据结构和相关常用命令

本节中将介绍Redis支持的主要数据结构,以及相关的常用Redis命令。本节只对Redis命令进行扼要的介绍,且只列出了较常用的命令。如果想要了解完整的Redis命令集,或了解某个命令的详细使用方法,请参考官方文档:

https://redis.io/commands

Key

Redis采用Key-Value型的基本数据结构,任何二进制序列都可以作为Redis的Key使用(例如普通的字符串或一张JPEG图片)

关于Key的一些注意事项:

不要使用过长的Key。例如使用一个1024字节的key就不是一个好主意,不仅会消耗更多的内存,还会导致查找的效率降低

Key短到缺失了可读性也是不好的,例如”u1000flw”比起”user:1000:followers”来说,节省了寥寥的存储空间,却引发了可读性和可维护性上的麻烦

最好使用统一的规范来设计Key,比如”object-type:id:attr”,以这一规范设计出的Key可能是”user:1000″或”comment:1234:reply-to”

Redis允许的最大Key长度是512MB(对Value的长度限制也是512MB)

String

String是Redis的基础数据类型,Redis没有Int、Float、Boolean等数据类型的概念,所有的基本类型在Redis中都以String体现。

与String相关的常用命令:

SET:为一个key设置value,可以配合EX/PX参数指定key的有效期,通过NX/XX参数针对key是否存在的情况进行区别操作,时间复杂度O(1)

GET:获取某个key对应的value,时间复杂度O(1)

GETSET:为一个key设置value,并返回该key的原value,时间复杂度O(1)

MSET:为多个key设置value,时间复杂度O(N)

MSETNX:同MSET,如果指定的key中有任意一个已存在,则不进行任何操作,时间复杂度O(N)

MGET:获取多个key对应的value,时间复杂度O(N)

上文提到过,Redis的基本数据类型只有String,但Redis可以把String作为整型或浮点型数字来使用,主要体现在INCR、DECR类的命令上:

INCR:将key对应的value值自增1,并返回自增后的值。只对可以转换为整型的String数据起作用。时间复杂度O(1)

INCRBY:将key对应的value值自增指定的整型数值,并返回自增后的值。只对可以转换为整型的String数据起作用。时间复杂度O(1)

DECR/DECRBY:同INCR/INCRBY,自增改为自减。

INCR/DECR系列命令要求操作的value类型为String,并可以转换为64位带符号的整型数字,否则会返回错误。

也就是说,进行INCR/DECR系列命令的value,必须在[-2^63 ~ 2^63 – 1]范围内。

前文提到过,Redis采用单线程模型,天然是线程安全的,这使得INCR/DECR命令可以非常便利的实现高并发场景下的精确控制。

例1:库存控制

在高并发场景下实现库存余量的精准校验,确保不出现超卖的情况。

设置库存总量:

SET inv:remain "100" 

库存扣减+余量校验:

DECR inv:remain 

当DECR命令返回值大于等于0时,说明库存余量校验通过,如果返回小于0的值,则说明库存已耗尽。

假设同时有300个并发请求进行库存扣减,Redis能够确保这300个请求分别得到99到-200的返回值,每个请求得到的返回值都是唯一的,绝对不会找出现两个请求得到一样的返回值的情况。

例2:自增序列生成

实现类似于RDBMS的Sequence功能,生成一系列唯一的序列号

设置序列起始值:

SET sequence "10000" 

获取一个序列值:

INCR sequence 

直接将返回值作为序列使用即可。

获取一批(如100个)序列值:

INCRBY sequence 100 

假设返回值为N,那么[N – 99 ~ N]的数值都是可用的序列值。

当多个客户端同时向Redis申请自增序列时,Redis能够确保每个客户端得到的序列值或序列范围都是全局唯一的,绝对不会出现不同客户端得到了重复的序列值的情况。

List