关于Redis核心数据结构与高性能原理

关于Redis核心数据结构与高性能原理

  • 一、Redis安装(以5.0.3为例)
  • 二、Redis的单线程和高性能
    • 执行快:
    • 单线程:
    • I/O 多路复用与多线程 I/O:
  • 三、其他高级命令
    • keys:全量遍历键
    • scan:渐进式遍历键
    • info:查看redis服务运行信息
    • help:查看指令用法
  • 四、5种基本数据结构
    • 1、String 结构
      • 1.1 String常用操作
      • 1.2 String应用场景
    • 2、Hash结构
      • 2.1 Hash常用操作
      • 2.2 Hash应用场景
      • 2.3 Hash结构优缺点
    • 3、List结构
      • 3.1 List常用操作
      • 3.2 List应用场景
    • 4、Set结构
      • 4.1 常用操作
      • 4.2 Set应用场景
    • 5、ZSet有序集合结构
      • 5.1 常用操作
      • 5.2 Zset应用场景
  • 五、Redis集群架构

一、Redis安装(以5.0.3为例)

下载地址:http://redis.io/download
安装步骤:

  1. 安装 gcc 编译器,用来编译 C 和 C++ 等源代码,Redis 使用 C 语言写的,用于第 3 步的 make
yum install gcc
  1. 进入 /usr/local 目录下,下载 redis 的 Linux 版本(.tar.gz)的压缩包,并进行解压
cd /usr/local
wget http://download.redis.io/releases/redis-5.0.3.tar.gz
tar -zxvf redis-5.0.3.tar.gz
  1. 进入解压完的 redis-5.0.3 目录下,进行编译与安装
cd redis-5.0.3
make
  1. 修改配置
vi redis.conf
# 后台启动
daemonize yes  
# 关闭保护模式,开启的话,只有本机才可以访问redis
protected-mode no  
# 需要检查是否有注释掉 bind
# bind绑定的是当前机器网卡的 ip,若有多块网卡可以配多个 ip,代表允许客户端通过机器的这些网卡 ip 去访问
# 内网则一般可以不配置 bind,注释掉即可
#bind 127.0.0.1
  1. 根据配置启动服务
src/redis-server redis.conf
  1. 验证启动是否成功
ps -ef | grep redis 
  1. 进入redis客户端
src/redis-cli 
  1. 退出客户端
quit
  1. 停止redis服务
(1)pkill redis-server 
(2)kill 进程号                       
(3)src/redis-cli shutdown 

第 1、2 种强制终止进程,可能导致数据丢失或损坏
第 3 种则是向 Redis 服务器发送关闭请求,允许服务器完成必要的清理工作

二、Redis的单线程和高性能

执行快:

  1. 纯内存操作:Redis 将所有数据存储在内存中,所有运算为内存级别,内存的访问速度远高于磁盘
  2. 单线程模型:由于是单线程模型处理客户端请求, 避免多线程频繁切换和过度竞争所带来的性能开销,Redis 每个请求的执行时间都很短,因此单线程能够处理大量的并发请求
  3. I/O 多路复用:可在单线程中同时监听多个客户端连接,只有当网络事件发生时才会进行实际的 I/O 操作,有效利用 CPU 资源,减少无谓的等待和上下文切换
  4. 高效数据结构:Redis 提供多种高效的数据结构,如哈希表、有序集合等,这些数据结构都经过优化,因此使用时效率非常高

Redis 是单线程,需尽量避免耗时的指令(如keys),很可能导致 Redis 卡顿。

单线程:

Redis 6.0 之前,是单线程运行所有操作,包括客户端的请求处理、命令执行、数据读写等,目的是为了避免多线程环境下的锁竞争和上下文切换带来的性能开销,保障高并发场景下的性能。

Redis 6.0 开始,引入多线程的支持,但仅限于网络 I/O 层面,即在网络请求阶段使用工作线程进行处理,来提高网络吞吐量。当这些 I/O 多线程完成网络的请求和解析,再把结果交由主线程执行。

对于读写操作仍是单线程处理,因此不会有多线程的并发问题。

后台持久化、异步删除、主从复制等,也是由额外的线程执行。

I/O 多路复用与多线程 I/O:

I/O 多路复用:Redis 利用 epoll 来实现 I/O 多路复用,意味着主线程可以有效监听多个 socket,将连接信息和事件放入队列,依次放入文件事件分派器,事件分派器将事件分发给事件处理器,但每个连接的具体处理(例如命令解析和执行)仍然由主线程串行进行。因此尽管 I/O 的监听是并行,但随着客户端连接数量的更加,主线程会花费更多时间在网络通信上,而不是执行实际的数据操作。

