Redis6基础篇

Redis6

一、为什么使用NoSQL?

当今互联网时代,用户访问量大幅提升,出现了高并发高内存问题,同时产生了大量的用户数据,为了缓解CPU及

内存压力,NoSQL这种缓存数据库的作用就体现出来了,它使得数据完全在内存中,访问数据速度极快,数据结

构也较简单,同时它还解决了IO压力,以往的关系型数据库当存储的内容较大时,会选择"水平切分,垂直切分,

读写分离等操作"但是这破坏了一定的业务逻辑依此来换取性能,代价还是很大的。总而言之,NoSQL的出现是

决性能方面的。

1.1 NoSQL概述

NoSQL(NoSQL = Not Only SQL ),意思“不仅仅是 SQL”,泛指非关系型的数据库。 NoSQL 不依赖业务逻辑方式存

,而以简单的 key-value 模式存储。因此大大的增加了 数据库的扩展能力。

其特点:

  • 不遵循SQL标准
  • 不支持ACID(事务四大特性,不是说Redis不支持事务)
  • 远超于SQL的性能

1.2 NoSQL的使用场景

  • 存在数据高并发的读写
  • 海量数据的读写
  • 对数据可扩展性的

总之:数据量庞大存在高并发且对数据可扩展的选择NoSQL

1.3 NoSQL不适用的场景

  • 需要事务的支持
  • 处理较为复杂的关系

1.4 常见的NoSQL

1、Memcache
Redis6基础篇_第1张图片
  1. 很早出现的NoSql数据库
  2. 数据都在内存中,一般不持久化
  3. 支持简单的k-v模式,支持的数据类型较为单一
  4. 一般作为缓存数据库辅助持久化的数据库
2、MongoDB
Redis6基础篇_第2张图片
  1. 高性能、开源、模式自由(schema free)的文档型数 据库
  2. 数据都在内存中, 如果内存不足,把不常用的数据保存到硬盘
  3. 虽然是 key-value 模 式 ,但 是对 value (尤其是 json)提供了丰富的查询功能
  4. 支持二进制数据及大型对象 ,
  5. 可以根据数据的特点替代 RDBMS ,成为独立的数据库。或者配合 RDBMS,存储特定的数据
3、Redis
image-20220320154353718
  1. 几乎覆盖了 Memcached 的绝大部分功能
  2. 数据都在内存中,支持持久化,主要用作备份恢复
  3. 除了支持简单的 key-value 模式,还支持多种数据结构 的存储,比如 list、set、hash、zset 等。
  4. 一般是作为缓存数据库辅助持久化的数据库

二、Redis概述与安装

2.1 Redis概述

  • Redis是一个开源的k-v存储系统
  • 支持存储的value类型包括:String,list,set,zset,hash
  • 这些数据类型都支持 push/pop、add/remove 及取交集并集和差集及更丰富的操作, 而且这些操作都是原子性的
  • 在此基础上,Redis 支持各种不同方式的排序
  • 为了保证效率,数据都是缓存在内存中
  • 区别的是 Redis 会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件(RDB & AOF)
  • 并且在此基础上实现了 master-slave(主从)同步。
Redis6基础篇_第3张图片

2.2 Redis安装

:这里只讲Linux的安装过程

去官网,点击Download下载最新版本的zip文件

image-20220320155114675
2.2.1 安装步骤

准备工作:以CentOS7为例

1、下载最新版本的gcc编译器

yum install centos-release-scl scl-utils-build
yum install -y ddevtoolset-8-toolchain
scl enable devtoolset-8-bash

2、测试gcc版本

gcc --version
image-20220320155452082

3、采用xtfp工具将windows上下载的redis压缩包放到自己在linux这边的目录

4、进入linux找到刚刚放redis压缩包的目录,打开终端

5、解压命令:tar -zxvf redis-6.2.1.tar.gz

6、解压完进入目录 cd 解压目录

7、在该目录执行 make(编译好)

8、如果在第一步时候没有准备C语言编译缓解,make会报错提示:-Jemalloc/jemalloc.h:没有那个文件

​ 解决方法:make distclean

​ 8.1、在刚才解压目录下再次执行make命令

