redis高性能键值数据库技术简介

什么是redis

redis是远程字典服务(Remote Dictionary Server )的简写,是一个完全开源的高性能的Key-Value数据库,提供了丰富的数据结构如string、Hash、List、SetSortedset等等。数据是存在内存中的,同时Redis支持事务、持久化、LUA脚本、发布订阅、缓存淘汰、流技术等特性,提供了主从模式、Redis Sentinel和Redis cluster集群架构方案。

安装redis

yum方式安装

shell 复制代码
sudo yum install redis
sudo systemctl enable redis
sudo systemctl start redis

yum方式版本比较落后,无法安装最新版的redis,如果需要安装最新版本的redis需要使用源码安装的方式

源码方式安装

shell 复制代码
# 检查环境依赖
yum install gcc -y
# 下载Redis源码,一般下载到/opt目录下,/opt/software
wget http://download.redis.io/releases/redis-7.0.2.tar.gz
# 解压缩到当前目录(/opt/module)  
tar zxvf /opt/software/redis-7.0.2.tar.gz  
# 编译并安装 redis  (默认安装在/usr/local/bin目录下)
make && make install 
# 启动redis	
redis-server

安装目录(/usr/local/bin)中的文件结构

配置redis.conf文件

shell 复制代码
# 进入redis解压目录
cd redis-7.0.2
# 备份redis.conf文件
cp redis.conf redis.conf.bak
# 将redis改为后台执行,替换daemonize no为daemonize yes
sed -i 's/^daemonize no/daemonize yes/' "redis.conf"

# 将redis改为可在外网访问,替换bind 127.0.0.1 -::1为bind 0.0.0.0
sed -i 's/^bind 127.0.0.1 -::1/bind 0.0.0.0/' "redis.conf"

# 配置redis密码,这里使用root作为密码,替换requirepass foobared为requirepass root
sed -i 's/^# requirepass foobared/requirepass root/' "redis.conf"

# 按照配置文件要求启动redis服务
redis-server redis.cnof

redis数据类型

数据类型 解释 作用
String 字符串类型 二进制安全的数据类型,可以用来存储任何类型的数据
List 列表类型 Redis列表是简单的字符串列表,按照插入顺序排序
Hash 哈希表 存储键值对,使用存储对象
Set 集合类型 String类型的无序集合,集合中不能存在重复的数据。底层通过hash来实现
ZSet 有序集合 String类型的有序集合,集合中不能存在重复的数据。每个元素关联一个double类型的分数,底层通过hash来实现。
GEO 地理空间 地理位置,坐标、距离等
HyperLogLog 基数统计 在输入元素数量或体积非常大时,计算基数所需时间和空间总是固定的
Bitmap 位图 二进制的bit数组
Bitfield 位域 连续的比特位
Stream 用于消息队列(一般不是用)

String类型底层原理

String类型是redis最基本的数据类型,

SDS 简单动态字符串,SDS有的三个属性int len、int free、char buf[]。

len保存了字符串的长度

free表示buf数组中未使用的字节数量

buf数组则是保存字符串的每一个字符元素

Redis与C原生字符串相比:

1、C原生字符串不会记录长度,每次获取字符串长度时间复杂度都为O(n),Redis读取len中的数值即可,时间复杂度为O(1)。

2、C原生字符串拼接,如果分配空间不够会造成缓存区溢出的情况,SDS会现根据len中的数值判断空间是否足够,如果不够会进行相应的空间扩展,所以不会出现缓存区溢出的情况。

3、SDS提供空间预分配和惰性空间释放两种策略,在给字符串分配空间时,分配的空间比字符串实际所需空间大很多,这样能减少字符串增长带来的内存重新分配次数。当字符串被缩短时,SDS不会立即收回空间,而是通过free属性将空余的空间记录下来,等后面需要使用的时候再释放这些空间。

空间分配原则:当修改字符串后的长度len小于1MB,就会预分配和len一样长度的空间,即len=free;若是len大于1MB,free分配的空间大小就为1MB。
举个例子:
如果进行修改之后, SDS 的 len 将变成 13 字节, 那么程序也会分配 13 字节的未使用空间, SDS 的 buf 数组的实际长度将变成 13 + 13 + 1 = 27 字节(额外的一字节用于保存空字符)。
如果进行修改之后, SDS 的 len 将变成 30 MB , 那么程序会分配 1 MB 的未使用空间, SDS 的 buf 数组的实际长度将为 30 MB + 1 MB + 1 byte 。

List类型底层源码分析

