Redis基础(笔记)

一、相关介绍

1.1 技术的分类

  • 解决功能性的问题:Java、Jsp、RDBMS、Tomcat、Linux、JDBC、SVN
  • 解决扩展性的问题(框架):Struts、Spring、SpringMVC、Hibernate、Mybatis
  • 解决性能的问题:NoSQL、Java线程、Hadoop、Nginx、MQ、Elastic Search

1.2 中间件

中间件是介于应用系统和系统软件之间的一类软件,它使用系统软件所提供的基础服务(功能),衔接网络上应用系统的各个部分或不同的应用,能够达到资源共享、功能共享的目的。它并没有很严格的定义,但是普遍接受IDC的定义:中间件是一种独立的系统软件服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源,中间件位于客户机服务器的操作系统之上,管理计算资源和网络通信。从这个意义上可以用一个等式来表示中间件:中间件=平台+通信,这也就限定了只有用于分布式系统中才能叫中间件,同时也把它与支撑软件和实用软件区分开来。——《百度词条》

1.2.1 大致分类

  • 消息中间件
  • 交易中间件
  • 应用服务器
  • 应用交付中间件
  • 缓存中间件

1.3 Session储存问题

  • 方案1:放入cookie之中
    • 优点:
    1. 由客户端保存维护
    2. 请求时会带有数据一起
    • 缺点:
    1. 不安全
    2. 网络负担大、效率低
  • 方案2:session存储在文件服务器或数据库中
    • 优点:
    1. 服务器维护数据,相较而言更安全
    2. 可以由服务端主动向客户端发送消息,而不再用类似轮询的方式
    • 缺点:
    1. 大量的IO效率问题

分库分表(水平切分、垂直切分、读写分离)也可以减少IO压力,但是会破坏业务逻辑。

  • 方案3:session复制,即将信息存在多个节点之中
    • 优点:
    1. 有多个节点分担请求,解决了但唔够服务器处理过慢问题
    • 缺点:
    1. session数据冗余,且节点越多,浪费越大
    2. 需要考虑数据一致性问题
  • 方案4:缓存数据库(NoSQL)
    • 优点:
    1. 常用数据存在内存之中,减少数据库读写的耗时
    • 缺点:
    1. 带了相应的问题,比如缓存击穿、穿透、雪崩以及哨兵模式相关的问题

1.4 NoSQL

NoSQL(not only sql),泛指非关系型数据库。
不依赖业务逻辑方式存储,而是以简单的键值对(key-value)模式存储。
不是以逻辑为优先级,而是以性能为优先。

  • 不遵循SQL标准
  • 不支持ACID(事务:原子性、一致性、隔离性、永久性)
  • 性能远高于SQL

1.4.1 适用场景

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

1.4.2 不适用场景

  • 需要事务支持
  • 基于sql的结构化查询存储

1.4.3 常用的缓存中间件

  • Memcache
  • Redis
  • MongoDB

1.5 行式、列式数据库

  • 行式:常用的方式。一行代表一个对象的相关信息。存储结构则是一行存放在一起。查询则是一行一行的查询。
  • 列式:同一属性存储在一起,方便统计一类数据的信息。

二、Redis 安装与部署

(宝塔等服务器管理程序可以一键安装部署)
官网下载

注意,Redis Stack是另外一个产品,是由多个模块组成的。此外,Redis官方的产品,是不支持Windows系统的。
笔者使用的是Redis 7.0。

2.1 安装环境

测试gcc环境,确认是否安装C环境(一般都自带)

gcc --version

如果没有的化,需要安装C语言编译环境。
笔者使用的是yum命令,如果是其他Linux社区的虚拟机请自行查阅相关命令。

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

2.2 安装redis

tar -zxvf redis-7.0.2.tar.gz

完成后进入解压后的文件,(如下图)在redis-7.0.2目录下,
在这里插入图片描述
在这里插入图片描述

使用编译命令make,完成编译操作,以保证兼容当前平台。