9、正式安装:make install 默认安装目录:/usr/local/bin

Redis6基础篇_第4张图片

redis-benchmark:性能测试工具,可以在自己本子运行,看看自己本子性能如何

redis-check-aof:修复有问题的 AOF 文件

redis-check-dump:修复有问题的 dump.rdb 文件

redis-sentinel:Redis 集群使用

redis-server:Redis 服务器启动命令

redis-cli:客户端,操作入口

2.3 启动Redis

2.3.1 前台启动(不推荐)

前台启动,命令行窗口不能关闭,一旦关闭,redis服务停止(ctrl + c 强制结束)

Redis6基础篇_第5张图片
2.3.2 后台启动(推荐)

一般建议将刚刚我们解压目录中的redis.conf配置文件 复制到另一个位置上

cp /myredis/redis-6.2.1/redis.conf /etc/redis.conf

修改配置文件redis.conf

image-20220320160618766

后台启动设置 daemonize no 改成 daemonize yes

image-20220320160640095

后台启动redis服务

redis-server /etc/redis.conf

查看关于redis的后台进程

ps -ef | grep redis

image-20220320160827673

这里我的redis的地址是*:表示任意一台IP地址都可以访问,这需要在配置文件中配置

你们一开始查看的时候都是本机地址,即 redis-server 127.0.0.1:6379

采用客户端访问redis

redis-cli
image-20220320161003402

测试是否成功

在redis客户端输入ping,如果出现 PONG ,恭喜你正式启动了Redis

Redis关闭

Linux命令行关闭 : redis-cli shutdown

redis客户端关闭 :shutdown

2.4 Redis 必知点

  • Redis 默认端口号为6379
  • Redis 配置文件名称为: redis.conf
  • Redis 默认16个数据库,初始默认库位0号库
    • 切换库的指令为 select x x: 0 ~ 15
    • 统一密码管理,所有库同样密码
    • 查看当前库key的数量 : dbsize
    • 清空当前库:flushdb
    • 通杀全部库(别用!):flushall
  • Redis 采用 单线程 + 多路IO复用技术
    • Redis的单线程指的是执行命令时的单线程,体现在当客户端执行命令时,一条命令从客户端到服务端不会立即被执行,而是进入一个等待队列中,每次只有一条指令被选中执行,按顺序执行
    • 多路I/O复用技术用来解决IO问题,多路复用是指使用一个线程来检查多个文件描述符(Socket)的就绪状态,比如调用 select 和 poll 函数,传入多个文件描述符,如果有一个文件描述符就绪,则返回,否则 阻塞直到超时。得到就绪状态后进行真正的操作可以在同一个线程里执行,也可以启 动线程执行(比如使用线程池)

三、常用五大数据类型

  • String(字符串)
  • List(列表)
  • Set(集合)
  • Hash(哈希)
  • Zset(有序集合)

常用五大数据类型的操作命令:http://www.redis.cn/commands.html

3.1 键(Key)

keys *查看当前库所有 key (匹配:keys *1)

exists key 判断某个 key 是否存在

type key查看你的 key 是什么类型

del key 删除指定的 key 数据

unlink key 根据 value 选择非阻塞删除 仅将 keys 从 keyspace 元数据中删除,真正的删除会在后续异步操作。

expire key seconds10 秒钟:为给定的 key 设置过期时间

tl key查看还有多少秒过期,-1 表示永不过期,-2 表示已过期

select 命令切换数据库

dbsize查看当前数据库的 key 的数量

flushdb清空当前库

flushall 通杀全部库

3.2 String字符串

Redis6基础篇_第6张图片

String 是 Redis 最基本的类型 “一个 key 对应一个 value” String 类型是二进制安全的。意味着 Redis 的 string 可以包含任何数据。比如 jpg 图片 或者序列化的对象。

​ 一个 Redis 中字符串 value 最多可以是 512M

3.2.1 常用命令
  • set 添加键值对
127.0.0.1:6379> set name wcd
OK

​ *nx:当数据库key不存在时,可以将k-v添加到数据库

