Redis 阅读笔记 基础

82 阅读6分钟

列举Redis基础知识,参考 《edis开发与运维 - 付磊 & 张益军》

redis的三个基本特征:

  • 内存数据库
  • 单进程高并发
  • I/O优化

这三件事是高度相关的。

之所以作为单进程数据库,还能支撑高并发,就是因为它是内存数据库。 操作的响应速度远快于硬盘。 不需要多个进程切换来面对硬盘读写。在本机的速度问题解决之后,重要的就是网络,也就是I/O优化, Redis使用epoll实现,不在网络上浪费时间。在I/O问题解决之后,单线程的一个大优势就是不用做线程切换。

说了这么多好处,有没有问题? 最严重的问题就是如果一个命令执行时间过长,后面的命令就会阻塞,严重影响并发。

常用命令

set (ex:在key已经存在的时候生效,同update,nx:在key不存在的时候生效,同insert)

get

multil操作: 意义是减少I/O.

数据结构

类型简介特性场景
string(字符串)二进制安全可以包含任何数据,比如jpg图片或者序列化对象---
Hash(字典)键值对集合,即编程语言中的map类型适合存储对象,并且可以像数据库中的update一个属性一样只修改某一项属性值存储、读取、修改用户属性
List(列表)链表(双向链表)增删快,提供了操作某一元素的api最新消息排行;消息队列
set(集合)hash表实现,元素不重复添加、删除、查找的复杂度都是O(1),提供了求交集、并集、差集的操作共同好友;利用唯一性,统计访问网站的所有Ip
sorted set(有序集合)将set中的元素增加一个权重参数score,元素按score有序排列数据插入集合时,已经进行了天然排序排行榜;带权重的消息队列

编码方式

编码方式是说这些数据结构是怎么存储的。 实际上能有的存储方式并不多, 不外乎连续存储(数组),链表, 哈希, 图(一般是树)。 每个方式都各有优缺点。 Redis的优势是随着数据的变化(单个数据大小,数据量),会自动地切换编码方式,达到比较好的存储效果。

zipList: 紧凑的连续的存储,能看到大多数数据结构在小而少的时候都使用ziplist

hashtable: hash多起来以后使用,目的是优化读写到O(1)

string

set key value

最常见的形式

哈希

结构:key --> field

field是一组哈希k:v值

  • 命令:在常用命令前+h
hset
hexist

使用场景:对标关系型数据库

列表:list

  • 类似python的list, 有序,可以使用下标随机访问。也可以lpush,lpop,rpush,rpop作为队列使用
  • 一个列表最多存贮2^32-1个元素

命令

rpush key value
lpush key value
lrange key start end (包含end)

集合

无序,唯一

命令

sadd key element

使用场景

tag

有序集合

相比集合,加入了一个score变量,可以依据score变量排序

使用场景:排行榜系统

HyperLogLog

Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。

在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。 代价是一定程度上不准确。

常见功能

慢查询

slowlog-log-slower-than = 正数

记录所有执行时间比这个大的命令

Pipeline

打包命令一次性发给server,主要解决网络延迟问题

lua事务

之所以要有lua事务,是因为原生事务不支持原子性。 单条命令当然是原子性的(单线程保证),但是多条命令中如果有一条出错,数据库不会回滚。

使用lua脚本,Redis保证脚本执行是原子性的。

  • 应用: 使用Redis做分布式锁的时候, 解锁的两步操作要写lua脚本。

持久化

RDB

压缩后写入DISK,需要阻塞Redis。

优劣

  • 优势: 由于压缩,占用DISK的Redis体积比占用内存小。

  • 劣势: 持久化总是需要阻塞一段时间,不能做到每秒都持久化。

操作

save: 本进程,阻塞数据库进行持久化,已经废弃

bdsave:fork子进程持久化,只有fork的过程会阻塞。

fork过程复制父进程页表, redis的页表经常不小,导致fork过程慢

写时复制问题:如果在fork过程中, 新的指令写redis, (父进程),此时触发写时复制,操作系统需要重新为子进程分配物理地址,很可能造成长时间的阻塞。

AOF: append only file

原理:保存Redis建立以来的每一句命令

每次持久化的时候append在AOF缓存之后,AOF缓存依据配置写入文件系统。

优劣

  • 优势:每秒持久化
  • 劣势:大

操作

  • AOF缓冲区同步到文件系统的策略:
配置效果
always每次写入缓冲区之后都调用fsync,fsync阻塞到磁盘写入完成。非常影响高并发
everysec每次写入缓冲区之后都调用write,操作系统什么时候sync不知道,有专门的线程每秒调用一次fsync,常用
no每次写入缓冲区之后都调用write,操作系统什么时候sync随它去
  • 重写

手动或者自动,重写的时候剔除冗余部分。 AOF文件变小。

超时文件, 无效命令,合并命令

  • everysec阻塞:

    虽然是另外一个线程fsync,但是主线程会检查上次sync时间,大于2秒,主线程会阻塞

复制

复制是集群化布置的核心功能。

通过slaveof命令指定主从关系,一个主可以有多个从。

  • 复制原理

    • 全量复制: 发RDB,造成网络和硬件压力。
    • 部分复制:发AOF
  • 心跳:主从之间分别伪装成client定时发送Ping-Pong以确认连接有效

  • 异步复制:命令在主上完成后就返回,不在乎主从同步

  • 应用:读写分离:因为应用里读远远多,可以把读分布到从数据库里

    • 读只能在主数据库里
    • 异步同步延迟,原则上无法避免,可以使用monitor防止偏移量过大