Redis核心数据结构和高性能原理

  • Redis安装
  • 安装问题处理
  • 修改了redis.conf文件
  • 关闭防火墙
  • 关闭防火墙
  • 开放端口
  • redis.conf中绑定多个ip地址
  • 用空格进行分隔
  • 绑定任意IP
  • 设置redis密码(已踩坑)
  • 使用telnet测试远程ip的端口
  • Redis基础数据结构
  • 字符串
  • 常用操作
  • 原子计数
  • 应用场景
  • 分布式锁
  • 单值缓存
  • 对象缓存
  • 计数器
  • web集群session共享
  • 分布式系统全局id
  • list(列表)
  • 应用场景
  • 模拟数据结构
  • 微博和微信公号消息流
  • hash (字典)
  • Hash常用操作
  • Hash结构的应用场景
  • 对象缓存
  • 电商购物车
  • set (集合)
  • set常用操作
  • 应用场景
  • 微信抽奖小程序
  • 微信微博点赞,收藏,标签
  • 集合操作
  • 集合操作实现微博微信关注模型
  • 集合操作实现电商商品筛选
  • zset (有序集合)
  • 应用场景
  • Zset集合操作实现排行榜
  • 其他高级命令
  • Redis核心原理
  • Redis的单线程和高性能
  • Redis是单线程吗?
  • Redis 单线程为什么还能这么快?
  • Redis 单线程如何处理那么多的并发客户端连接?


Redis安装

下载地址:http://redis.io/download
安装步骤:
# 安装gcc
yum install gcc

# 把下载好的redis-5.0.3.tar.gz放在/usr/local文件夹下,并解压
wget http://download.redis.io/releases/redis-5.0.3.tar.gz
tar -zxvf redis-5.0.3.tar.gz
cd redis-5.0.3

# 进入到解压好的redis-5.0.3目录下,进行编译与安装
make

# 修改配置
daemonize yes  #后台启动
protected-mode no  #关闭保护模式,开启的话,只有本机才可以访问redis
# 需要注释掉bind
#bind 127.0.0.1(bind绑定的是自己机器网卡的ip,如果有多块网卡可以配多个ip,代表允许客户端通过机器的哪些网卡ip去访问,内网一般可以不配置bind,注释掉即可)

# 启动服务
src/redis-server redis.conf

# 验证启动是否成功 
ps -ef | grep redis 

# 进入redis客户端 
src/redis-cli 

# 退出客户端
quit

# 退出redis服务: 
(1)pkill redis-server 
(2)kill 进程号                       
(3)src/redis-cli shutdown

参考链接
Redis安装

安装问题处理

修改了redis.conf文件

每次修改了redis.conf文件之后都需要重新加载一下配置文件再重启服务

./redis-server redis.conf

关闭防火墙

由于linux防火墙默认开启,redis的服务端口6379并不在开放规则之内,所有需要将此端口开放访问或者关闭防火墙

关闭防火墙
systemctl stop firewalld
systemctl status firewalld
systemctl disable firewalld   //关闭防火墙
systemctl enable firewalld
开放端口
firewall-cmd --add-port=6379/tcp

redis.conf中绑定多个ip地址

用空格进行分隔
bind 127.0.0.1 192.168.5.3
绑定任意IP
bind 0.0.0.0

设置redis密码(已踩坑)

为了安全一定要设,而且这里如果不绑定ip也不设密码的话,redis是默认保护模式,只能本虚拟机访问,不允许其他ip访问。
关闭保护模式也可以

protected-mode no  #关闭保护模式,开启的话,只有本机才可以访问redis

使用telnet测试远程ip的端口

redis 6 proxy原理 redis教程原理_redis


未输出任何字样表示远程端口可以访问

Redis基础数据结构

Redis 有 5 种基础数据结构,分别为:string (字符串)、list (列表)、set (集合)、hash (哈希) 和 zset (有序集合)

redis 6 proxy原理 redis教程原理_数据库_02

字符串

常用操作

redis 6 proxy原理 redis教程原理_数据库_03


redis 6 proxy原理 redis教程原理_redis 6 proxy原理_04

原子计数

redis 6 proxy原理 redis教程原理_Redis_05

如果 value 值是一个整数,还可以对它进行自增操作。自增是有范围的,它的范围是 signed long 的最大最小值,超过了这个值,Redis 会报错

redis 6 proxy原理 redis教程原理_Redis_06

应用场景

分布式锁

redis 6 proxy原理 redis教程原理_redis_07


redis 6 proxy原理 redis教程原理_redis_08

单值缓存

redis 6 proxy原理 redis教程原理_redis_09

对象缓存

redis 6 proxy原理 redis教程原理_缓存_10

计数器

redis 6 proxy原理 redis教程原理_redis 6 proxy原理_11


redis 6 proxy原理 redis教程原理_redis 6 proxy原理_12

web集群session共享

redis 6 proxy原理 redis教程原理_redis_13

分布式系统全局id

redis 6 proxy原理 redis教程原理_redis_14

list(列表)

  • Redis 的列表相当于 Java 语言里面的 LinkedList,注意它是链表而不是数组。这意味着 list 的插入和删除操作非常快,时间复杂度为 O(1),但是索引定位很慢,时间复杂度为 O(n),这点让人非常意外。 当列表弹出了最后一个元素之后,该数据结构自动被删除,内存被回收。
  • Redis 的列表结构常用来做异步队列使用。将需要延后处理的任务结构体序列化成字符串塞进 Redis 的列表,另一个线程从这个列表中轮询数据进行处理。