127.0.0.1:6379> setnx age 18
(integer) 1   //库中不存在,可以添加,返回1
127.0.0.1:6379> setnx name hhh
(integer) 0   //库中已存在,不可以添加,返回0

​ *xx(set):当数据库中 key 存在时,可以将 key-value 添加数据库,与 nx 参数互斥

​ *ex:key 的超时秒数 setex

127.0.0.1:6379> setex day 20 day1
OK
127.0.0.1:6379> keys *
1) "day"
2) "age"
3) "name"
4) "k3"
5) "k1"
6) "k2"
......20s后
127.0.0.1:6379> keys *
1) "age"
2) "name"
3) "k3"
4) "k1"
5) "k2"

​ *px:key 的超时毫秒数,与 ex 互斥

  • get 查询给定key对应的value
127.0.0.1:6379> get name 
"wcd"
  • append 将给定的值追加到原值的末尾
127.0.0.1:6379> append name 666
(integer) 6  //返回追加后的字符串长度
127.0.0.1:6379> get name
"wcd666" 
  • strlen 获得值的长度

  • incr 将key中存储的数字增1,只能对数字值操作,如果为空,新增值为1

  • decr 将key中存储的数字减1,只能对数字值操作,如果为空,新增值为-1

  • incrby/decrby 将key中存储的数字值进行增减,自定义步长

127.0.0.1:6379> get age
"18"
127.0.0.1:6379> incrby age 20  //decrby同理
(integer) 38  //返回成功后的数字值
127.0.0.1:6379> get age
"38" 

原子性

incr,decr,incrby,decrby具备原子性的操作叫做原子操作。所谓原子操作是指不会被线程调度机制打断的操作

这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另 一个线程)。

(1)在单线程中, 能够在单条指令中完成的操作都可以认为是"原子操作",因为中 断只能发生于指令之间。

(2)在多线程中,不能被其它进程(线程)打断的操作就叫原子操作。 Redis 单命令的原子性主要得益于 Redis 的单线程。

  • mset … 同时设置一个或多个k-v对

  • mget 同时获取一个或多个value

  • msetnx … 同时设置一个或多个k-v对,当且仅当所有给定的key都不存在,如果有一个存在,那么该指令操作失败(原子性:要么都成功,有一个失败就失败)

  • getrange 获得值的范围,类似java中的subString

127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> mget k1 k2 k3
1) "v1"
2) "v2"
3) "v3"

127.0.0.1:6379> getrange name 0 2
"wcd"      //"wcd666" 从0开始到2截取字符串 
  • setrange 用覆盖所存储的字符串值,从开始(索引从0开始)

  • getset 以旧换新,设置了新值的同时获得旧值

127.0.0.1:6379> getset name zpp
"wcd666"  //设置新值"zpp",返回旧值"wcd666"
127.0.0.1:6379> get name
"zpp" 
3.2.2 数据结构

​ String 的数据结构为 简单动态字符串(Simple Dynamic String,缩写 SDS)。是可以 修改的字符串,内部结构实现上类似于 Java 的 ArrayList,采用预分配冗余空间的方式 来减少内存的频繁分配

Redis6基础篇_第7张图片

​ 如上图所示,内部为当前字符串实际分配的空间 capacity 一般要高于实际字符串长度 len。当字符串长度小于 1M 时,扩容都是加倍现有的空间,如果超过 1M,扩容时一次 只会多扩 1M 的空间。需要注意的是字符串最大长度为 512M。

3.3 List列表

记住List:“单键多值"

Redis6基础篇_第8张图片

​ Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(Left)或者尾部(Right)

​ 底层是一个双向链表,对双端的操作性都很高,如果通过索引下标的操作方式,中间的节点性能会较差。

Redis6基础篇_第9张图片
3.3.1 常用命令

List的命令基本都是L(List)开头

  • lpush/rpush 从左边/右边插入一个或多个值。
127.0.0.1:6379> lpush number 1 2 3 
(integer) 3
127.0.0.1:6379> rpush number 4 5 6
(integer) 6
127.0.0.1:6379> lrange number 0 -1
1) "3"
2) "2"
3) "1"
4) "4"
5) "5"
6) "6"


       		 	---------------------       ---------------------
