前言(基本知识)
Redis背景
08年的时候有一个意大利西西里岛的小伙子,笔名antirez(http://invece.org/),创建了一个访客信息网站 LLOOGG.COM。这个网站是干嘛的呢,
其实就是跟我们的百度统计一样!需要知道网站的访问情况,比如访客的IP、操作系统、浏览器、使用的搜索关键词、所在地区、访问的网页地址等等。我们不用自己写代码去实现这个功能,只需要在全局的 footer 里面嵌入一段JS 代码就行了,当页面被访问的时候,就会自动把访客的信息发送到这些网站统计的服务器,然后我们登录后台就可以查看数据了。
LLOOGG.COM 提供的就是这种功能,它可以查看最多10000条的最新浏览记录。 这样的话,它需要为每一个网站创建一个列表(List),不同网站的访问记录进入到不同的列表。如果列表的长度超过了用户指定的长度,它需要把最早的记录删除(先进先出)。
大家来想一下这样的底层数据怎么来保存了!肯定是用数据库对吧
他最开始的时候用的就是mysql。但是当 LLOOGG.COM 的用户越来越多的时候,它需要维护的列表数量也越来越多,这种记录最新的请求和删除最早的请求的操作也越来越多。
然后mysql数据还是写在磁盘的,那么每一次记录和删除都要读写磁盘,因为数据量和并发量太大,在这种情况下无论怎么去优化数据库都不管用了。
他考虑到最终限制数据库性能的瓶颈在于磁盘,所以打算放弃磁盘,自己去实现一个具有列表结构的数据库的原型,把数据放在内存而不是磁盘,这样就可以大大地提升列表的操作和查的效率。antirez发现这种思路确实能解决这个问题。
所以他用C语言重写了一个内存数据库!(这才是大佬,工具不好用就自己写一个工具)
09年,Redis这个内存数据库出世了。从最开始只支持列表的数据类型,到现在支持多种数据类型,并且提供了一系列的高级特性,Redis已经成为一个在全世界被广泛使用的开源项目。这就是redis的由来!
那么redis的全称是全称是REmote DIctionary Service,直接翻译过来是远程字典服务
Redis初识
官网介绍(可以直接点)
中文官网(可以直接点)
Redis安装
1. 安装gcc依赖
Redis是C语言编写的,编译需要GCC。
Redis6.x.x版本支持了多线程,需要gcc的版本大于4.9,但是CentOS7的默认版本是4.8.5。
查看gcc的版本:
gcc -v
升级gcc版本:
yum -y install centos-release-sclyum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutilsscl enable devtoolset-9 bashecho "source /opt/rh/devtoolset-9/enable" >>/etc/profile
2. 修改config文件
daemonize yes //更改为后台启动#bind 127.0.0.1 //注释protected-mode no //允许外部网络直接访问
3. 启动Redis
如果src没有redis-server,在redis目录执行make
[root@localhost src]# ./redis-server ../redis.conf //启动服务[root@localhost src]# ./redis-cli //进入客户端
RedisCluster集群安装
现在正常都是三主三从6个节点了
我把6节点分别放在127.128.129 3台机器的 6380、6381端口
复制原有安装文件,把原有文件改成6380、6381
cp -r redis-6.0.16 redis-6.0.16-6381mv redis-6.0.16 redis-6.0.16-6380
更改配置文件
#bind 127.0.0.1protected-mode nodaemonize yescluster-enabled yes //可开启集群cluster-config-file nodes-6380.confpidfile /var/run/redis_6380.pid
开启集群
[root@localhost src]# ./redis-cli --cluster create192.168.8.129:6380 192.168.8.129:6381 192.168.8.128:6381192.168.8.128:6380 192.168.8.127:6380 192.168.8.127:6381 -cluster-replicas 1
集群相关命令
集群命令
(需进入客户端)
- cluster info :打印集群的信息
- cluster nodes :列出集群当前已知的所有节点(node),以及这些节点的相关信息。
- cluster meet :将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。
- cluster forget :从集群中移除 node_id 指定的节点(保证空槽道)。
- cluster replicate :将当前节点设置为 node_id 指定的节点的从节点。
- cluster saveconfig :将节点的配置文件保存到硬盘里面
槽slot命令
- cluster addslots [slot …] :将一个或多个槽(slot)指派(assign)给当前节点。
- cluster delslots [slot …] :移除一个或多个槽对当前节点的指派。
- cluster flushslots :移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。
- cluster setslot node :将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。
- cluster setslot migrating :将本节点的槽 slot 迁移到 node_id指定的节点中。
- cluster setslot importing :从 node_id 指定的节点中导入槽slot 到本节点。
- cluster setslot stable :取消对槽 slot 的导入(import)或者迁移(migrate)。
键命令
- cluster keyslot :计算键 key 应该被放置在哪个槽上。
- cluster countkeysinslot :返回槽 slot 目前包含的键值对数量。
- cluster getkeysinslot :返回 count 个 slot 槽中的键。
Redis特性
就一个字:快
这个工具发明出来的意义就是为了快
为什么快?
- 基于内存操作,操作不需要跟磁盘交互
- 本身就是k-v结构,redis自己底层数据结构支持,比如跳表
- 命令执行是单线程,同时通信采用多路复用
- lO多路复用,单个线程中通过记录跟踪每一个sock(I/O流) 的状态来管理多个I/O流 。
其他特性:
- Key-value字典结构存储,存储在内存,key是string类型,value根据不同的数据类型而不同
- 它的出世就是为了解决磁盘的性能问题,既然是解决性能问题,所以它是一个以key-value的字典结构存储方式,其中key的最大值为512M,这个数据来自于官网,value根据不同类型有不同的大小
- 更丰富的数据类型 ,value可以存储很多的数据类型
- 功能丰富:持久化机制、过期策略
- 支持多种编程语言(这个是它火起来的关键)
- 高可用,集群
最最常用的基本操作
它默认有16个库(0-15),这个其实可以在配置文件中修改的,默认使用第一个db0。
//切换数据库select 0
我们刚才讲过它是一个key-value的方式,所以:
//存值:set zwq 666//取值:get zwq
我是不是能像数据库的一样每个业务用不同的db?
能,但是我不建议!为什么呢,因为我们有个命令能很轻松的删库跑路!
//清空所有数据库flushall
//清空当前数据库flushdb
//查看所有键keys *
//获取键总数dbsize
//重命名键rename zwq 777
//对某个key设置过期时间expire zwq 10pexpire zwq 10000
//查看键是否存在exists zwq
//删除键del zwq
//查看对外类型type zwq
这些是一些比较基本的命令,还有一些命令我就不一一列举了,大家可以自己去看下,
常用命令
常用5大数据类型及应用场景
官网
Redis有这么多数据类型:String、Hash、Set、List、Zset、Hyperloglog(基数统计)、Geo(地理
位置)、Streams流。
但是常用的其实就5个。
String
我们刚才已经知道了redis里面都是key-value的结构存储的,那么string数据类型那个value可以存储什么?其实这个value可以存储String,Number,Float,Bits等等…
那么这个String到底是怎么玩的,我们来看下string的一些基本指令!
set get 就不说了
//批量设置mset zwq 111 zwq2 222//批量获取mget zwq zwq2//字符串追加内容append zwq 123//获取指定范围的字符getrange zwq 0 5//(整数)值递增incr intkeyincrby intkey 100//(浮点数)值递增看set f 2.6incrbyfloat f 7.3//如果不存在这个key设置成功,存在设置失败(分布式锁)//EX − 设置指定的到期时间(以秒为单位)。//PX - 设置指定的到期时间(以毫秒为单//NX - 仅在键不存在时设置键。//XX - 只有在键已存在时才设置。set lock1 1 EX 10 NXsetnx k1 1
应用场景:
- 缓存
这个我们就不用多讲了,redis用过肯定最先用到的是这个!Set一个值,如果值还在,那么我们就去get就行 - 分布式ID
大家想下这个ID我们应该用什么命令来实现 ?
我们知道它要全局唯一!Incr,因为它是单线程下自增的! - 计数器、限流 !
这个我们incrby指令可以决定我们每次增长的长度,那么限流是不是也能做 - 分布式锁 set 加nx参数
或者setnx (命令执行是单线程的)
Hash哈希
我们发现我们string可以存浮点,整型,字符串类型,但是假如我要存一个对象怎么办,转换成json,读时再转换回来?
这样可以实现,但是有更加直接的方法:
Hash 的结构是这样的 : Key file value
比String多了一个小file,我们把它当作字段名就好。
那么面试题来了,为什么要有这个hash数据类型?
1、把所有相关的值聚集到一个大key中,节省内存空间
2、只使用一个key,减少key冲突
3、当需要批量获取值的时候,只需要使用一个命令,减少内存/IO/CPU 的消耗
但是,它也有一个不足:
1、不能设置file的过期时间,我们只能针对于key设置过期时间
使用场景:
String可以做的事情,Hash都可以做!
- 存储对象类的数据
- 统计类的数据
- 购物车
操作命令可以参考这个网站:
常用命令
List列表
存储有序的字符串(从左到右),元素可以重复。可以充当队列和栈的角色。
应用场景:
- 用户消息时间线
因为list是有序的 - 消息队列
List提供了两个阻塞的弹出操作:BLPOP/BRPOP,可以设置超时时间。
BLPOP:BLPOP key1 timeout 移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
但是队列我不建议大家用redis了,为什么,因为我们有更加成熟的技术,就是我们的MQ!
并且redis它是内存型数据库,可能会造成数据丢失,还有它消费了后没法回应!
操作命令可以参考这个网站:
常用命令
Set集合
String类型的无序集合,最大存储数量 2^32-1(40 亿左右)。
应用场景
- 抽奖
- 点赞、签到等
- 交集并集 关注等场景
操作命令可以参考这个网站:
常用命令
Sorted Set(ZSet)有序集合
应用场景
- 排行榜
这个排行榜一般在公司的使用是在任何排行的地方都可以用到,像销售榜、热搜榜、游戏评分排行等等
操作命令可以参考这个网站:
常用命令
小小的总结
redis常用的5种数据类型以及使用场景!
(1)String 缓存,计算器,分布式锁等等
(2)Hash 有子键filed 购物车等场景
(3)List 有序集合,元素可以重复队列,有序列表
(4)Set 无序集合,元素不可重复关注点赞,抽奖
(5)ZSet 有序集合,元素不可重复排行榜
它的特性:
(1)分布在内存以及IO多路复用,速度快
(2)很丰富的数据类型支持
(3)能分布式集群部署,保证高可用
(4)支持持久化,数据过期以及淘汰