redis

2019-02-22  本文已影响0人  一斗

一、简介

使用场景

Redis适合存贮数据规模不太大,热数据。

单线程也快

  1. 纯内存访问,内存的响应时长约为100纳秒,这是Redis达到每秒万级别访问的基础
  2. 非阻塞I/O,Redis使用epoll作为I/O多路复用技术的实现,再加上Redis自身的事件处理模型将epoll中的连接、读写、关闭都转换为事件,不在网络I/O上浪费过多时间
  3. 单线程避免了线程切换和竞态产生的消耗

二、数据类型

常用数据类型有string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合)。

这些数据结构都是Redis对外的数据结构,实际上每种数据结构都有自己底层的内部编码实现,而且是多种实现,且随Redis版本迭代会有变化。这样设计好处,一是内部编码改进后对外部无影响,二是多种内部编码可以在不同场景下发挥各自的优势。


对外数据结构.PNG
内部编码实现.PNG
object encoding key

返回内部编码实现

1、字符串

优先键都是字符串类型,而且其他几种数据结构都是再字符串基础上构建的。

字符串类型的值可以是字符串(简单的字符串,复杂的字符串如JSON、XML)、数字(整数、浮点数),甚至是二进制(图片、音频、视频),但是值最大不能超过512MB

命令

1、设置值

set key value

对同一个键多次设置会覆盖旧值

setnx key value

只有该键不存在才能设置成功。由于Redis单线程,如果有多个客户端同时执行setnx,只有一个能成功,setnx可以作为分布式锁的一种实现方案。
2、获取值

get key

不存在返回nil
3、批量设置值

mset key value [key value ...]

4、批量获取值

mget key [key ...]

批量操作可以提高效率


多次get.PNG
批量get.PNG

Redis可以支撑每秒数万的读写操作,是指Redis服务端的处理能力,而网络可能成为性能瓶颈。
5、计数

incr key

自增1,返回自增后的值,键不存在当作0自增,返回1

decr key  // 自减
incrby key increment  // 自增指定数字
decrby key increment  // 自减指定数字
incrbyfloat key increment  // 自增浮点数

内部编码

2、哈希

Redis中的哈希类型是指键值对里的值也是键值对类型,形如value={{field1, value1}, ...{fielNd, valueN}}

命令

1、设置值

hset key field value

hsetnx类似setnx,但作用域由键变成field

2、获取值

hget key value

3、批量设置获取

hmset key field value [field value ...]
hmget key field [field ...]

4、删除field

hdel key field [field ...]

5、计算field个数

hlen key

6、判断field存在

hexists key field

7、获取所有field

hkeys key

8、获取所有值

hvals key

9、field值自增

hincrby key field increment
hincrbyfloat key field increment

内部编码

3、列表

列表类型是用来存储多个有序的字符串的,一个列表最多存储232-1个元素,可以两端插入和弹出元素,故可充当栈和队列。

list操作.PNG

命令

1、添加元素

rpush key value [value ...]  // 从右边插入
lpush key value [value ...]  // 从左边插入

2、获取列表长度

llen key

3、索引查值

索引从0开始计算

lrange key start end  // start至end的索引范围内的值,包括end
lindex key index  // index处的值

4、删除元素

rpop key  // 从右边弹出
lpop key  // 从左边弹出

5、阻塞弹出

brpop key [key ...] timeout
blpop key [key ...] timeout

内部编码

使用场景

4、集合

一个集合最多存储232-1个元素,集合中元素是不重复的,无序的。Redis除了支持集合内的增删改查,同时还支持多个集合取交集、并集、差集。

命令

1、添加元素

sadd key element [element ...]

返回添加成功元素个数

2、删除元素

srem key element [element ...]

返回删除成功元素个数

3、计算元素个数

scard key

直接内部用于统计数量的变量的值,时间复杂度为0(1)

4、判断元素是否存在

sismember key element

存在返回1,反之0

5、随机返回指定个数元素

srandmember key [count]

count是可选参数,不写则默认为1

6、随机弹出一个元素

spop key

返回弹出的元素,集合不存在返回nil

7、获取所有元素

smembers key

元素过多可能阻塞Redis,慎用

集合间的操作

1、交集

sinter key [key ...]

2、并集

sunion key [key ...]

3、差集

sdiff key [key ...]
集合间操作.PNG

集合间的运算比较耗时,所以Redis提供了三个命令(原命令+store)将集合间的交集、并集、差集保存在destination key中。

sinterstore destination key [key ...]
sunionstore destination key [key ...]
sdiffstore destination key [key ...]

内部编码

5、有序集合

有序集合的元素也不能重复,同时它给每个元素设置一个分数(score)作为排序的依据,分数可以有重复。有序集合提供了获取指定分数和元素范围查询、计算成员排名等功能。


有序集合.PNG

列表、集合和有序集合三者异同点


三者异同.PNG