若出现Jemalloc/jemalloc.h致命错误,确定是否gcc安装成功。若已成功,可以尝试用make distclean,清楚所有的编译文件,再试一次。(笔者直接成功的,因此不清楚是否是gcc版本问题或是其他原因)

成功编译了以后,调用install完成文件安装。

make installl

可以在该文件下进行测试,以保证正确编译、安装。

make test

默认执行程序安装在/usr/local/bin 文件下
在这里插入图片描述

  • redis-benchmark:性能测试工具
  • redis-check-rdb(dump):修复有问题的RDB文件(快照文件)
  • redis-check-aof:修复有问题的AOF文件(记录输入命令)
  • redis-sentinel:Redis集群使用
  • redis-server:服务器启动命令
  • redis-cli:客户端操作入口

2.3 启动

2.3.1 前台启动

就是通过命令行启动它

redis-server

在这里插入图片描述

2.3.2 后台启动

即通过配置文件启动。
我们将我们解压文件中的redis.conf 复制导 /etc 下,通过修改文件中的 daemonize nodaemonize yes,即可。
在这里插入图片描述
通过启动下述命令即可。

redis-server /etc/redis.conf

可以看到已经启动了
在这里插入图片描述

2.4 连接与关闭

通过redis-cli从客户端连接
在这里插入图片描述

  • 前台通过ctrl+c可以直接关闭
  • 通过 redis-cli shutdown 关闭(已连接则直接shutdown)
  • 通过kill命令关闭

三、 Redis 基本

开源的键值对存储系统。默认端口为6379。

基本类型:

  • string
  • list
  • set
  • zset:有序集合
  • hash

有 push/pop、add/remove与取 交集并集 等操作。操作也都是原子性的。

Redis会周期性的把更新的数据写入磁盘或把修改操作写入追加的记录文件之中。也实现了主从同步。

通常配合关系型数据库做高速缓存。

默认有16个数据库,0~15,初始默认使用0号数据库。切换数据库:

select <dbid,数据库编号>

在这里插入图片描述

3.1 Redis 与 Memcache 区别

  • Memecache:
    1. 支持数据类型较单一
    2. 不支持持久化操作,只能在内存中存储
    3. 多线程+锁
  • Redis:
    1. 支持类型较多
    2. 支持持久化与内存存储
    3. 单线程+多路IO复用

3.2 Redis 的单线程与多路复用

3.2.1 多路复用

指的是使用一个线程来检查多个文件描述符(socket)的就绪状态。比如使用select,poll函数,传入多个文件描述符,如果有一个文件描述符就绪,则返回,否则阻塞直到超时。得到就绪态后,及逆行真正的操作可以在同一个线程里面执行,也可以启动线程执行。

3.2.2 单线程与多路复用原理

请求1
处理
请求2
请求3
文件信息
...

请求方发出请求后,就可以做其他事情了。处理的部分有结果后,会返回结果给请求方。

3.3 基本操作与数据类型

连接上后,我们进行操作。
在这里插入图片描述
操作是原子的,因为它是单线程+多路IO。

3.3.1 key的基础操作

查看所有key

keys *

添加key或修改值,有效时间无限

set <key> <value>

获取value

get <key>

key是否存在

exists <key>

键的类型

type <key>

删除键

del <key>

非阻塞删除,仅将keykeyspace元数据中删除,真正的删除会在后续异步操作

unlink <key>

设置或更新key的有效时间

expire <key> <time,单位为秒>

查看key有效时间,-2表示已经过期,-1表示永不过期,正整数表示还有多久过期

ttl <key>

此外,redis的范围操作大多数都是闭区间,而非我们常用的左闭右开区间。

3.3.2 库操作

切换库(默认0~15)

select <index>

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

dbsize

清空当前库,后面可以选择异步或同步操作

flushdb

清除全部库,后面可以选择异步或同步操作

flushall

3.3.3 string类型操作

  • Redis中最基本的类型,value最大为512MB。
  • 是二进制安全的。可以以字符串的形式存储图片,视频,序列化对象等。