lpush(123)   3 2 1  |   |   |    |     -->          3  |  2 |   1
        		----------------------      ----------------------

 ---------------------            		-------------------------
             3   2   1  <---rpush(456)  3  2  1  4  5  6 
 ----------------------					--------------------------
lrange key 0 -1 :从左边下标为0的位置到最右边第一个下标-1 之间的所有value
  • lpop/rpop [count] 从左边/右边吐出count个值。“值在键在,值光键亡
lpop number 1
1) "3"
  • rpoplpush 从列表右边吐出一个值,插到列表左边。
127.0.0.1:6379> lpush size 10 20 30
(integer) 3
127.0.0.1:6379> rpoplpush size number
"10"
127.0.0.1:6379> lrange number 0 -1
1) "10"
2) "3"
3) "2"
4) "1"
5) "4"
6) "5"
7) "6"

Redis6基础篇_第10张图片

  • lrange 按照索引下标获得元素(从左到右) lrange mylist 0 -1 0 左边第一个,-1 右边第一个,(0-1 表示获取所有)

  • lindex 按照索引下标获得元素(从左到右) 下标从0开始

  • llen 获得列表长度

  • linsert before/after 在的前面/后面插入

127.0.0.1:6379> lrange size 0 -1
1) "30"
2) "20"
3) "10"
127.0.0.1:6379> linsert size before 30 40
(integer) 4
127.0.0.1:6379> linsert size before 40 50
(integer) 5
127.0.0.1:6379> linsert size after 10 5
(integer) 6
127.0.0.1:6379> lrange size 0 -1
1) "50"
2) "40"
3) "30"
4) "20"
5) "10"
6) "5"
  • lrem 从左边删除 n 个 value(从左到右)
127.0.0.1:6379> lrem size 2 10  //从左到右删除2个value为10的,如果没有就不删除,不足2个也删除,作用就是从左到右批量删除一样的值
(integer) 1
127.0.0.1:6379> lrange size 0 -1
1) "50"
2) "40"
3) "30"
4) "20"
5) "5"
  • lset 将列表 key 下标为 index 的值替换成 value
127.0.0.1:6379> lset size 0 100  //将下标0的值替换成100
OK
127.0.0.1:6379> lrange size 0 -1
1) "100"
2) "40"
3) "30"
4) "20"
5) "5"
3.3.2 数据结构

List的数据结构为快速链表QuickList

​ 首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是 ziplist,也即是 压缩列表它将所有的元素紧挨着一起存储,分配的是一块连续的内存。 当数据量比较多的时候才会改成 quicklist。

​ 因为普通的链表需要的附加指针空间太大,会比较浪费空间。比如这个列表里存的只 是 int 类型的数据,结构上还需要两个额外的指针 prev 和 next。

image-20220320190320573

Redis 将链表和 ziplist 结合起来组成了 quicklist。也就是将多个 ziplist 使用双向指针串起来使用。这样既满足了快速的插入删除性能,又不会出现太大的空间冗余。

3.3 Set集合

Redis6基础篇_第11张图片

”可以看作是有去重功能的List“

​ Redis set 对外提供的功能与 list 类似是一个列表的功能,特殊之处在于 set 是可以自动排重(类似于MySql的去重distinct)的,当你需要存储一个列表数据,又不希望出现重复数据时,set 是一个很好的选择.并且 set 提供了判断某个成员是否在一个 set 集合内的重要接口,这个也是 list 所不能提供的

​ Redis 的 Set 是 String 类型的无序集合(Zset与之相反)。它底层其实是一个 value 为 null 的 hash 表,所 以添加,删除,查找的复杂度都是 O(1)。

​ 一个算法,随着数据的增加,执行时间的长短,如果是 O(1),数据增加,查找数据的时间不变

3.3.1 常用命令

Set的命令都以"s”开头

  • sadd … 将一个或多个 member 元素加入到集合 key 中,已经存在的 member 元素将被忽略