epoll 是 Linux 下的一个 I/O 事件通知机制,用于处理大量文件描述符的高效事件通知。它通常被用于网络编程中,特别是在实现高性能服务器时

关于Redis核心数据结构与高性能原理_第1张图片

多线程 I/O:为了进一步提高性能,尤其是面对大量连接但每个连接数据交换量不大的场景,Redis 6.0 引入了多线程负责解析网络请求,使主线程专注于命令的执行,即可更好利用现代多核处理器的能力,减少网络延迟的影响。

# 查看redis支持的最大连接数,在redis.conf文件中可修改,# maxclients 10000
127.0.0.1:6379> CONFIG GET maxclients
    ##1) "maxclients"
    ##2) "10000"

三、其他高级命令

keys:全量遍历键

用来列出所有满足特定正则字符串规则的key,当redis数据量比较大时,性能比较差,要避免使用

关于Redis核心数据结构与高性能原理_第2张图片

scan:渐进式遍历键

SCAN cursor [MATCH pattern] [COUNT count]

scan 参数:

  1. cursor:整数值(hash 桶的索引值)
  2. match:key 的正则模式
  3. count:一次遍历的 key 的数量,仅为参考值,底层遍历的数量不一定,并不是符合条件的结果数量。

第一次遍历时,cursor 值为 0,然后将返回结果中第一个整数值作为下一次遍历的 cursor,直到遍历返回的 cursor 值为 0 时结束。

若在 scan 的过程中有键发生变化(增删改),可能引发问题:
1)新增的键可能没有遍历到
2)遍历出了重复的键等情况

因此 scan 并不能保证完整地遍历出所有的键

关于Redis核心数据结构与高性能原理_第3张图片
关于Redis核心数据结构与高性能原理_第4张图片

info:查看redis服务运行信息

  1. Server:服务器运行的环境参数
  2. Clients:客户端相关信息
  3. Memory:服务器运行内存统计数据
  4. Persistence:持久化信息
  5. Stats: 通用统计数据
  6. Replication:主从复制相关信息
  7. CPU:CPU 使用情况
  8. Cluster:集群信息
  9. KeySpace:键值对统计数量信息

关于Redis核心数据结构与高性能原理_第5张图片

connected_clients:2                  # 正在连接的客户端数量

instantaneous_ops_per_sec:789        # 每秒执行多少次指令

used_memory:929864                   # Redis分配的内存总量(byte),包含redis进程内部的开销和数据占用的内存
used_memory_human:908.07K            # Redis分配的内存总量(Kb,human会展示出单位)
used_memory_rss_human:2.28M          # 向操作系统申请的内存大小(Mb)(这个值一般是大于used_memory的,因为Redis的内存分配策略会产生内存碎片)
used_memory_peak:929864              # redis的内存消耗峰值(byte)
used_memory_peak_human:908.07K       # redis的内存消耗峰值(KB)

maxmemory:0                         # 配置中设置的最大可使用内存值(byte),默认0,不限制,一般配置为机器物理内存的百分之七八十,需要留一部分给操作系统
maxmemory_human:0B                  # 配置中设置的最大可使用内存值
maxmemory_policy:noeviction         # 当达到maxmemory时的淘汰策略

help:查看指令用法

help @set
# zset底层为sorted_set
help @sorted_set

四、5种基本数据结构

关于Redis核心数据结构与高性能原理_第6张图片

1、String 结构

1.1 String常用操作

# 字符串常用操作
SET  key  value 									//存入字符串键值对
MSET  key  value [key value ...] 	//批量存储字符串键值对
SETNX  key  value 								//存入一个不存在的字符串键值对
GET  key 													//获取一个字符串键值
MGET  key  [key ...]	 						//批量获取字符串键值
DEL  key  [key ...] 							//删除一个键
EXPIRE  key  seconds 							//设置一个键的过期时间(秒)

# 原子加减
INCR  key 												//将key中储存的数字值加1
DECR  key 												//将key中储存的数字值减1
INCRBY  key  increment 						//将key所储存的值加上increment
DECRBY  key  decrement 						//将key所储存的值减去decrement

1.2 String应用场景

关于Redis核心数据结构与高性能原理_第7张图片

# 单值缓存
SET key value 	
GET key 	

# 对象缓存
1) SET user:1 value(json格式数据)
2) MSET user:1:name zhangsan user:1:balance 1800
MGET user:1:name user:1:balance