二进制安全(binary safe)是一种主要用于字符串操作函数相关的计算机编程术语。一个二进制安全函数,其本质上将把输入内容作为原始的、无任何特殊格式意义的数据流进行处理。

比如C/C++字符数组以’\0’结束,ASCLL码与二进制不能完全对等转等等。如果我们将二进制存储为字符串,或将字符串转换为二进制,就会出问题。


添加key或修改值,有效时间无限

set <key> <value>

获取value

get <key>

设置key并设置有效时间

setex <key> <time,单位为秒><value>

增加字符串,返回加入后的总长度

append <key> <value>

获取值的长度

strlen <key>

取得旧值,同时设置新值

getset <key> <value>

设置key的值,,有效时间无限。但它不能覆盖或替换已有值。即,key必须不存在。

setnx <key> <value>

获取范围值,类似java中的String.substring(),C++中的string.substr(),-1代表末尾,是闭区间

getrange <key><start><end>

设置范围值,从0开始

setrange <key><start> <value>

批量设置

mset <key1> <value1> <key2> <value2>…

批量设置不存在的key(原子性,一个失败全部失败)

msetnx <key1> <value1> <key2> <value2>…

批量获取

mget <key1> <value1> <key2> <value2>…

3.3.3.1 数字值操作

值自增1,只能对数字值操作,返回结果

incr <key>

值自减1,只能对数字值操作,返回结果

decr <key>

自定义自增步长,只能对数字值操作,负数就是自减,返回结果

incrby <key> <步长>

自定义自增步长,只能对数字值操作,负数就是自增,返回结果

decrby <key> <步长>

3.3.3.2 数据结构

结构为简单动态字符串(Simple Dynamic String,SDS)。是一个可以修改的字符串,实现上类似Java的ArrayList或者C++的Vector,使用冗余分配,减少内存频繁分配。

  • capacity:为实际分配空间
  • len:使用了的空间
  • 当长度小于1MB时,扩容采取2倍扩容(capacity = capacity << 1),超过了后,采取每次扩容1MB空间。注意,最大长度:capacity <= 512MB

3.3.4 List列表操作

单键多值。即一个键对应一个列表。可以从列表的首尾(左右)添加元素或者删除元素。

底层实际是一个双向链表,对双端的操作性能很高,通过索引下表操作中间节点性能较差。


从左边/右边(首尾)插入一个或多个值

lpush/rpush <key> <value1> <value2>…

从左边/右边(首尾)弹出一个值。如果值全部弹出,键也被销毁。

lpop/rpop <key>

依照索引下标获取元素(首尾),-1代表末尾

lrange <key> <start> <end>

key1右侧弹出一个值,插入key2左侧

rpoplpush <key1> <key2>

索引下标获取值

lindex <key> <index>

获取列表长度

llen <key>

插入值,在value之后/前(靠近左侧/首部为前,取第一个值相同的)插入newvalue

linsert <key> before/after <value> <newvalue>

从左侧(首部)删除,前number个value

lrem <key> <number> <value>

将index处的值替换为value

lset <key> <index> <value>

3.3.4.1 数据结构

List的数据结构为快速链表(quickList)

  1. 在列表元素较少的情况下,会使用一块连续的内存存储,这个结构是ziplist(压缩链表)。他将所有的元素紧挨着一起存储,分配的是一块连续的内存。因为普通链表需要的附加指针空间太大,会浪费空间。比如列表里只是int类型的数据,结构还需要两个额外的指针prevnext。因此一开始,这只是使用一块连续地址存储。

  2. 当数据量比较多的时候,会变成quickList。即,多个压缩链表为节点。

next
prev
next
prev
next
prev
ziplist1
ziplist2
ziplist3
ziplist4

3.3.5 Set集合类型操作

功能与list类似,但是可以自动排除重复数据

它是string类型的无序集合,底层是一个value为null的hash表。因此添加,删除,查找复杂度为O(1)。