127.0.0.1:6379> sadd s1 v1 v2 v3 v1 v4  //排重,v1重复,只添加1个
(integer) 4
127.0.0.1:6379> smembers s1
1) "v1"
2) "v4"
3) "v3"
4) "v2"
127.0.0.1:6379> sismember s1 v1
(integer) 1
127.0.0.1:6379> scard s1
(integer) 4
127.0.0.1:6379> srem s1 v1 v2
(integer) 2
127.0.0.1:6379> smembers s1
1) "v4"
2) "v3"
127.0.0.1:6379> spop s1 1
1) "v3"

  • smembers 取出该集合的所有值。

  • sismember 判断集合是否为含有该值,有 1,没有 0

  • scard 返回该集合的元素个数。

  • srem 删除集合中的某元素。

  • spop 随机从该集合中吐出n个值。

  • srandmember 随机从该集合中取出 n 个值。不会从集合中删除 。

127.0.0.1:6379> smembers s1
1) "v1"
2) "v2"
3) "v5"
4) "v3"
5) "v4"
127.0.0.1:6379> srandmember s1 2
1) "v1"
2) "v5"
127.0.0.1:6379> smove s1 s2 v1
(integer) 1
127.0.0.1:6379> smove s1 s2 v2
(integer) 1
127.0.0.1:6379> smembers s2
1) "v1"
2) "v2"
  • smove 把集合A中的一个值从移动到集合B
  • sinter 返回两个集合的交集元素。
  • sunion 返回两个集合的并集元素。
  • sdiff 返回两个集合的差集元素(key1 中的,不包含 key2 中的)
3.3.2 数据结构

​ Set 数据结构是 dict 字典,字典是用哈希表实现的。 Java 中 HashSet 的内部实现使用的是 HashMap,只不过所有的 value 都指向同一个对象。 Redis 的 set 结构也是一样,它的内部也使用 hash 结构,所有的 value 都指向同一个内部值。

3.4 Hash哈希

Redis hash 是一个键值对集合

Redis hash 是一个 String 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。 类似 Java 里面的 Map

假设要存储一个用户,用户 ID 为查找的 key,存储的 value用户对象包含姓名,年龄,生日等信息,如果用普通的 key/value 结构来存储,主要有两种方式

Redis6基础篇_第12张图片

而Hash哈希就是上面两种方法的折中,通过key(UserID) + field(属性标签) 就可以操作对应的属性数据,即不需要重读存储数据,也不会带来序列化和并发修改控制的问题

Redis6基础篇_第13张图片
3.4.1 常用命令

和上面一样,Hash的命令都是"h"开头

  • hset … 给集合中的键赋值

  • hget 从集合取出 value

  • hmset … 批量设置 hash 的值

  • hmget… 查看hash中field对应的值

  • hexists查看哈希表 key 中,给定域 field 是否存在。返回1表示存在

  • hkeys 列出该 hash 集合的所有 field

  • hvals 列出该 hash 集合的所有 value

  • hincrby 为哈希表 key 中的域 field 的值加上增量 1 -1

  • hsetnx 将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在

127.0.0.1:6379> hset user:1001 name wcd age 18 sex male
(integer) 3
127.0.0.1:6379> hget user:1001 name
"wcd"
127.0.0.1:6379> hget user:1001 age
"18"
127.0.0.1:6379> hget user:1001 sex
"male"
127.0.0.1:6379> hmset user:1002 name zpp age 18 sex female
OK
127.0.0.1:6379> hmget user:1002 name age sex
1) "zpp"
2) "18"
3) "female"
127.0.0.1:6379> hkeys user:1001
1) "name"
2) "age"
3) "sex"
127.0.0.1:6379> hvals user:1001
1) "wcd"
2) "18"
3) "male"
127.0.0.1:6379> hincrby user:1001 age 2
(integer) 20
127.0.0.1:6379> hincrby user:1001 age -2
(integer) 18
127.0.0.1:6379> hsetnx user:1001 name wll  //name存在,无法重新赋值,返回0
(integer) 0
127.0.0.1:6379> hsetnx user:1001 inters basketball
(integer) 1
3.4.2 数据结构

​ Hash 类型对应的数据结构是两种:ziplist(压缩列表),hashtable(哈希表)。当 field-value 长度较短且个数较少时,使用 ziplist,否则使用 hashtable。

3.5 Zset有序集合