# 分布式锁
SETNX product:10001 true 					//返回1代表获取锁成功
SETNX product:10001 true 					//返回0代表获取锁失败
。。。执行业务操作
DEL product:10001									//执行完业务释放锁

SET product:10001 true ex 10 nx	  //防止程序意外终止导致死锁

关于Redis核心数据结构与高性能原理_第8张图片

# 计数器
INCR article:readcount:{文章id}  	
GET article:readcount:{文章id} 

# Web集群session共享
spring session + redis实现session共享

# 分布式系统全局序列号	
INCRBY orderId 1000		//redis批量生成序列号提升性能

2、Hash结构

2.1 Hash常用操作

# Hash常用操作
HSET key field value 										  //存储一个哈希表key的键值
HSETNX key field value 									  //存储一个不存在的哈希表key的键值
HMSET key field value [field value ...] 	//在一个哈希表key中存储多个键值对
HGET key field 														//获取哈希表key对应的field键值
HMGET key field [field ...] 							//批量获取哈希表key中多个field键值
HDEL key field [field ...] 							  //删除哈希表key中的field键值
HLEN key																	//返回哈希表key中field的数量
HGETALL key																//返回哈希表key中所有的键值

HINCRBY key field increment 							//为哈希表key中field键的值加上增量increment

2.2 Hash应用场景

关于Redis核心数据结构与高性能原理_第9张图片

关于Redis核心数据结构与高性能原理_第10张图片

对象缓存
HMSET user {userId}:name zhangsan {userId}:balance 1800
HMSET user 1:name zhangsan 1:balance 1800
HMGET user 1:name 1:balance

关于Redis核心数据结构与高性能原理_第11张图片

# 电商购物车
1)以用户id为key
2)商品id为field
3)商品数量为value

# 购物车操作
添加商品 → hset cart:1001 10088 1
增加数量 → hincrby cart:1001 10088 1
商品总数 → hlen cart:1001
删除商品 → hdel cart:1001 10088
获取购物车所有商品 → hgetall cart:1001

2.3 Hash结构优缺点

优点

  1. 同类数据归类整合储存,方便数据管理
  2. 相比 String 操作消耗内存与 CPU 更小
  3. 相比 String 储存更节省空间

缺点

  1. 过期功能不能使用在 field 上,只能用在 key 上
  2. Redis 集群架构下不适合大规模使用

3、List结构

3.1 List常用操作

关于Redis核心数据结构与高性能原理_第12张图片

# List常用操作
LPUSH  key  value [value ...] 	//将一个或多个值value插入到key列表的表头(最左边)
RPUSH  key  value [value ...]	 	//将一个或多个值value插入到key列表的表尾(最右边)
LPOP  key												//移除并返回key列表的头元素
RPOP  key												//移除并返回key列表的尾元素
LRANGE  key  start  stop				//返回列表key中指定区间内的元素,区间以偏移量start和stop指定

BLPOP  key  [key ...]  timeout	//从key列表表头弹出一个元素,若列表中没有元素,阻塞等待timeout秒,如果timeout=0,一直阻塞等待
BRPOP  key  [key ...]  timeout 	//从key列表表尾弹出一个元素,若列表中没有元素,阻塞等待timeout秒,如果timeout=0,一直阻塞等待

3.2 List应用场景

# 常用数据结构
Stack(栈) = LPUSH + LPOP
Queue(队列)= LPUSH + RPOP
Blocking MQ(阻塞队列)= LPUSH + BRPOP

关于Redis核心数据结构与高性能原理_第13张图片

关于Redis核心数据结构与高性能原理_第14张图片

# 微博消息流和微信公众号消息流
张三关注了MacTalk,备胎说车等大V
1)MacTalk发微博,消息ID为10018
LPUSH  msg:{张三-ID}  10018
2)备胎说车发微博,消息ID为10086
LPUSH  msg:{张三-ID} 10086
3)查看最新微博消息
LRANGE  msg:{张三-ID}  0  4

4、Set结构

4.1 常用操作

# Set常用操作
SADD key member [member ...]			//往集合 key 中存入元素,元素存在则忽略,若 key 不存在则新建
SREM key member [member ...]			//从集合 key 中删除元素
SMEMBERS key											//获取集合 key 中所有元素
SCARD key													//获取集合 key 的元素个数
SISMEMBER key member							//判断 member 元素是否存在于集合key中
SRANDMEMBER key [count]						//从集合 key 中选出 count 个元素,元素不从 key 中删除
SPOP key [count]									//从集合 key 中选出 count 个元素,元素从 key 中删除