可以看作Java里面的hashset和C++里面的unordered_set。


将一个或多个成员元素加入到集合key中,成功几个返回几个数(重复则失败)

sadd<key> <value1> <value2> …

取出集合中的所有值

smembers <key>

判断集合之中是否含有该<value>值,有为1,无为0。

sismember <key> <value>

返回该集合的元素个数

scard <key>

删除集合中的某个元素

srem <key> <value1> <value2> …

从集合中随机弹出一个值

spop <key>

随机从集合中取出n个值。但是不会从集合中删除。

srandmember <key> <n>

3.3.5.1 集合间操作

将集合中的一个值移动到另一个集合

smove <source> <destination> <value>

返回连个集合的交集

sinter <key1> <key2>

返回两个集合的并集

sunion <key1> <key2>

返回两个集合的差集,<key1>包含,<key2>不包含

sdiff <key1> <key2>

3.3.5.2 数据结构

Set结构式通过dict字典实现的,字典则是用hash表实现的。(类似于Java 中,hashset是基于hashmap实现的)

3.3.6 Hash哈希类型

是一个键值对集合。

是一个string类型的field和value的映射表。用于存储对象。

类似于Java中的map<String,Object>。


向hash表中加入数据

hset <key> <field> <value>

从hash表中,取出<field>中的<value>

hget <key> <field>

批量设置hash中<field>的值

hmset <key1> <field1> <value1> <field2> <value2>

查看是否存在

hexists <key> <field>

列出hash中所有的<field>

hkeys <key>

列出hash中所有的<value>

hvals <key>

为hash表key中的域值增加或减少<increment>

hincrby <key> <field> <increment>

当hash表中<field>不存在时,<field>的值设为<value>

hsetnx <key> <filed> <value>

3.3.6.1 数据结构
  1. 我们序列化或者JSON的写法中,可以是‘user’ :{‘id’ = ‘1’,‘name’=‘zhangsan’},但是这样做修改时,需要将其读出为对象,较麻烦。
  2. 我们可以将其分开直接存储,user:id,user:name zhangsan,这种方式会让数据分散,使用时会比较麻烦。
1
key
value
user:id
user:name
zhangsan
  1. Redis hash中,就采用了下图这种方式。修改时,只需要通过key + field找到。
key
value
user
id 1,name zhangsan

当filed-value给的长度较短且个数较少时,使用的是ziplist

否则使用hashtable

3.3.7 Zset有序集合

与set类似,无重复元素的字符串集合。

通过一个**评分(score)**的方式,从最低分到最高分的方式排序。注意,集合成员是唯一的,但是评分可以重复。


向有序集合中加入一个或多个元素

zadd <key> <score1> <value1> <scroe2> <value2>…

返回有序集合中的,下标在<start> <end>之间的元素(有 WITHSCORES 会显示评分)

zrange <key> <start> <end> [WITHSCORES]

在这里插入图片描述
返回score值介于<min>到<max>之间(含两端)的成员,limit offset count即是偏移数目(score从小到大)

zrangebyscore <key> <min> <max> [WITHSCORES] [limit offset count]

在这里插入图片描述

从大到小排列

zrevrangebyscore <key> <max> <min> [WITHSCORES] [limit offset count]

为某个值增加评分

zincrby <key> <increment> <value>

删除某个值

zrem <key> <value>

统计评分在<min> 到 <max>中,元素的个数

zcount <key> <min> <max>

返回改制在集合中的排名,从0开始

zrank <key> <value>

3.3.7.1 数据结构

SortedSet(zset),一方面等价于Java中的Map<String,Double>,另一方面等价于TreeSet,内部会按照权重score进行排序,得到元素的名次以及通过范围来获取元素列表。

1.使用了hash类型,用于关联key、元素value和权重score。
2.使用了跳跃表,以此到达给value排序且能够用score的范围获取元素列表。

3.3.7.2 跳表

参考Skip List–跳表(全网最详细的跳表文章没有之一)
一般的有序链表