​ Redis 有序集合 zset 与普通集合 set 非常相似,是一个没有重复元素的字符串集合

​ 不同之处是有序集合的每个成员都关联了一个评分(score),这个评分(score)被用 来按照从最低分到最高分的方式排序集合中的成员。集合的成员是唯一的,但是评分可以是重复的 。

​ 因为元素是有序的, 所以可以很快的根据评分(score)或者次序(position)来获取一个范围的元素。 访问有序集合的中间元素也是非常快的,因此你能够使用有序集合作为一个没有重复成员的智能列表。

3.5.1 常用命令
  • zadd … 将一个或多个 member 元素及其 score 值加入到有序集 key 当中。
  • zrange [WITHSCORES] 返回有序集 key 中,下标在之间的元素 带 WITHSCORES,可以让分数一起和值返回到结果集。 与其相反的是zrevrange (reverse反转)
  • zrangebyscore [withscores] [limit offset count] 返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。 有序集成员按 score 值递增(从小到大)次序排列。
  • zrevrangebyscore [withscores] [limit offset count] 同上,改为从大到小排列。
  • zincrby 为元素的 score 加上增量
  • zrem 删除该集合下,指定值的元素
  • zcount 统计该集合,分数区间内的元素个数
  • zrank 返回该值在集合中的排名,从 0 开始。
127.0.0.1:6379> zadd scores 100 math 90 english 95 chinese
(integer) 3
127.0.0.1:6379> zrange scores 0 -1  //从小到大
1) "english"
2) "chinese"
3) "math"
127.0.0.1:6379> zrevrange scores 0 -1  //从大到小
1) "math"
2) "chinese"
3) "english"
127.0.0.1:6379> zrange scores 0 -1 withscores //带分数
1) "english"
2) "90"
3) "chinese"
4) "95"
5) "math"
6) "100"
127.0.0.1:6379> zrevrange scores 0 -1 withscores 
1) "math"
2) "100"
3) "chinese"
4) "95"
5) "english"
6) "90"
127.0.0.1:6379> zrangebyscore scores 95 100 withscores  //根据分数由小到大排序,从95-100
1) "chinese"
2) "95"
3) "math"
4) "100"
127.0.0.1:6379> zrevrangebyscore scores 100 95 withscores   //根据分数由大到小排序,从100-95
1) "math"
2) "100"
3) "chinese"
4) "95"
127.0.0.1:6379> zincrby scores 2 english 
"92"

127.0.0.1:6379> zrem scores english
(integer) 1
127.0.0.1:6379> zrange scores 0 -1
1) "chinese"
2) "math"
  • 案例:如何利用 zset 实现一个文章访问量的排行榜?

采用zrevrange 根据分数排序

Redis6基础篇_第14张图片
3.5.2 数据结构

​ SortedSet(zset)是 Redis 提供的一个非常特别的数据结构,一方面它等价于 Java 的数据结构 Map,可以给每一个元素 value 赋予一个权重 score,另 一方面它又类似于 TreeSet,内部的元素会按照权重 score 进行排序,可以得到每个元 素的名次,还可以通过 score 的范围来获取元素的列表。

​ zset 底层使用了两个数据结构

​ (1)hash,hash 的作用就是关联元素 value 和权重 score,保障元素 value 的唯 一性,可以通过元素 value 找到相应的 score 值。

​ (2)跳跃表,跳跃表的目的在于给元素 value 排序,根据 score 的范围获取元素列表。

3.5.2.1 跳跃表

跳跃表又称跳表

​ 有序集合在生活中比较常见,例如根据成绩对学生排名,根据得分对玩家排名等。对于有序集合的底层实现,可以用数组、平衡树、链表等。数组对于元素的插入、 删除比较繁琐;平衡树或红黑树虽然效率高但结构复杂;链表查询遍历所有元素时效率低。Redis 采用的是跳跃表。跳跃表效率堪比红黑树,实现远比红黑树简单。

例子

对比有序链表和跳跃表,从链表中查询出 51

1)有序链表

image-20220320202819876

要查找值为 51 的元素,需要从第一个元素开始依次查找、比较才能找到。共需要 6 次比较。

2)跳表

Redis6基础篇_第15张图片