命令

1、添加成员

zadd key score member [score member ...]

返回添加成功元素个数。有序集合相比集合提供了排序,但也产生了代价,zadd的时间复杂度为O(log(n)),sadd为O(1)

2、计算成员个数

zcard key

时间复杂度为O(1)

3、计算某个成员的分数

zscore key member

返回分数,成员不存在返回nil

4、计算成员的排名

zrank key member       // 分数从低到高
zrevrank key member   // 分数从高到低

排名从0开始计算,成员不存在返回nil

5、删除成员

zrem key member [member ...]

返回删除成功元素个数

6、增加成员的分数

zincrby key increment member

返回增加后的分数,increment可以为负数

7、返回指定排名范围的成员

zrange key start end [withscores]
zrevrange key start end [withscores]

withscores同时返回成员的分数

8、返回指定分数范围的成员

zrangebyscore key min max [withscores] [limit offset count]
zrevrangebyscore key max min [withscores] [limit offset count]

limit offset count选项可以限制输出的起始位置和个数。同时min和max还支持开区间(小括号)和闭区间(中括号),-inf和+inf分别代表无限小和无限大。

9、返回指定分数范围成员个数

zcount key min max

10、删除指定排名内的升序元素

zremrangebyrank key start end

11、删除指定分数范围的成员

zremrangebyscore key min max

内部编码

键管理

1、查看所有键

keys *

keys命令会遍历所有键,时间复杂度为O(n),当Redis保存了大量键时,线上环境禁止使用。

2、键总数

dbsize

dbsize命令直接获取Redis内置的键总数变量,时间复杂度为O(n)

3、检查键存在

exists key

存在返回1,反之0

4、删除键

del key [key...]

可一次删除多个键,返回成功删除键个数,删除一个不存在的键返回0

5、键过期

expire key seconds   // 键在seconds秒后过期
expireat key timestamp   // 键在秒级别时间戳后过期

persist key   // 清除过期设置

键要先存在才能设置其过期时间,如果seconds为负,则直接删除键

ttl key

ttl返回键剩余时间,返回以下情况

6、键所对于值的数据结构类型

type key

可返回string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合),键不存在返回none

7、键重命名

rename key newkey

如果newkey已经存在,则newkey的值会被覆盖,可以使用renamenx命令,在newkey不存在时才重命名成功。由于重命名会执行del命令删除旧键,如果键对应的值比较大,会阻塞Redis

8、随机返回一个键

randomkey

三、持久化

RDB

Redis会定期保存数据快照至一个rbd文件中,并在启动时自动加载rdb文件,恢复之前保存的数据。可以在配置文件中配置Redis进行快照保存的时机:

save [seconds] [changes]

意为在[seconds]秒内如果发生了[changes]次数据修改,则进行一次RDB快照保存,例如

save 60 100

会让Redis每60秒检查一次数据变更情况,如果发生了100次或以上的数据变更,则进行RDB快照保存。可以配置多条save指令,让Redis执行多级的快照保存策略。Redis默认开启RDB快照。

也可以通过BGSAVE命令手动触发RDB快照保存。

RDB优点

RDB缺点

AOF

采用AOF持久方式时,Redis会把每一个写请求都记录在一个日志文件里。在Redis重启时,会把AOF文件中记录的所有写操作顺序执行一遍,确保数据恢复到最新。AOF默认是关闭的,如要开启,进行如下配置:

appendonly yes

AOF提供了三种fsync配置,always/everysec/no,通过配置项[appendfsync]指定:

随着AOF不断地记录写操作日志,因为所有的操作都会记录,所以必定会出现一些无用的日志。大量无用的日志会让AOF文件过大,也会让数据恢复的时间过长。不过Redis提供了AOF rewrite功能,可以重写AOF文件,只保留能够把数据恢复到最新状态的最小写操作集。

AOF rewrite可以通过BGREWRITEAOF命令触发,也可以配置Redis定期自动进行:

auto-aof-rewrite-percentage 100auto-aof-rewrite-min-size 64mb

上面两行配置的含义是,Redis在每次AOF rewrite时,会记录完成rewrite后的AOF日志大小,当AOF日志大小在该基础上增长了100%后,自动进行AOF rewrite。同时如果增长的大小没有达到64mb,则不会进行rewrite。

AOF优点

AOF缺点

建议策略

Redis的数据持久化工作本身就会带来延迟,需要根据数据的安全级别和性能要求制定合理的持久化策略:

Redis在fork子进程时需要将内存分页表拷贝至子进程,以占用了24GB内存的Redis实例为例,共需要拷贝24GB / 4kB * 8 = 48MB的数据。在使用单Xeon 2.27Ghz的物理机上,这一fork操作耗时216ms。

可以通过INFO命令返回的latest_fork_usec字段查看上一次fork操作的耗时(微秒)

上一篇下一篇

猜你喜欢

热点阅读