1
2
3
32
51
NULL

跳表

2
3
51
1
1
3
1
3
32
51
  1. 从上到下,找到最接近且小于目标的数
  2. 结束后,对比是否相同

3.3.8 Bitmaps位映射

本身不是数据类型,而是字符串string类型。通过单独的一套命令,它可以对字符串进行位操作,来满足我们对位运算的需求。当然,只能是0或1。(若对其用stiring的命令,则会变为对应的编码格式)

可以理解为,C++中的bitset,通过下标来取值(偏移量)。


设置Bitmaps偏移量,从0开始偏移。

setbit <key> <offset> <value>

在这里插入图片描述
获取值

getbit <key> <offset>

在这里插入图片描述
统计bit位为1的数目,可不填[start end],表示范围为start到end闭区间

getcount <key> [start end]

复合操作(operation 与或非 and not xor),destkey是用来存储的key,后面则是操作的key,返回的是1的个数

bitop <operation> <destkey> <key1> [<key2> <key3> …]

3.3.9 HyperLogLog

用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。因此用更少的空间,表示更多的值。

基数则是不重复元素,比如{1,1,2,2,3,4,},基数就是{1,2,3,4}

注意,它不存储元素,他只是对不重复元素计数。

相关链接HyperLogLog 算法详解


添加元素

pfadd <key> <element1> [<element2> … ]

在这里插入图片描述

统计数目

pfcount <key>

合并多个HyperLogLog

pfmerge <destkey> <sourcekey> [<sourcekey> …]

3.3.10 Geospatial

存储地理信息。用于经纬度相关操作。


添加 多个地理信息,经度(-180~180) 纬度(-85.05112878~85.05112878) 名称

geoadd<key> <longitude> <latitude> <member> [<longitude> <latitude> <member>]

获取指定地区坐标

geopos <key> <member> [<member> …]

计算两坐标间的直线距离,[m,km,ft,mi],单位,米、千米、英里、英尺

geodist <key> <member1> <member2> [m,km,ft,mi]

以某一经纬度为中心,计算半径以内的元素,radius就是半径

georadius <key> <longitude> <latitude> <radius> m|km|ft|mi

3.3.11 stream 流

Redis 5.0 版本新增加的数据结构。主要用于消息队列(MQ,Message Queue)。

订阅与发布模式(见后面)虽然有消息队列功能,但不能持久化。如果出现网络断开、Redis 宕机等,消息就会被丢弃。

而 Redis Stream 提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每一个客户端的访问位置,还能保证消息不丢失。

3.3.11.1 结构

Redis Stream 的结构如下所示,它有一个消息链表,将所有加入的消息都串起来,每个消息都有一个唯一的 ID 和对应的内容

ID1、ID2、ID3…是消息队列,代表发布者发布的消息。

Consumer Group ,last_delivered_id
ID2
Consumer Group ,last_delivered_id
ID6
consumer,pending_ids[]
consumer,pending_ids[]
ID1
ID3
ID4
ID5
ID7
ID8
  • Consumer Group :消费组,使用 XGROUP CREATE 命令创建,一个消费组有多个消费者(Consumer)。
  • last_delivered_id :游标,每个消费组会有个游标 last_delivered_id,任意一个消费者读取了消息都会使游标 last_delivered_id 往前移动。
  • Consumer :消费者,即订阅的人。
  • pending_ids :消费者(Consumer)的状态变量,作用是维护消费者的未确认的 id。 pending_ids 记录了当前已经被客户端读取的消息,但是还没有 ack (Acknowledge character:确认字符)。

3.4 配置文件的一些内容

一般位于

/etc/redis.conf

文件大小写不敏感
请添加图片描述

在这里插入图片描述
单位表示,且只支持字节。

在这里插入图片描述
用于包含公共部分

在这里插入图片描述
此处是导入模块。Redis的模块采用的是动态链接库的方式,外部模块可对Redis进行功能性扩展。(此处是启动时载入,也有在运行时加载部分)