从第 2 层开始,1 节点比 51 节点小,向后比较。

21 节点比 51 节点小,继续向后比较,后面就是 NULL 了,所以从 21 节点向下到第1层

在第1层,41 节点比 51 节点小,继续向后,61 节点比 51 节点大,所以从 41 向下

在第0层,51 节点为要查找的节点,节点被找到,共查找 4 次。

从此可以看出跳跃表比有序链表效率要高

四、Redis配置文件

安装完的redis目录中的conf文件我复制到了 /etc/redis.conf

Redis6基础篇_第16张图片

image-20220320203619329

让我们从上到下看看配置文件

4.1 Units单位

Redis6基础篇_第17张图片

  • 配置了大小单位,只支持bytes,不支持bit

  • 大小写不敏感 (units are case insensitve so 1GB 1Gb 1gB are all the same)

4.2 inclues包含

Redis6基础篇_第18张图片

类似于JSP中的include,多实例的情况可以把公用的配置文件提取出来,然后包含到其他配置文件

4.3 网络相关配置

Redis6基础篇_第19张图片

4.3.1 bind

Redis6基础篇_第20张图片

  • 默认情况 bind=127.0.0.1 只能接受本机的访问请求

  • 不写的情况下,无限制接受任何 ip 地址的访问

  • 生产环境肯定要写你应用服务器的地址;服务器是需要远程访问的,所以需要将其注释掉 如果开启了 protected-mode,那么在没有设定 bind ip 且没有设密码的情况下,Redis 只允许接受本机的响应

  • 保存配置,停止服务,重启启动查看进程,不再是本机访问了。

    • 如何停止服务?
      • 客户端->shutdown / linux终端 -->redis-cli shutdown / 强制杀死进程 kill- 9 pid
      • 之后重启服务 redis-server /etc/redis.conf
      • 查看进程 ps -ef | grep redis
image-20220320204947538
4.3.2 protected-mode

将本机访问保护模式设置 no,不然就算只改了bind Id,远程ip也无法访问,后续可能还要关闭防火墙

4.3.3 Port

端口号,默认 6379

image-20220320205306960
4.3.4 tcp-backlog
Redis6基础篇_第21张图片
  • 设置 tcp 的 backlog,backlog 其实是一个连接队列,backlog 队列总和=未完成三次握手 队列 + 已经完成三次握手队列。
  • 在高并发环境下你需要一个高 backlog 值来避免慢客户端连接问题。
  • 注意 Linux 内核会将这个值减小到/proc/sys/net/core/somaxconn 的值(128),所以需要 确认增大/proc/sys/net/core/somaxconn 和/proc/sys/net/ipv4/tcp_max_syn_backlog(128) 两个值来达到想要的效果
4.3.5 timeout
  • 一个空闲的客户端维持多少秒会关闭,0 表示关闭该功能。即永不关闭。
image-20220320205717978
4.3.6 tcp-keepalive
  • 对访问客户端的一种心跳检测,每个 n 秒检测一次。 单位为秒,如果设置为 0,则不会进行 Keepalive 检测,建议设置成 60

Redis6基础篇_第22张图片

4.4 通用配置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0epHybC1-1647841176634)(C:/Users/Lebr7Wcd/AppData/Roaming/Typora/typora-user-images/image-20220320210012502.png)]

4.4.1 daemonize
  • 是否为后台进程,设置为 yes 守护进程,后台启动

Redis6基础篇_第23张图片

4.4.2 pidfile
  • 存放 pid 文件的位置,每个实例会产生一个不同的 pid 文件

Redis6基础篇_第24张图片

4.4.3 logfile
  • 日志文件名称

Redis6基础篇_第25张图片

4.4.4 loglevel
  • 指定日志记录级别,Redis总共支持四个级别:debug,verbose,notice,warning,默认为Notice

四个级别根据使用阶段来选择,生产环境选择 notice 或者 warning

4.4.4 databases 16
  • 设定库的数量 默认 16,默认数据库为 0,可以使用 SELECT 命令在连接上指定数据库

image-20220320210400422

4.5 安全配置

Redis6基础篇_第26张图片

4.5.1 设置密码