redis 6 proxy原理 redis教程原理_缓存_15


redis 6 proxy原理 redis教程原理_redis_16

应用场景

模拟数据结构

Stack(栈) = LPUSH + LPOP

Queue(队列)= LPUSH + RPOP

Blocking MQ(阻塞队列)= LPUSH + BRPOP

redis 6 proxy原理 redis教程原理_redis_17


redis 6 proxy原理 redis教程原理_缓存_18

微博和微信公号消息流

redis 6 proxy原理 redis教程原理_数据库_19


redis 6 proxy原理 redis教程原理_redis 6 proxy原理_20

redis 6 proxy原理 redis教程原理_redis_21


redis 6 proxy原理 redis教程原理_数据库_22

hash (字典)

  • Redis 的字典相当于 Java 语言里面的 HashMap,它是无序字典。内部实现结构上同 Java 的 HashMap 也是一致的,同样的数组 + 链表二维结构。第一维 hash 的数组位置碰撞时,就会将碰撞的元素使用链表串接起来
  • hash 结构也可以用来存储用户信息,不同于字符串一次性需要全部序列化整个对象,hash 可以对 用户结构中的每个字段单独存储。这样当我们需要获取用户信息时可以进行部分获取。而以整个字符串的形式去保存用户信息的话就只能一次性全部读取,这样就会比较浪费网络流量。 hash 也有缺点,hash 结构的存储消耗要高于单个字符串,到底该使用 hash 还是字符串,需要根据实际情况再三权衡。

Hash常用操作

redis 6 proxy原理 redis教程原理_数据库_23


redis 6 proxy原理 redis教程原理_redis_24


redis 6 proxy原理 redis教程原理_数据库_25

Hash结构的应用场景

对象缓存

redis 6 proxy原理 redis教程原理_redis_26

电商购物车

redis 6 proxy原理 redis教程原理_缓存_27


redis 6 proxy原理 redis教程原理_Redis_28


redis 6 proxy原理 redis教程原理_缓存_29

set (集合)

Redis 的集合相当于 Java 语言里面的 HashSet,它内部的键值对是无序的唯一的。它的内部实现相当于一个特殊的字典,字典中所有的 value 都是一个值NULL。 当集合中最后一个元素移除之后,数据结构自动删除,内存被回收。

set常用操作

redis 6 proxy原理 redis教程原理_redis_30


redis 6 proxy原理 redis教程原理_redis 6 proxy原理_31


redis 6 proxy原理 redis教程原理_Redis_32

应用场景

微信抽奖小程序

redis 6 proxy原理 redis教程原理_数据库_33


redis 6 proxy原理 redis教程原理_缓存_34

微信微博点赞,收藏,标签

redis 6 proxy原理 redis教程原理_redis 6 proxy原理_35


redis 6 proxy原理 redis教程原理_缓存_36

集合操作

redis 6 proxy原理 redis教程原理_redis_37

集合操作实现微博微信关注模型

redis 6 proxy原理 redis教程原理_数据库_38

集合操作实现电商商品筛选

redis 6 proxy原理 redis教程原理_数据库_39

zset (有序集合)

zset 类似于 Java 的 SortedSet 和 HashMap 的结合体,一方面它是一个 set,保证了内部 value 的唯一性,另一方面它可以给每个 value 赋予一个 score,代表这个 value 的排序权重。

zset 可以用来存粉丝列表,value 值是粉丝的用户 ID,score 是关注时间。我们可以对粉丝列表按关注时间进行排序。

zset 还可以用来存储学生的成绩,value 值是学生的 ID,score 是他的考试成绩。我们可以对成绩按分数进行排序就可以得到他的名次。

redis 6 proxy原理 redis教程原理_缓存_40

redis 6 proxy原理 redis教程原理_redis_41


redis 6 proxy原理 redis教程原理_数据库_42


redis 6 proxy原理 redis教程原理_数据库_43

应用场景

Zset集合操作实现排行榜

redis 6 proxy原理 redis教程原理_数据库_44


redis 6 proxy原理 redis教程原理_Redis_45

其他高级命令

  • keys:全量遍历键,用来列出所有满足特定正则字符串规则的key,当redis数据量比较大时,性能比较差,要避免使用
  • redis 6 proxy原理 redis教程原理_redis_46

  • Info:查看redis服务运行信息,分为 9 大块,每个块都有非常多的参数,这 9 个块分别是:
  • Server 服务器运行的环境参数
  • Clients 客户端相关信息
  • Memory 服务器运行内存统计数据
  • Persistence 持久化信息
  • Stats 通用统计数据
  • Replication 主从复制相关信息
  • CPU CPU 使用情况
  • Cluster 集群信息

Redis核心原理

Redis的单线程和高性能

Redis是单线程吗?

Redis 的单线程主要是指 Redis 的网络 IO 和键值对读写是由一个线程来完成的,这也是 Redis 对外提供键值存储服务的主要流程。但 Redis 的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的

Redis 单线程为什么还能这么快?

因为它所有的数据都在内存中,所有的运算都是内存级别的运算,而且单线程避免了多线程的切换性能损耗问题。正因为 Redis 是单线程,所以要小心使用 Redis 指令,对于那些耗时的指令(比如keys),一定要谨慎使用,一不小心就可能会导致 Redis 卡顿。

Redis 单线程如何处理那么多的并发客户端连接?

Redis的IO多路复用:redis利用epoll来实现IO多路复用,将连接信息和事件放到队列中,依次放到文件事件分派器,事件分派器将事件分发给事件处理器。

redis 6 proxy原理 redis教程原理_数据库_47