在这里插入图片描述
网络部分,其中bind表示限制访问IP。此处表示只能本地连接,一般将其注释即可。(同时把保护模式改为弄no)
在这里插入图片描述

protected-mod no

连接队列,用于记录未完成已完成三次握手的队列。默认值是511

tcp-backlog 511

未操作连接中断时间,单位为秒,为0时永不超时

timeout 0

心跳时间,即检测连接是否活着。单位为秒。若连接已经无效,则中断。

tcp-keepalive 300

超时是指为操作,但是连接还是有效的没有中断。心跳时间是用于判断连接是否有效。就是挂机和掉线的区别。

GENERAL 一般设置

用于设置为守护进程,后台启动

daemonize yes

Redis每次操作就有一个进程号,当以守护进程进行时,进程号就会保存在里面。只有一个进程号,这样用于防止启动多个脚本。

pidfile /var/run/redis_6379

日志级别:debug(详细信息) verbose(有用信息) notice(重要信息)warning(警告信息)

loglevel notice

日志存储位置

logfile “”

库数目

database 16

SECURITY 安全设置
若要设置密码,需要取消该注释

#requirepass <password>

或者连接后用如下命令,设置密码

config set requirepass <password>

用如下命令查看密码

config get requirepass

LIMITS 限制设置
设置最大连接客户端

maxclients 10000

最大内存占用(单位为字节 byte)

maxmemory-policy <byte>

最大样本数量(一般取3~7,样本数越小越不精确,但性能消耗越小),用于LRU和TTL算法中的估算(缓存淘汰算法)。

maxmemory-samples <value>

3.5 发布与订阅

频道1
频道2
频道1
发布者pub1
订阅者sub1
订阅者sub2
订阅了频道1
订阅了频道2
  1. 发布者发布消息,订阅者就会接收到消息。
  2. 发布者发布的消息可通过不同频道传达,订阅者只会收到订阅的频道中的消息

3.5.1 设置发布与订阅

首先在命令行中创建一个连接进程,订阅频道1

subscribe channel1

在这里插入图片描述
再在另一个命令行中,创建一个连接线程,发布一个消息
可以看到,返回了订阅数目

publish channel1 hello

在这里插入图片描述
此时另一边会发现,已经收到了消息

在这里插入图片描述

注意,消息没有持久化,后面订阅的无法收到前面的消息。

参考文献

[1]【尚硅谷】Redis6入门到精通 超详细教程
[2]菜鸟教程-Redis
[3]Redis-官方文档

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很高兴您对Redis感兴趣!Redis是一款开源的内存数据库,它以键值对的方式存储数据,并提供了丰富的数据结构和功能。以下是关于Redis的一些笔记: 1. Redis的应用场景:Redis被广泛应用于缓存、消息队列、排行榜、计数器、分布式锁等场景,因为它具备高性能、高并发、持久化和分布式特性。 2. 数据结构:Redis支持多种数据结构,包括字符串、哈希表、列表、集合和有序集合。这些数据结构可以满足不同的业务需求。 3. 缓存:Redis做为缓存的优势在于它将数据存储在内存中,读写速度非常快。可以通过设置过期时间、LRU算法等来控制缓存的失效策略。 4. 持久化:Redis提供了两种持久化方式,分别是RDB和AOF。RDB是将内存中的数据定期保存到磁盘中,AOF则是将每条写命令追加到文件末尾。 5. 主从复制:Redis支持主从复制机制,当主节点发生故障时,从节点可以顶替主节点继续提供服务。主从复制还可以用于读写分离,提高系统并发能力。 6. 事务:Redis支持简单的事务操作,通过MULTI和EXEC命令可以将多个命令封装为一个事务进行执行,保证了操作的原子性。 7. Lua脚本:Redis支持通过Lua脚本的方式执行一系列命令,可以在服务端实现复杂逻辑,减少网络开销。 这些只是Redis的一些基础知识,如果您对特定的问题或者进一步深入了解Redis有兴趣,我可以为您提供更多的信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值