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基础数据结构
Redis 有 5 种基础数据结构,分别为:string (字符串)、list (列表)、set (集合)、hash (哈希) 和 zset (有序集合)。
字符串
常用操作
原子计数
如果 value 值是一个整数,还可以对它进行自增操作。自增是有范围的,它的范围是 signed long 的最大最小值,超过了这个值,Redis 会报错
应用场景
分布式锁
单值缓存
对象缓存
计数器
web集群session共享
分布式系统全局id
list(列表)
- Redis 的列表相当于 Java 语言里面的 LinkedList,注意它是链表而不是数组。这意味着 list 的插入和删除操作非常快,时间复杂度为 O(1),但是索引定位很慢,时间复杂度为 O(n),这点让人非常意外。 当列表弹出了最后一个元素之后,该数据结构自动被删除,内存被回收。
- Redis 的列表结构常用来做异步队列使用。将需要延后处理的任务结构体序列化成字符串塞进 Redis 的列表,另一个线程从这个列表中轮询数据进行处理。
应用场景
模拟数据结构
Stack(栈) = LPUSH + LPOP
Queue(队列)= LPUSH + RPOP
Blocking MQ(阻塞队列)= LPUSH + BRPOP
微博和微信公号消息流
hash (字典)
- Redis 的字典相当于 Java 语言里面的 HashMap,它是无序字典。内部实现结构上同 Java 的 HashMap 也是一致的,同样的数组 + 链表二维结构。第一维 hash 的数组位置碰撞时,就会将碰撞的元素使用链表串接起来。
- hash 结构也可以用来存储用户信息,不同于字符串一次性需要全部序列化整个对象,hash 可以对 用户结构中的每个字段单独存储。这样当我们需要获取用户信息时可以进行部分获取。而以整个字符串的形式去保存用户信息的话就只能一次性全部读取,这样就会比较浪费网络流量。 hash 也有缺点,hash 结构的存储消耗要高于单个字符串,到底该使用 hash 还是字符串,需要根据实际情况再三权衡。
Hash常用操作
Hash结构的应用场景
对象缓存
电商购物车
set (集合)
Redis 的集合相当于 Java 语言里面的 HashSet,它内部的键值对是无序的唯一的。它的内部实现相当于一个特殊的字典,字典中所有的 value 都是一个值NULL。 当集合中最后一个元素移除之后,数据结构自动删除,内存被回收。
set常用操作
应用场景
微信抽奖小程序
微信微博点赞,收藏,标签
集合操作
集合操作实现微博微信关注模型
集合操作实现电商商品筛选
zset (有序集合)
zset 类似于 Java 的 SortedSet 和 HashMap 的结合体,一方面它是一个 set,保证了内部 value 的唯一性,另一方面它可以给每个 value 赋予一个 score,代表这个 value 的排序权重。
zset 可以用来存粉丝列表,value 值是粉丝的用户 ID,score 是关注时间。我们可以对粉丝列表按关注时间进行排序。
zset 还可以用来存储学生的成绩,value 值是学生的 ID,score 是他的考试成绩。我们可以对成绩按分数进行排序就可以得到他的名次。
应用场景
Zset集合操作实现排行榜
其他高级命令
- keys:全量遍历键,用来列出所有满足特定正则字符串规则的key,当redis数据量比较大时,性能比较差,要避免使用
- 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多路复用,将连接信息和事件放到队列中,依次放到文件事件分派器,事件分派器将事件分发给事件处理器。