redis3,2版本后,List类型通过quickList作为默认底层实现,quickList本质上是一个双端链表,可以认为是linkedList和ZipList的结合体。

LinkedList

LinkedList是一个普通的链表,LinkedList每一个节点的空间都是不连续的,所以可能造成过多的空间碎片。

ziplist

ziplist是为了节省内存而开发的一种压缩列表数据结构

zlbytes: 4字节,记录 ziplist 整个结构体的占用空间大小。用于内存重分配或计算zlend位置。

zltail: 4字节, 记录整个 ziplist 中最后一个 entry 的偏移量。用于快速定位到尾节点。

zllen: 4字节, 记录 entry 的数量,该值被固定为 2^16 - 1。 大于这个值就必须要遍历整个结构了。

entry: 真正存数据的结构。

zlend: 1字节, 为 ziplist 的结束标识。

entry节点结构

prelen:记录了前一个节点的长度。通过这个值,可以进行指针计算,从而跳转到上一个节点。如果前一节点的长度小于254字节,则prelen属性需要用1字节长的空间来保存;如果前一节点的长度大于等于254字节,则需要用5字节长的空间来保存。

encoding:记录了节点的content属性所保存数据的类型以及长度。编码的最高位用于标识数据类型(整数或字节数组),其余位用于表示内容的长度。

entry-data:保存节点的值

quicklist

quicklist存储了一个双向列表,每个列表的节点是一个ziplist

quicklist同样采用了linkedlist的双端列表特性,然后quicklist中的每个节点又是一个ziplist,所以quicklist就是综合平衡考虑了空间碎片和读写性能两个维度。使用quicklist需要注意以下2点:

1、如果ziplist中的entry个数过少,极端情况就是只有1个entry,此时就相当于退化成了一个普通的linkedlist。

2、如果ziplist中的entry过多,那么也会导致一次性需要申请的内存空间过大,而且因为ziplist本身的就是以时间换空间,所以会过多entry也会影响到列表对象的读写性能。

ziplist中的entry个数可以通过参数list-max-ziplist-size来控制

Redis持久化

redis为什么需要持久化?

Redis持久化的意义就是为了保证突然宕机,内存数据不会全部丢失。

RDB机制

RDB持久化是周期性的把redis当前内存中的全量数据写入到一个快照文件中

快照文件是一个二进制文件,包含了 Redis 在某个时间点内的所有数据。

在redis6.0之前,RDB的频率为15分钟1个变化、5分钟10个变化,1分钟1万个变化,

在redis6.2之后,RDB的频率为1小时1个变化,5分钟100个变化,1分钟1万个变化。

自动触发

再配置文件redis.conf中修改以下配置:

修改快照时间

save 5 2

修改文件保存路径

dir 文件路径

修改文件名称

dbfilename 文件名称.rdb

进入redis检查配置文件是否成功

config get save

config get dir

config get dbfilename

RDB会读取dump.rdb文件进行恢复,所以服务要与备份分机隔离。不可以把备份文件dump.rdb与生茶redis服务器放在同一台机器上,必须分开各自存储,以防止生产机物理损坏后备份文件也跟着挂了。

手动触发

手动执行有两个命令:save和bgsave

save:阻塞主进程,直到生成新的RDB文件;执行save命令期间,Redis不能处理其他命令。在生产中严禁使用该命令。

bgsave:异步生成RDB文件,fork子进程去生成新的RDB文件,主进程不阻塞。

相关推荐
IvorySQL16 分钟前
PostgreSQL 分区表的 ALTER TABLE 语句执行机制解析
数据库·postgresql·开源
·云扬·26 分钟前
MySQL 8.0 Redo Log 归档与禁用实战指南
android·数据库·mysql
IT邦德29 分钟前
Oracle 26ai DataGuard 搭建(RAC到单机)
数据库·oracle
惊讶的猫1 小时前
redis分片集群
数据库·redis·缓存·分片集群·海量数据存储·高并发写
不爱缺氧i1 小时前
完全卸载MariaDB
数据库·mariadb
期待のcode1 小时前
Redis的主从复制与集群
运维·服务器·redis
纤纡.1 小时前
Linux中SQL 从基础到进阶:五大分类详解与表结构操作(ALTER/DROP)全攻略
linux·数据库·sql
jiunian_cn1 小时前
【Redis】渐进式遍历
数据库·redis·缓存
橙露2 小时前
Spring Boot 核心原理:自动配置机制与自定义 Starter 开发
java·数据库·spring boot
冰暮流星2 小时前
sql语言之分组语句group by
java·数据库·sql