Redis6基础篇_第27张图片

  • 访问密码的查看、设置和取消
  • 在命令中设置密码,只是临时的。重启 redis 服务器,密码就还原了。
  • 永久设置,需要再配置文件中进行设置
Redis6基础篇_第28张图片

4.6 限制配置

4.6.1 maxclients

Redis6基础篇_第29张图片

  • 设置 redis 同时可以与多少个客户端进行连接。
  • 默认情况下为 10000 个客户端。
  • 如果达到了此限制,redis 则会拒绝新的连接请求,并且向这些连接请求方发出 “max number of clients reached”以作回应。
4.6.2 maxmemory
  • 建议必须设置,否则,将内存占满,造成服务器宕机
  • 设置 redis 可以使用的内存量。一旦到达内存使用上限,redis 将会试图移除内部数据,移除规则可以通过 maxmemory-policy 来指定。
  • 如果 redis 无法根据移除规则来移除内存中的数据,或者设置了“不允许移除”, 那么 redis 则会针对那些需要申请内存的指令返回错误信息,比如 SET、LPUSH 等。
  • 但是对于无内存申请的指令,仍然会正常响应,比如 GET 等。如果你的 redis 是主 redis(说明你的 redis 有从 redis),那么在设置内存使用上限时,需要在系统中留 出一些内存空间给同步队列缓存,只有在你设置的是“不移除”的情况下,才不用考虑这个因素

Redis6基础篇_第30张图片

4.6.3 maxmemory-policy
  • volatile-lru:使用 LRU 算法移除 key,只对设置了过期时间的键;(最近最少使用)
  • allkeys-lru:在所有集合 key 中,使用 LRU 算法移除 key
  • volatile-random:在过期集合中移除随机的 key,只对设置了过期时间的键
  • allkeys-random:在所有集合 key 中,移除随机的 key
  • volatile-ttl:移除那些 TTL 值最小的 key,即那些最近要过期的 key
  • noeviction:不进行移除。针对写操作,只是返回错误信息

Redis6基础篇_第31张图片

4.6.4 maxmemory-samples
  • 设置样本数量,LRU 算法和最小 TTL 算法都并非是精确的算法,而是估算值,所 以你可以设置样本的大小,redis 默认会检查这么多个 key 并选择其中 LRU 的那个。
  • 一般设置 3 到 7 的数字,数值越小样本越不准确,但性能消耗越小。

Redis6基础篇_第32张图片

五、Redis的发布与订阅

5.1 什么是发布与订阅

  • Redis中的(pub/sub)发布与订阅是一种消息通信模式;发送者(publish)发送消息,订阅者(subscriber)接收消息

  • Redis 客户端可以订阅任意数量的频道

5.2 图片演示

  1. 客户端可以订阅频道如下图
Redis6基础篇_第33张图片
  1. 当给这个频道发布消息后,消息就会发送给订阅的客户端
Redis6基础篇_第34张图片

5.3 发布订阅命令行实现

  1. 打开一个redis客户端充当订阅者去订阅频道channel

subscriber channel1

Redis6基础篇_第35张图片
  1. 打开另一个客户端(这里指的是多窗口打开,不是在一个终端中),充当发布者
image-20220320212713362

publish channerl1 hello

image-20220320212841781

​ 返回的1是订阅者的数量

  1. 打开第一个客户端可以看到发布者发送的消息
Redis6基础篇_第36张图片

:发布的消息没有持久化

ng" alt=“image-20220320212419405” style=“zoom:80%;” />

  1. 当给这个频道发布消息后,消息就会发送给订阅的客户端
Redis6基础篇_第37张图片

5.3 发布订阅命令行实现

  1. 打开一个redis客户端充当订阅者去订阅频道channel

subscriber channel1

Redis6基础篇_第38张图片
  1. 打开另一个客户端(这里指的是多窗口打开,不是在一个终端中),充当发布者
image-20220320212713362

publish channerl1 hello

image-20220320212841781

​ 返回的1是订阅者的数量

  1. 打开第一个客户端可以看到发布者发送的消息
Redis6基础篇_第39张图片

:发布的消息没有持久化

你可能感兴趣的:(redis)