# Set运算操作
SINTER key [key ...] 										//交集运算
SINTERSTORE destination key [key ..]		//将交集结果存入新集合 destination 中
SUNION key [key ..] 										//并集运算
SUNIONSTORE destination key [key ...]	  //将并集结果存入新集合 destination 中
SDIFF key [key ...] 										//差集运算
SDIFFSTORE destination key [key ...]		//将差集结果存入新集合 destination 中

4.2 Set应用场景

关于Redis核心数据结构与高性能原理_第15张图片

# 微信抽奖小程序
1)点击参与抽奖加入集合
SADD key {userlD}
2)查看参与抽奖所有用户
SMEMBERS key	  
3)抽取count名中奖者
SRANDMEMBER key [count] / SPOP key [count]

关于Redis核心数据结构与高性能原理_第16张图片

# 微信微博点赞,收藏,标签
1) 点赞
SADD like:{消息ID} {用户ID}
2) 取消点赞
SREM like:{消息ID} {用户ID}
3) 检查用户是否点过赞
SISMEMBER like:{消息ID} {用户ID}
4) 获取点赞的用户列表
SMEMBERS like:{消息ID}
5) 获取点赞用户数 
SCARD like:{消息ID}

关于Redis核心数据结构与高性能原理_第17张图片

# 集合操作
SINTER set1 set2 set3  { c }
SUNION set1 set2 set3  { a,b,c,d,e }
SDIFF set1 set2 set3  { a }

关于Redis核心数据结构与高性能原理_第18张图片

关于Redis核心数据结构与高性能原理_第19张图片

# 集合操作实现微博微信关注模型
1) 张三关注的人: 
zhangsanSet-> {lisi, wangwu}
2) 赵六关注的人:
 zhaoliuSet--> {zhangsan, tianqi, lisi, wangwu}
3) 李四老师关注的人: 
lisiSet-> {zhangsan, zhaoliu, tianqi, wangwu, qianba)
4) 我和赵六共同关注: 
SINTER zhangsanSet zhaoliuSet--> {lisi, wangwu}
5) 我关注的人也关注他(赵六): 
SISMEMBER lisiSet zhaoliu 
SISMEMBER wangwuSet zhaoliu
6) 我可能认识的人: 
SDIFF zhaoliuSet zhangsanSet->(zhangsan, tianqi}

关于Redis核心数据结构与高性能原理_第20张图片

# 集合操作实现电商商品筛选
SADD brand:huawei P40
SADD brand:xiaomi mi-10
SADD brand:iPhone iphone12
SADD os:android P40 mi-10
SADD cpu:brand:intel P40 mi-10
SADD ram:8G P40 mi-10 iphone12

SINTER os:android cpu:brand:intel ram:8G {P40,mi-10}

5、ZSet有序集合结构

5.1 常用操作

关于Redis核心数据结构与高性能原理_第21张图片

# ZSet常用操作
ZADD key score member [[score member]…]	//往有序集合key中加入带分值元素
ZREM key member [member …]							//从有序集合key中删除元素
ZSCORE key member 											//返回有序集合key中元素member的分值
ZINCRBY key increment member						//为有序集合key中元素member的分值加上increment 
ZCARD key																//返回有序集合key中元素个数
ZRANGE key start stop [WITHSCORES]			//正序获取有序集合key从start下标到stop下标的元素
ZREVRANGE key start stop [WITHSCORES]		//倒序获取有序集合key从start下标到stop下标的元素

# Zset集合操作
ZUNIONSTORE destkey numkeys key [key ...] 	//并集计算
ZINTERSTORE destkey numkeys key [key …]			//交集计算

5.2 Zset应用场景

关于Redis核心数据结构与高性能原理_第22张图片

关于Redis核心数据结构与高性能原理_第23张图片

# Zset集合操作实现排行榜
1)点击新闻
ZINCRBY hotNews:20190819 1 守护香港
2)展示当日排行前十
ZREVRANGE hotNews:20190819 0 9 WITHSCORES 
3)七日搜索榜单计算
ZUNIONSTORE hotNews:20190813-20190819 7 
hotNews:20190813 hotNews:20190814... hotNews:20190819
4)展示七日排行前十
ZREVRANGE hotNews:20190813-20190819 0 9 WITHSCORES

五、Redis集群架构

关于Redis核心数据结构与高性能原理_第24张图片

你可能感兴趣的:(Redis专栏,redis,数据结构,java)