阶段十-分布式-Redis01

第一章 Redis入门

1.1 节 什么是NoSql型数据库

 NoSQL ,泛指非关系型的数据库, NoSQL Not Only SQL,它可以作为关系型数据库的良好补充。 NoSQL 不依赖业务逻辑方式存储,而以简单的key-value模式存储。因此大大的增加了数据库的扩展能力。NoSQL与SQL数据库区别对比如下:

SQLNoSQL
数据结构结构化非结构化
数据关联关联的无关联的
查询方式SQL查询非SQL查询
事务特征ACIDBASE
存储方式磁盘内存
扩展性垂直水平
使用场景数据结构固定;相关业务对数据安全性、一致性要求较高数据结构不固定;对一致性,安全性要求不高,对性能要求高

常见NoSQL数据库:

  • Reids (键值对)

  • MongoDB(文档类型)

  • HBase (列类型)

  • Neo4j(Graph类型)

1.2 节 Reids介绍

Redis诞生于2009年全称是Remote Dictionary Server,远程词典服务器,是一个基于内存的键值型NoSQL数据库。其主要特征如下:

  • 键值(key-value)型,value支持多种不同数据结构,功能丰富;

  • 单线程,每个命令具备原子性;

  • 低延迟,速度快(基于内存、IO多路复用、良好的编码);

  • 支持数据持久化;

  • 支持主从集群、分片集群;

  • 支持多语言客户端;

1.3 节 Reids 安装

需要的文件

链接:https://pan.baidu.com/s/10o9t5OOX2A4s98vnFnJwmA?pwd=rxtc 
提取码:rxtc

基于Linux服务器来部署项目

1.4.1 Redis安装

【1】依赖库,Redis是基于C语言编写的,因此首先需要安装Redis所需要的gcc依赖:

yum install -y gcc tcl

【2】上传安装包并解压,然后将资料提供的Redis安装包上传到虚拟机的/usr/local/目录

【3】解压缩:

tar -xzf redis-6.2.6.tar.gz

【4】进入redis目录:

cd redis-6.2.6

【5】运行编译命令:

make && make install

默认的安装路径是在 /usr/local/bin目录下:该目录已经默认配置到环境变量,因此可以在任意目录下运行这些命令。其中:

  • redis-cli:是redis提供的命令行客户端

  • redis-server:是redis的服务端启动脚本

  • redis-sentinel:是redis的哨兵启动脚本

redis的启动方式有很多种,例如:

  • 默认启动

  • 指定配置启动

  • 开机自启

1.4.2 默认启动

安装完成后,在任意目录输入redis-server命令即可启动Redis:

redis-server

这种启动属于前台启动,会阻塞整个会话窗口,窗口关闭或者按下CTRL + C则Redis停止。不推荐使用。

1.4.3 指定配置启动

如果要让Redis以后台方式启动,则必须修改Redis配置文件,就在我们之前解压的redis安装包下(/usr/local/redis-6.2.6),名字叫redis.conf:

我们先将这个配置文件备份一份:

cp redis.conf redis.conf.bck

修改redis.conf文件中的一些配置:

# 允许访问的地址,默认是127.0.0.1,会导致只能在本地访问。修改为0.0.0.0则可以在任意IP访问,生产环境不要设置为0.0.0.0
bind 0.0.0.0
# 守护进程,修改为yes后即可后台运行
daemonize yes 
# 密码,设置后访问Redis必须输入密码
# requirepass 123456

Redis的其它常见配置:

# 监听的端口
port 6379
# 工作目录,默认是当前目录,也就是运行redis-server时的命令,日志、持久化等文件会保存在这个目录
dir .
# 数据库数量,设置为1,代表只使用1个库,默认有16个库,编号0~15
databases 16
# 设置redis能够使用的最大内存
maxmemory 512mb
# 日志文件,默认为空,不记录日志,可以指定日志文件名
logfile "redis.log"

启动Redis:

# 进入redis安装目录 
cd /usr/local/redis-6.2.6
# 启动
redis-server redis.conf

停止服务:

# 利用redis-cli来执行 shutdown 命令,即可停止 Redis 服务,
# 因为之前配置了密码,因此需要通过 -u 来指定密码
redis-cli -u 123456 shutdown

1.4.4 开机自启

我们也可以通过配置来实现开机自启。

首先,新建一个系统服务文件:

vi /etc/systemd/system/redis.service

内容如下:

[Unit]
Description=redis-server
After=network.target[Service]
Type=forking
ExecStart=/usr/local/bin/redis-server /usr/local/redis-6.2.6/redis.conf
PrivateTmp=true[Install]
WantedBy=multi-user.target

然后重载系统服务:

systemctl daemon-reload

现在,我们可以用下面这组命令来操作redis了:

# 启动
systemctl start redis
# 停止
systemctl stop redis
# 重启
systemctl restart redis
# 查看状态
systemctl status redis

执行下面的命令,可以让redis开机自启:

systemctl enable redis

1.5 节 Redis 基于Docker安装

【1】下载镜像

docker pull redis:6.2.6

【2】运行容器

docker run --name redis -d -p 6379:6379 redis:6.2.6

1.6 节 Redis桌面客户端

安装完成Redis,我们就可以操作Redis,实现数据的CRUD了。这需要用到Redis客户端,包括:

  • 命令行客户端

  • 图形化桌面客户端

  • 编程客户端

1.6.1 Redis命令行客户端

Redis安装完成后就自带了命令行客户端:redis-cli,

redis-cli [options] [commonds]

其中常见的options有:

  • -h 127.0.0.1:指定要连接的redis节点的IP地址,默认是127.0.0.1

  • -p 6379:指定要连接的redis节点的端口,默认是6379

  • -a 123456:指定redis的访问密码

其中的commonds就是Redis的操作命令,例如:

  • ping:与redis服务端做心跳测试,服务端正常会返回pong

不指定commond时,会进入redis-cli的交互控制台

1.6.2 图形化桌面客户端

【1】在资料中可以找到Redis的图形化桌面客户端:

【2】解压缩后,运行安装程序即可安装:

【3】安装完成后,在安装目录下找到rdm.exe文件:

【4】建立连接,点击左上角的连接到Redis服务器按钮:

【5】在弹出的窗口中填写Redis服务信息:

Redis默认有16个仓库,编号从0至15. 通过配置文件可以设置仓库数量,但是不超过16,并且不能自定义仓库名称。如果是基于redis-cli连接Redis服务,可以通过select命令来选择数据库  

# 选择 0号库
select 0

第二章 Redis基本知识

2.1 节 Reids 多路复用

在Redis6/7中,非常受关注的第一个新特性就是多线程。

这是因为,Redis一直被大家熟知的就是它的单线程架构(Redis6以前是单线程架构),虽然有些命令操作可以用后台线程或子进程执行(比如数据删除、快照生成、AOF重写)。但是,从网络IO处理到实际的读写命令处理,都是由单个线程完成的。

随着网络硬件的性能提升,Redis的性能瓶颈有时会出现在网络IO的处理,也就是说,单个主线程处理网络请求的速度跟不上底层网络硬件的速度,

为了应对这个问题:

采用多个IO线程来处理网络请求,提高网络请求处理的并行度,Redis6/7就是采用的这种方法。

但是,Redis的多线程只是用来处理网络请求的,对于读写操作命令Redis仍然使用单线程来处理。这是因为,Redis处理请求时,网络处理经常是瓶颈,通过多个IO线程并行处理网络操作,可以提升实例的整体处理性能。而继续使用单线程执行命令操作,就不用为了保证Lua脚本、事务的原子性,额外开发多线程互斥加锁机制了(不管加锁操作处理),这样一来,Redis线程模型实现就简单了

2.2 节 Redis 默认16 库

Redis是一个字典结构的存储服务器,一个Redis实例提供了多个用来存储数据的字典,客户端可以指定将数据存储在哪个字典中。 这与在一个关系数据库实例中可以创建多个数据库类似(如下图所示),所以可以将其中的每个字典都理解成一个独立的数据库。

Redis默认支持16个数据库,可以通过调整Redis的配置文件redis/redis.conf中的databases来修改这一个值,设置完毕后重启Redis便完成配置。

2.2.1 切换数据库

语法结构:

select number

示例:

127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> get k1
"v1"
# 切换数据库,获取不到k1数据
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> get k1
(nil) 

2.2.2 清空当前库

Redis Flushdb 命令用于清空当前数据库中的所有 key。

语法结构:

127.0.0.1:6379> FLUSHDB

2.2.3 通杀全部库

Redis Flushall 命令用于清空整个 Redis 服务器的数据(删除所有数据库的所有 key )。

语法结构:

redis 127.0.0.1:6379> FLUSHALL

2.3 节 Redis数据类型_key键

2.3.1 keys

查看当前库中所有的key 。

语法结构:

keys *

有3个通配符 *, ? ,[]

  • *: 通配任意多个字符

  • ?: 通配单个字符

  • []: 通配括号内的某1个字符

注意: 生产已经禁止。因为长时间阻塞redis而导致其他客户端的命令请求一直处于阻塞状态。 更安全的做法是采用scan。

新版本也进行了替代:

redis-cli -h 127.0.0.1 -p 6379 -a 123456 --scan "*"

2.3.2 exists

判断某个key是否存在,返回1表示存在,0不存在。

语法结构:

exists key
#查看k1是否存在,如果存在返回1
exists k1  
# 查看k1 k2 k3是否存在,如果k1 k2存在,k3不存在,则返回2
exists k1 k2 k3

注意: 可以设置多个key,只返回存在的个数,但不返回哪一个存在/不存在。

2.3.3 type

查看当前key 所储存的值的类型。返回当前key所储存的值的类型, 如string 、list等。

语法结构:

type key

2.3.3 del

删除已存在的key,不存在的 key 会被忽略。

语法结构:

del key

示例:

可以设置多个key,返回删除成功的个数。

# 删除k1,如果成功返回1,失败返回0
del k1
# 删除k1 k2 k3,如果k1 k2存在,k3不存在,则返回2
del k1 k2 k3

2.3.4 expire

给key设置time秒的过期时间。设置成功返回 1 。 当 key 不存在返回 0。

语法结构:

expire key time

示例:

# 给k1设置10秒后过期
expire k1 10

2.3.4 ttl

以秒为单位返回 key 的剩余过期时间。

语法结构:

ttl key

注意: 当 key 不存在时,返回 -2 。 当 key 存在但没有设置剩余生存时间时,返回 -1 。 否则,以秒为单位,返回 key 的剩余生存时间。

2.3.5 persist

移除给定 key 的过期时间,使得 key 永不过期。

语法结构:

persist key

注意: 当过期时间移除成功时,返回 1 。 如果 key 不存在或 key 没有设置过期时间,返回 0 。

第三章 Redis 数据类型

3.1 节 String

3.1.1 简介

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

3.1.2 常用命令

【1】set

用于设置给定 key 的值。如果 key 已经存储其他值, set 就重写旧值,且无视类型。

语法格式:

set key value

【2】get

用于获取指定 key 的值。如果 key 不存在,返回 nil 。

语法格式:

get key

【3】append

将给定的value追加到key的值的末尾。

语法格式:

append key value

注意: 如果 key 已经存在并且是一个字符串, append 命令将 value 追加到 key 原来的值的末尾。 如果 key 不存在, append 就简单地将给定 key 设为 value ,就像执行 set key value 一样。

【4】strlen

获取指定 key 所储存的字符串值的长度。当 key 储存的不是字符串值时,返回一个错误。

语法格式:

strlen key

【5】setex

给指定的 key 设置值及time 秒的过期时间。如果 key 已经存在, setex命令将会替换旧的值,并设置过期时间。

语法格式:

setex key time value

【6】setnx

只有在key不存在时设置key的值

语法格式:

setnx key value

【7】getrange

获取指定区间范围内的值,类似between........and 的关系,下标的起始与结束

语法格式:

getrange key start end

【8】setrange

设置指定区间范围内的值,类似between........and 的关系,下标的起始与结束

语法结构:

setrange key offset value

【9】incr

将 key 中储存的数字值增一。

语法格式:

incr key

注意: 如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 incr 操作。 如字符串类型的值不能表示为数字、或者是其他类型,那么返回一个错误。

【10】decr

将 key 中储存的数字值减一。

语法格式:

decr key

注意:

如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 decr 操作。 如字符串类型的值不能表示为数字、或者是其他类型,那么返回一个错误。

【11】incrby/decrby key step

将key存储的数字值按照step进行增减。

语法格式:

incrby/decrby key 步长

注意:

如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 incrby/decrby 命令。 如字符串类型的值不能表示为数字、或者是其他类型,那么返回一个错误。

【12】mset

同时设置一个或多个 key-value

语法格式:

mset key1 value1 key2 value2

【13】mget

返回所有(一个或多个)给定 key 的值。

语法格式:

mget key1 key2

【14】getset

将给定key值设为value,并返回key的旧值(old value),简单一句话(先get然后立即set)。

语法格式:

getset key value

3.1.3 使用场景

value 除了是字符串以外还可以是数字。

  • 计数器

  • 统计多单位的数量

  • 粉丝数

  • 对象缓存存储

  • 分布式锁

3.2 节 List

3.2.1 简介

List是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。底层是一个双向链表, 对两端操作性能极高,通过索引操作中间的节点性能较差。

一个List最多可以包含 $2^{32}-1$个元素 ( 每个列表超过40亿个元素)。

3.2.2 常用命令

【1】lpush/rpush

从左边(头部)/右边(尾部)插入一个或多个值。

语法结构:

lpush/rpush key1 value1 value2 value3……

示例:

#从左边放入v1 v2 v3
127.0.0.1:6379> lpush k1 v1 v2 v3
(integer) 3

【2】lrange

返回key列表中的start和end之间的元素(包含start和end)。 其中 0 表示列表的第一个元素,-1表示最后一个元素。

语法结构:

lrange key start end

示例:

#取出列表里前3个值,结果为v3 v2 v1
127.0.0.1:6379> lrange k1 0 2
#取出列表里全部值,结果为v3 v2 v1 v4 v5 v6
127.0.0.1:6379> lrange k1 0 -1

【3】lpop/rpop

移除并返回第一个值或最后一个值。

语法格式:

lpop/rpop key

示例:

# lpop k1 从列表中删除v3,并返回,当前列表全部值v2 v1 v4 v5 v6
127.0.0.1:6379> lpop k1
"v3"# rpop k1 从列表中删除v6,并返回,当前列表全部值v2 v1 v4 v5
127.0.0.1:6379> rpop k1
"v6"

注意:

值在键在,值光键亡

【4】lindex

获取列表index位置的值(从左开始)。

语法结构:

lindex key index

【5】llen

获取列表长度。

语法结构:

llen key

【6】lrem

从左边开始删除与value相同的count个元素。

语法结构:

lrem key count value

示例:

#从左边开始删除k1列表中2个v1元素
lrem k1 2 v1

【7】linsert

在列表中value值的前边/后边插入一个new value值(从左开始)。

语法结构:

linsert key before/after value newvalue

示例:

#  在v1前面插入一个v5
linsert k1 before v1 v5

【8】lset

将索引为index的值设置为value

语法结构:

lset key index value

3.2.3 使用场景

  • 消息队列

  • 排行榜

  • 最新列表

3.3 节 Set

3.3.1 简介

与List类似是一个列表功能,但Set是自动去重的,当需要存储一个列表数据,又不希望出现重复数据时,Set是一个很好的选择。 Set是String类型的无序集合,它底层其实是一个value为null的hash表,所以添加、删除、查找的时间复杂度都是O(1)。

【1】sadd

将一个或多个元素添加到集合key中,已经存在的元素将被忽略。

语法结构:

sadd key value1 value2……

【2】smembers

取出该集合的所有元素。

语法结构:

smembers key

【3】sismember

判断集合key中是否含有value元素,如有返回1,否则返回0。

语法结构:

sismember key value

【4】scard

返回该集合的元素个数。

语法结构:

scard key

【5】srem

删除集合中的一个或多个成员元素,不存在的成员元素会被忽略。

语法结构:

srem key value1 value2……

【6】spop

随机删除集合中一个元素并返回该元素。

语法结构:

spop key

【7】srandmember

随机取出集合中count个元素,但不会删除。

语法结构:

srandmember key count

【8】smove

将value元素从sourcekey集合移动到destinationkey集合中。

语法结构:

smove sourcekey destinationkey value

注意:

如果 sourcekey集合不存在或不包含指定的 value元素,则smove 命令不执行任何操作,仅返回 0 。

【9】sinter

返回两个集合的交集元素。

语法结构:

sinter key1 key2

【10】sunion

返回两个集合的并集元素。

语法结构:

sunion key1 key2

【11】sdiff

返回两个集合的差集元素(key1中的,不包含key2)

语法结构:

sdiff key1 key2

3.3.3 使用场景

  • 黑白名单

  • 随机展示

  • 好友

  • 关注人

  • 粉丝

  • 感兴趣的人集合

3.4 节 Hash

3.4.2 常用命令

【1】hset

给key集合中的field赋值value。

语法结构:

hset key field value

注意:

如果哈希表不存在,一个新的哈希表被创建并进行 HSET 操作。

如果字段已经存在于哈希表中,旧值将被重写。

【2】hget

从key哈希中,取出field字段的值。

语法结构:

hget key field

【3】hmset

批量设置哈希的字段及值。

语法结构:

hmset key field1 value1 field2 value2……

【4】hexists

判断指定key中是否存在field

语法结构:

hexists key field

【5】hkeys

获取该哈希中所有的field。

语法结构:

hkeys key

【6】hvals key

获取该哈希中所有的value。

语法结构

hvals key

【7】hincrby

为哈希表key中的field字段的值加上增量increment。

语法结构:

hincrby key field increment

注意:

  • 增量也可以为负数,相当于对指定字段进行减法操作。

  • 如果哈希表的 key 不存在,一个新的哈希表被创建并执行 hincrby 命令。

  • 如果指定的字段不存在,那么在执行命令前,字段的值被初始化为 0 。

  • 对一个储存字符串值的字段执行 hincrby 命令将造成一个错误。

【8】hdel

删除哈希表 key 中的一个或多个指定字段,不存在的字段将被忽略。

语法结构:

hdel key field1 field2……

【9】hsetnx

给key哈希表中不存在的的字段赋值 。

语法结构:

hsetnx key field value

3.4.3 使用场景

  • 购物车

  • 存储对象

3.5 节 Zset

3.5.1 简介

Zset与Set非常相似,是一个没有重复元素的String集合。不同之处是Zset的每个元素都关联了一个分数(score),这个分数被用来按照从低分到高分的方式排序集合中的元素。集合的元素是唯一的, 但分数可以重复。有顺序的Set

注意:

因为元素是有序的,所以可以根据分数(score)或者次序(position)来获取一个范围内的元素。

3.5.2 常用命令

【1】zadd

将一个或多个元素(value)及分数(score)加入到有序集key中。

语法结构:

zadd key score1 value1 score2 value2……

示例:

zadd k1 100 java 200 c++ 300 python 400 php

注意:

  • 如果某个元素已经是有序集的元素,那么更新这个元素的分数值,并通过重新插入这个元素,来保证该元素在正确的位置上。

  • 分数值可以是整数值或双精度浮点数。

  • 如果有序集合 key 不存在,则创建一个空的有序集并执行 zadd 操作。

【2】zrange

返回key集合中的索引start和索引end之间的元素(包含start和end)。

语法结构:

zrange key start end [withscores]

示例:

zrange k1 0 -1 返回集合中所有元素
zrange k1 0 -1 withscores 返回集合中所有元素,并携带元素分数

注意:

  • 其中元素的位置按分数值递增(从小到大)来排序。 其中 0 表示列表的第一个元素,-1表示最后一个元素。

  • withscores是可选参数,是否返回分数。

【3】zrangebyscore

返回key集合中的分数minscore 和分数maxscore 之间的元素(包含minscore 和maxscore )。其中元素的位置按分数值递增(从小到大)来排序。

语法结构:

zrangebyscore key minscore maxscore [withscores]

示例:

zrangebyscore k1 200 400 返回200-400分之间的元素递增排序

【4】zincrby

为元素value的score加上increment的值。

语法结构:

zincrby key increment value

示例:

zincrby k1 50 java 给java元素加上50分

【5】zrem

删除该集合下value的元素。

语法结构

zrem k1 php 删除php

【6】zcount

统计该集合在minscore 到maxscore分数区间中元素的个数。

语法结构:

zcount key minscore maxscore

示例:

zcount k1 100 300 统计100分到300分中间元素的个数

【7】zrank

返回value在集合中的排名,从0开始。

语法结构:

zrank key value

示例:

zrank k1 c++ 返回c++排名

3.5.3 使用场景

  • 延时队列

  • 排行榜

  • 限流

 

3.6 节 Bitmaps

3.6.1 简介

在计算机中,用二进制(位)作为存储信息的基本单位,1个字节等于8位。

例如 "abc" 字符串是由 3 个字节组成,计算机存储时使用其二进制表示,"abc"分别对应的ASCII码是97、98、99,对应的二进制是01100001、01100010、01100011,在内存中表示如下:

3.6.2 常用命令

【1】setbit

设置Bitmaps中某个偏移量的值。

语法结构:

setbit key offset value

示例: 记录张三 1月份上班打卡情况

127.0.0.1:6379> setbit zhangsan:1 0 1
(integer) 0
127.0.0.1:6379> setbit zhangsan:1 1 1
(integer) 0
127.0.0.1:6379> setbit zhangsan:1 2 1
(integer) 0
127.0.0.1:6379> setbit zhangsan:1 3 0
(integer) 0
127.0.0.1:6379> setbit zhangsan:1 4 1
(integer) 0
127.0.0.1:6379> setbit zhangsan:1 5 1
(integer) 0
127.0.0.1:6379> setbit zhangsan:1 6 0
(integer) 0

【2】getbit

获取Bitmaps中某个偏移量的值。

语法结构:

getbit key offset

示例:

查看张三1月份 第三天、第四天是否上班

127.0.0.1:6379> getbit zhangsan:1 2
(integer) 1
127.0.0.1:6379> getbit zhangsan:1 3
(integer) 0

【3】bitcount

统计字符串被设置为1的bit数量。一般情况下,给定的整个字符串都会被进行统计,可以选择通过额外的start和end参数,指定字节组范围内进行统计(包括start和end),0表示第一个元素,-1表示最后一个元素。

语法结构:

bitcount key [start end]

示例:统计张三上班天数

127.0.0.1:6379> bitcount zhangsan:1
(integer) 5

【4】bitop

将多个bitmaps通过求交集/并集方式合并成一个新的bitmaps。

语法结构:

bitop and/or destkey sourcekey1 sourcekey2……

示例:

bitop and k3 k1 k2 通过求交集将k1 k2合并成k3
bitop or k3 k1 k2 通过求并集将k1 k2合并成k3

3.6.3 使用场景

  • 活跃天数

  • 打卡天数

  • 登录天数

  • 用户签到

  • 统计活跃用户

  • 统计用户是否在线

  • 实现布隆过滤器

3.7 节 Geospatial

3.7.1 简介

GEO,Geographic,地理信息的缩写。该类型就是元素的二维坐标,在地图上就是经纬度。Redis基于该类型,提供了经纬度设置、查询、范围查询、距离查询、经纬度Hash等常见操作。

3.7.2 常用命令

【1】geoadd

用于存储指定的地理空间位置,可以将一个或多个经度 (longitude)、纬度(latitude)、位置名称(member)添加到指定的 key中。

语法结构:

geoadd key longitude latitude member

示例:

# 将北京的经纬度和名称添加到china
geoadd china 116.405285 39.904989 beijing
# 将成都和上海的经纬度、名称添加到china
geoadd china 104.065735 30.659462 chengdu 121.472644 31.231706 shanghai

【2】geopos

从给定的 key 里返回所有指定名称(member)的位置(经度和纬度),不存在的返回 nil。

语法结构:

geopos key member [member ……]

示例:

返回china中名称为shanghai和beijing的经纬度

geopos china shanghai beijing

【3】geodist

用于返回两个给定位置之间的距离。

语法结构:

geodist key member1 member2 [m|km|ft|mi]

参数说明:

  • m :米,默认单位。

  • km :千米。

  • mi :英里。

  • ft :英尺。

示例:

# 返回shanghai和beijing之间的距离,结果1067597.9668,单位米
geodist china shanghai beijing
# 返回shanghai和chengdu之间的距离,结果1660.0198,单位是千米
geodist china shanghai beijing km【4】georadius

以给定的经纬度(longitude latitude)为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离(radius )的所有位置元素。

语法结构:

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

示例:

#获取经纬度110 30为中心,在china内1200公里范围内的所有元素。
georadius china 110 30 1200 km

3.7.3 使用场景

  • 附近的电影院

  • 附近的好友

  • 离最近的火锅店

3.8 节 HyperLogLog

3.8.1 简介

在我们做站点流量统计的时候一般会统计页面UV(独立访客:unique visitor)和PV(即页面浏览量:page view)。redis HyperLogLog是用来做基数统计的算法,HyperLogLog的优点是:在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且使很小的。

什么是基数?

比如数据集{1,3,5,7,5,7,8},那么这个数据集的基数集为{1,3,5,7,8}, 基数(不重复元素)为5.基数估计就是在误差可接受的范围内,快速计算基数。就是不重复的元素的个数

3.8.2 常用命令

【1】pfadd

将所有元素参数添加到 Hyperloglog 数据结构中。

语法结构:

pfadd key element1 element2……

示例:

如果至少有个元素被添加返回 1, 否则返回 0。

pfadd book1 uid1 uid2 uid3

注意:

添加元素到HyperLogLog中,如果内部有变动返回1,没有返回0。

【2】pfcount

计算Hyperloglog 近似基数,可以计算多个Hyperloglog ,统计基数总数。

语法结构:

pfcount key1 key2……

示例:

pfcount book1             #计算book1的基数,结果为3
pfadd book2 uid3 uid4     #添加两个元素到book2中
pfcount book1 book2       #统计两个key的基数总数,结果为5

【3】pfmerge

将一个或多个Hyperloglog(sourcekey1) 合并成一个 Hyperloglog (destkey )。

语法结构:

pfmerge destkey sourcekey1 sourcekey2……

示例: 比如每月活跃用户可用每天活跃用户合并后计算。

#将book1和book2合并成book,结果为5
pfmerge book book1 book2

3.8.3 使用场景

基数不大,数据量不大就用不上,会有点大材小用浪费空间,有局限性,就是只能统计基数数量,而没办法去知道具体的内容是什么,和bitmap相比,属于两种特定统计情况,简单来说,HyperLogLog 去重比 bitmaps 方便很多,一般可以bitmap和hyperloglog配合使用,bitmap标识哪些用户活跃。

  • 网站PV统计

  • 网站UV统计

  • 统计访问量(IP数)

  • 统计在线用户数

  • 统计每天搜索不同词条的个数

  • 统计文章真实阅读数

第四章 Redis 配置文件

在redis的解压目录下有个重要的配置文件redis.conf

4.1 节 units单位

配置大小单位,开头定义基本度量单位,只支持bytes,大小写不敏感。

4.2 节 INCLUDES

Redis只有一个配置文件,如果多个人进行开发维护,那么就需要多个这样的配置文件,这时候多个配置文件就可以在此通过 include/path/to/local.conf 配置进来,而原本的 redis.conf 配置文件就作为一个总闸。

4.3 节 NETWORK

参数:

  • bind:绑定redis服务器网卡IP,默认为127.0.0.1,即本地回环地址。这样的话,访问redis服务只能通过本机的客户端连接,而无法通过远程连接。如果bind选项为空的话,那会接受所有来自于可用网络接口的连接。

  • port:指定redis运行的端口,默认是6379。由于Redis是单线程模型,因此单机开多个Redis进程的时候会修改端口。

  • timeout:设置客户端连接时的超时时间,单位为秒。当客户端在这段时间内没有发出任何指令,那么关闭该连接。默认值为0,表示不关闭。

  • tcp-keepalive :单位是秒,表示将周期性的使用SO_KEEPALIVE检测客户端是否还处于健康状态,避免服务器一直阻塞,官方给出的建议值是300s,如果设置为0,则不会周期性的检测。

4.4 节 GENERAL

具体配置详解:

  • daemonize:设置为yes表示指定Redis以守护进程的方式启动(后台启动)。默认值为 no

  • pidfile:配置PID文件路径,当redis作为守护进程运行的时候,它会把 pid 默认写到 /var/redis/run/redis_6379.pid 文件里面

  • loglevel :定义日志级别。默认值为notice,有如下4种取值:

    • debug(记录大量日志信息,适用于开发、测试阶段)

    • verbose(较多日志信息)

    • notice(适量日志信息,使用于生产环境)

    • warning(仅有部分重要、关键信息才会被记录)

  • logfile :配置log文件地址,默认打印在命令行终端的窗口上

  • databases:设置数据库的数目。默认的数据库是DB 0 ,可以在每个连接上使用select 命令选择一个不同的数据库,dbid是一个介于0到databases - 1 之间的数值。默认值是 16,也就是说默认Redis有16个数据库。

4.5 节 SNAPSHOTTING

这里的配置主要用来做持久化操作。

参数:

  • save:这里是用来配置触发 Redis的持久化条件,也就是什么时候将内存中的数据保存到硬盘

  • save 900 1:表示900 秒内如果至少有 1 个 key 的值变化,则保存

  • save 300 10:表示300 秒内如果至少有 10 个 key 的值变化,则保存

  • save 60 10000:表示60 秒内如果至少有 10000 个 key 的值变化,则保存

4.6 节 REPLICATION

参数:

  • slave-serve-stale-data:默认值为yes。当一个 slave 与 master 失去联系,或者复制正在进行的时候,slave 可能会有两种表现:

    • 如果为 yes ,slave 仍然会应答客户端请求,但返回的数据可能是过时,或者数据可能是空的在第一次同步的时候。

    • 如果为 no ,在你执行除了 info he salveof 之外的其他命令时,slave 都将返回一个 "SYNC with master in progress" 的错误

  • slave-read-only:配置Redis的Slave实例是否接受写操作,即Slave是否为只读Redis。默认值为yes。

  • repl-diskless-sync:主从数据复制是否使用无硬盘复制功能。默认值为no。

  • repl-diskless-sync-delay:当启用无硬盘备份,服务器等待一段时间后才会通过套接字向从站传送RDB文件,这个等待时间是可配置的。

  • repl-disable-tcp-nodelay:同步之后是否禁用从站上的TCP_NODELAY 如果你选择yes,redis会使用较少量的TCP包和带宽向从站发送数据。

4.7 节 SECURITY

requirepass:设置redis连接密码。 比如: requirepass 123 表示redis的连接密码为123。

4.8 节 CLIENTS

maxclients :设置客户端最大并发连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件。 描述符数-32(redis server自身会使用一些),如果设置maxclients为0 。表示不作限制。当客户端连接数到达限制时, Redis会关闭新的连接并向客户端返回max number of clients reached错误信息

4.9 节 MEMORY MANAGEMENT

参数:

  • maxmemory:设置Redis的最大内存,如果设置为0 。表示不作限制。通常是配合下面介绍的maxmemory-policy参数一起使用。

  • maxmemory-policy :当内存使用达到maxmemory设置的最大值时,redis使用的内存清除策略。有以下几种可以选择:

    1. volatile-lru 利用LRU算法移除设置过过期时间的key (LRU:最近使用 Least Recently Used )

    2. allkeys-lru 利用LRU算法移除任何key

    3. volatile-random 移除设置过过期时间的随机key

    4. allkeys-random 移除随机key

    5. volatile-ttl 移除即将过期的key(minor TTL)

    6. noeviction noeviction 不移除任何key,只是返回一个写错误 ,默认选项

4.10 节 APPEND ONLY MODE

参数:

  • appendonly:默认redis使用的是rdb方式持久化,这种方式在许多应用中已经足够用了。但是redis如果中途宕机,会导致可能有几分钟的数据丢失,根据save来策略进行持久化, Append Only File是另一种持久化方式, 可以提供更好的持久化特性。Redis会把每次写入的数据在接收后都写入appendonly.aof文件,每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件。默认值为no。

  • appendfilename :aof文件名,默认是"appendonly.aof"

  • appendfsync:aof持久化策略的配置;no表示不执行fsync,由操作系统保证数据同步到磁盘,速度最快;always表示每次写入都执行fsync,以保证数据同步到磁盘;everysec表示每秒执行一次fsync,可能会导致丢失这1s数据

4.11 节 LUA SCRIPTING

参数: lua-time-limit:一个lua脚本执行的最大时间,单位为ms。默认值为5000.

4.12 节 REDIS CLUSTER

参数:

  • cluster-enabled:集群开关,默认是不开启集群模式。

  • cluster-config-file:集群配置文件的名称。

  • cluster-node-timeout :可以配置值为15000。节点互连超时的阀值,集群节点超时毫秒数

  • cluster-slave-validity-factor :可以配置值为10。

第五章 Redis Java客户端

 在Redis官网中提供了各种语言的客户端,地址:https://redis.io/docs/connect/clients/

标记为*的就是推荐使用的java客户端,包括:

  • Jedis和Lettuce:这两个主要是提供了Redis命令对应的API,方便我们操作Redis,而SpringDataRedis又对这两种做了抽象和封装,因此我们后期会直接以SpringDataRedis来学习。

  • Redisson:是在Redis基础上实现了分布式的可伸缩的java数据结构,例如Map、Queue等,而且支持跨进程的同步机制:Lock、Semaphore等待,比较适合用来实现特殊的功能需求。

 

4.1 节 Jedis 客户端

Jedis的官网地址: https://github.com/redis/jedis

4.1.1.快速入门

1)引入依赖:

<!--jedis-->
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.7.0</version>
</dependency>
<!--连接池-->
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId><version>2.11.1</version>
</dependency>
<!--单元测试-->
<dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.7.0</version><scope>test</scope>
</dependency>

2)编写入门程序

新建一个单元测试类,内容如下:

/*** jedis入门程序*/
public class JedisTest {Jedis jedis;@BeforeEachpublic void before(){//建立连接jedis = new Jedis("192.168.184.129",6379);//设置密码jedis.auth("123456");//选择库jedis.select(0);}@Testpublic void stringTest(){//存数据jedis.set("name","张三");//获取数据System.out.println(jedis.get("name"));}@Testpublic void hashTest(){//存数据jedis.hset("user:1","name","张三");jedis.hset("user:1","age","22");//取数据Map<String, String> map = jedis.hgetAll("user:1");System.out.println(map);}@AfterEachpublic void after(){if(jedis!=null){jedis.close();}}
}

4.1.2.连接池

Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此我们推荐大家使用Jedis连接池代替Jedis的直连方式。

public class JedisConnectionFactory {private static JedisPool jedisPool;static {//配置连接池JedisPoolConfig poolConfig = new JedisPoolConfig();poolConfig.setMaxTotal(8);poolConfig.setMaxIdle(8);poolConfig.setMinIdle(0);// 创建连接池对象,参数:连接池配置、服务端ip、服务端端口、超时时间、密码jedisPool = new JedisPool(poolConfig, "192.168.184.129", 6379, 1000, "123456");}public static Jedis getJedis(){return jedisPool.getResource();}public static void main(String[] args) {System.out.println(JedisConnectionFactory.getJedis());}
}

4.2 节 SpringDataRedis 客户端

SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis,官网地址:Spring Data Redis

  • 提供了对不同Redis客户端的整合(Lettuce和Jedis)

  • 提供了RedisTemplate统一API来操作Redis

  • 支持Redis的发布订阅模型

  • 支持Redis哨兵和Redis集群

  • 支持基于Lettuce的响应式编程

  • 支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化

  • 支持基于Redis的JDKCollection实现

SpringDataRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作。并且将不同数据类型的操作API封装到了不同的类型中:

API返回值类型说明
redisTemplate.opsForValue()ValueOperations操作String类型数据
redisTemplate.opsForHash()HashOperations操作Hash类型数据
redisTemplate.opsForList()ListOperations操作List类型数据
redisTemplate.opsForSet()SetOperations操作Set类型数据
redisTemplate.opsForZset()ZSetOperations操作SortedSet类型数据
redisTemplate通用命令

4.2.1 快速入门

SpringBoot已经提供了对SpringDataRedis的支持,使用非常简单。

首先,新建一个maven项目,然后按照下面步骤执行:

1)引入依赖

<dependencies><!--redis依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!--common-pool--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><!--Jackson依赖--><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency>
</dependencies>

2)配置Redis

spring:redis:host: 192.168.184.129port: 6379password: 123456lettuce:pool:max-active: 8max-idle: 8min-idle: 0max-wait: 100ms

3)注入RedisTemplate,编写测试代码

@SpringBootTest
public class RedisTemplateTests {@Autowiredprivate RedisTemplate redisTemplate;@Testpublic void testString() {// 写入一条String数据redisTemplate.opsForValue().set("name", "张三");// 获取string数据Object name = redisTemplate.opsForValue().get("name");System.out.println("name = " + name);}
}

4.2.2.自定义序列化

RedisTemplate可以接收任意Object作为值写入Redis:

只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果是这样的:

我们可以自定义RedisTemplate的序列化方式,代码如下:  

@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){// 创建RedisTemplate对象RedisTemplate<String, Object> template = new RedisTemplate<>();// 设置连接工厂template.setConnectionFactory(connectionFactory);// 创建JSON序列化工具GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();// 设置Key的序列化template.setKeySerializer(RedisSerializer.string());template.setHashKeySerializer(RedisSerializer.string());// 设置Value的序列化template.setValueSerializer(jsonRedisSerializer);template.setHashValueSerializer(jsonRedisSerializer);// 返回return template;}
}

这里采用了JSON序列化来代替默认的JDK序列化方式。最终结果如图:

整体可读性有了很大提升,并且能将Java对象自动的序列化为JSON字符串,并且查询时能自动把JSON反序列化为Java对象。不过,其中记录了序列化时对应的class名称,目的是为了查询时实现自动反序列化。这会带来额外的内存开销。  

4.2.3.StringRedisTemplate

为了节省内存空间,我们可以不使用JSON序列化器来处理value,而是统一使用String序列化器,要求只能存储String类型的key和value。当需要存储Java对象时,手动完成对象的序列化和反序列化。

省去了我们自定义RedisTemplate的序列化方式的步骤,而是直接使用:

@SpringBootTest
public class StringRedisTemplateTest {@Autowiredprivate StringRedisTemplate stringRedisTemplate;// JSON序列化工具private static final ObjectMapper mapper = new ObjectMapper();@Testvoid testSaveUser() throws JsonProcessingException {// 创建对象User user = new User();user.setId(2);user.setName("李四");user.setAge(33);// 手动序列化String json = mapper.writeValueAsString(user);// 写入数据stringRedisTemplate.opsForValue().set("user:2", json);// 获取数据String jsonUser = stringRedisTemplate.opsForValue().get("user:2");// 手动反序列化User user1 = mapper.readValue(jsonUser, User.class);System.out.println("user1 = " + user1);}
}

但一般还是常用自动序列化

第六章 Redis 发布订阅

6.1 节 什么是发布与订阅

Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。

6.2 节 什么时候用发布订阅

看到发布订阅的特性,可用来做一个简单的实时聊天系统。再比如,在一个博客网站中,有100个粉丝订阅了你,当你发布新文章,就可以推送消息给粉丝们拉。

6.3 节 Redis的发布订阅

6.4 节 发布订阅命令

订阅

语法格式:

subscribe 频道名字

示例:

127.0.0.1:6379> subscribe channel-1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel-1"
3) (integer) 1

发布命令

语法格式:

publish channel-1 hello

示例: 打开另一个客户端,给channel1发布消息hello

127.0.0.1:6379> publish channel-1 hello
(integer) 1

注意: 返回的1是订阅者数量。

打开第一个客户端可以看到发送的消息

127.0.0.1:6379> subscribe channel-1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel-1"
3) (integer) 1
1) "message"
2) "channel-1"
3) "hello"

注意: 发布的消息没有持久化,如果在订阅的客户端收不到hello,只能收到订阅后发布的消息。

第七章 Redis 慢查询

7.1 节 什么是慢查询

慢查询,顾名思义就是比较慢的查询,但是究竟是哪里慢呢?

Redis执行命令过程如下:

说明:

  1. 慢查询发生在第3阶段

  2. 客户端超时不一定慢查询,但慢查询是客户端超时的一个可能因素

  3. 慢查询日志是存放在Redis内存列表中

7.2 节 慢查询日志

什么是慢查询日志?

慢查询日志是Redis服务端在命令执行前后计算每条命令的执行时长,当超过某个阈值是记录下来的日志。日志中记录了慢查询发生的时间,还有执行时长、具体什么命令等信息,它可以用来帮助开发和运维人员定位系统中存在的慢查询。

如何获取慢查询日志?

可以使用 slowlog get 命令获取慢查询日志,在 slowlog get 后面还可以加一 个数字,用于指定获取慢查询日志的条数,比如,获取3条慢查询日志:

127.0.0.1:6379> SLOWLOG get 3
1) (integer) 0
2) (integer) 1640056567
3) (integer) 11780
4) 1) "FLUSHALL"
5) "127.0.0.1:43406"
6) ""

参数:

  1. 唯一标识ID

  2. 命令执行的时间戳

  3. 命令执行时长

  4. 执行的命名和参数

如何获取慢查询日志的长度?

可以使用 slowlog len 命令获取慢查询日志的长度

> slowlog len
(integer) 121

注意: 当前Redis中有121条慢查询日志。

7.3 节 怎么配置慢查询参数

配置慢查询参数如下:

  • 命令执行时长的指定阈值 slowlog-log-slower-than:

    slowlog-log-slower-than的作用是指定命令执行时长的阈值,执行命令的时长超过这个阈值时就会被记录下来。

  • 存放慢查询日志的条数 slowlog-max-len。

    slowlog-max-len的作用是指定慢查询日志最多存储的条数。实际上,Redis使用了一个列表存放慢查询日志,slowlog-max-len就是这个列表的最大长度。

如何进行配置:

【1】查看慢日志配置

查看redis慢日志配置,登陆redis服务器,使用redis-cli客户端连接redis server

127.0.0.1:6379> config get slow*
1) "slowlog-max-len"
2) "128"
3) "slowlog-log-slower-than"
4) "10000"

慢日志说明:

10000阈值,单位微秒,此处为10毫秒,128慢日志记录保存数量的阈值,此处保存128条。

【2】修改Redis配置文件

比如,把slowlog-log-slower-than设置为1000,slowlog-max-len 设置为1200

slowlog-log-slower-than 1000
slowlog-max-len 1200

【3】也可以使用 config set 命令动态修改。

比如,还是把slowlog-log-slower-than设置为1000,slowlog-max-len设置为1200

> config set slowlog-log-slower-than 1000
OK
> config set slowlog-max-len 1200
OK
> config rewrite
OK

7.4 节 实践建议

slowlog-max-len配置建议

  • 线上建议调大慢查询列表,记录慢查询时Redis会对长命令做截断操作,并不会占用大量内存。

  • 增大慢查询列表可以减缓慢查询被剔除的可能,例如线上可设置为1000以上。

slowlog-log-slower-than配置建议

  • 默认值超过10毫秒判定为慢查询,需要根据Redis并发量调整该值。

  • 由于Redis采用单线程响应命令,对于高流量的场景,如果命令执行时间在1毫秒以上,那么Redis最多可支撑OPS不到1000。因此对于高OPS场景的Redis建议设置为1毫秒。

 

第八章 Redis 流水线 pipeline

8.1 节 Redis网络通讯模型弊端

1次网络命令通信模型

经历了1次时间 = 1次网络时间 + 1次命令时间。

批量网络命令通信模型

经历了 n次时间 = n次网络时间 + n次命令时间

8.2 节 什么是流水线

经历了 1次pipeline(n条命令) = 1次网络时间 + n次命令时间,这大大减少了网络时间的开销,这就是流水线。

8.3 节 案例

注意:

在执行批量操作而没有使用pipeline功能,会将大量的时间耗费在每一次网络传输的过程上;而使用pipeline后,只需要经过一次网络传输,然后批量在redis端进行命令操作。这会大大提高了效率。

pipeline-Jedis实现

【1】首先,引入jedis依赖包:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

【2】没有pipeline的命令执行

@Test
void test1(){redisTemplate.opsForValue().set("k1","v1");redisTemplate.opsForValue().set("k2","v2");redisTemplate.opsForValue().set("k3","v3");
}
@Test
void test2() {long start = System.currentTimeMillis();Object k1 = redisTemplate.opsForValue().get("k1");Object k2 = redisTemplate.opsForValue().get("k2");Object k3 = redisTemplate.opsForValue().get("k3");long end = System.currentTimeMillis();System.out.println("话费时间:"+(end-start));
}

注意:

在不使用pipeline的情况下,使用for循环进行每次一条命令的执行操作,耗费的时间可能达到 1w 条插入命令的耗时为50s。

【3】使用pipeline

@Test
void test3() {redisTemplate.executePipelined((RedisConnection connection)->{long start = System.currentTimeMillis();Object k1 = connection.get("k1".getBytes());Object k2 = connection.get("k2".getBytes());Object k3 = connection.get("k3".getBytes());long end = System.currentTimeMillis();System.out.println("话费时间:"+(end-start));return null;});}

耗时会大大减少

第九章 Redis 持久化机制

由于Redis的数据都存放在内存中,如果没有配置持久化,Redis重启后数据就全丢失了,于是需要开启Redis的持久化功能,将数据保存到磁盘上,当Redis重启后,可以从磁盘中恢复数据。

9.1 节 Redis持久化概述

对于Redis而言,持久化机制是指把内存中的数据存为硬盘文件, 这样当Redis重启或服务器故障时能根据持久化后的硬盘文件恢复数据

持久化机制的意义

redis持久化的意义,在于故障恢复。比如部署了一个redis,作为cache缓存,同时也可以保存一些比较重要的数据。

Redis提供了两个不同形式的持久化方式

  • RDB(Redis DataBase)

  • AOF(Append Only File)

9.2 节 RDB持久化机制

9.2.1 什么是RDB?

RDB是什么

在指定的时间间隔内将内存的数据集快照写入磁盘,也就是行话讲的快照,它恢复时是将快照文件直接读到内存里。

9.2.2 RDB基本配置

配置dump.rdb文件

RDB保存的文件,在redis.conf中配置文件名称,默认为dump.rdb。

440 # The filename where to dump the DB
441 dbfilename dump.rdb

rdb文件的保存位置,也可以修改。默认在Redis启动时命令行所在的目录下。

当前路径

dir ./

触发机制-主要三种方式

RDB配置

快照默认配置:

  • save 3600 1:表示3600秒内(一小时)如果至少有1个key的值变化,则保存。

  • save 300 100:表示300秒内(五分钟)如果至少有100个 key 的值变化,则保存。

  • save 60 10000:表示60秒内如果至少有 10000个key的值变化,则保存。

配置新的保存规则

给redis.conf添加新的快照策略,30秒内如果有5次key的变化,则触发快照。配置修改后,需要重启Redis服务。

save 3600 1
save 300 100
save 60 10000
save 30 5

flushall

执行flushall命令,也会触发rdb规则。

save与bgsave

手动触发Redis进行RDB持久化的命令有两种:

  • save

    该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止,不建议使用。

  • bgsave

    执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。

9.2.3 RDB高级配置

stop-writes-on-bgsave-error

默认值是yes。当Redis无法写入磁盘的话,直接关闭Redis的写操作。

rdbcompression

默认值是yes。对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是的话,redis会采用LZF算法进行压缩。如果你不想消耗CPU来进行压缩的话,可以设置为关闭此功能,但是存储在磁盘上的快照会比较大。

rdbchecksum

默认值是yes。在存储快照后,我们还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。

恢复数据

只需要将rdb文件放在Redis的启动目录,Redis启动时会自动加载dump.rdb并恢复数据。

9.2.4 RDB的优势与劣势

优势

  • 适合大规模的数据恢复

  • 对数据完整性和一致性要求不高更适合使用

  • 节省磁盘空间

  • 恢复速度快

劣势

  • 在备份周期在一定间隔时间做一次备份,所以如果Redis意外down掉的话,就会丢失最后一次快照后的所有修改。

 

9.3 节 AOF持久化机制

9.3.1 什么是AOF

以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来。

AOF默认不开启

可以在redis.conf中配置文件名称,默认为appendonly.aof。

注意:

AOF文件的保存路径,同RDB的路径一致,如果AOF和RDB同时启动,Redis默认读取AOF的数据。

AOF同步频率设置

参数:

  1. appendfsync always 始终同步,每次Redis的写入都会立刻记入日志,性能较差但数据完整性比较好。

  2. appendfsync everysec 每秒同步,每秒记入日志一次,如果宕机,本秒的数据可能丢失。

  3. appendfsync no redis不主动进行同步,把同步时机交给操作系统。

优势

  • 备份机制更稳健,丢失数据概率更低。

  • 可读的日志文本,通过操作AOF稳健,可以处理误操作。

劣势

  • 比起RDB占用更多的磁盘空间。

  • 恢复备份速度要慢。

  • 每次读写都同步的话,有一定的性能压力。

9.4 节 如何选用持久化方式

综合使用AOF和RDB两种持久化机制

用AOF来保证数据不丢失,作为数据恢复的第一选择,用RDB来做不同程度的冷备,在AOF文件都丢失或损坏不可用的时候,还可以使用RDB来进行快速的数据恢复。

第十章 总结

【1】你都用过哪些Redis数据类型?

答:String、List、Set、Map、ZSet、BitMaps、GEO、HyperLogLog。

常规缓存用String类型 、对象经常修改字段用Map类型 、BitMaps处理打卡上班记录等问题,GEO处理地理坐标类问题,HyperLogLo处理PV,UV等基数统计操作。

List可以实现排行榜,最新列表等功能。Set实现共同联系人,黑白名单功能。

ZSet可以实现特定条件的排行榜。按照人气排行,人气作为存储分数。

【2】说一下发布订阅机制?

答:发布订阅机制可以实现类似你订阅某个频道后,该频带给你发送消息的功能,订阅频道命令

subscribie 频道
# 发送消息
publish 频道名 消息

【3】如何解决慢查询问题?

答:通过慢查询日志解决,slowlog len获取慢查询记录数,在通过slowlog get n获取具体信息去排查。

还可以通过

> config set slowlog-log-slower-than 1000
OK
> config set slowlog-max-len 1200
OK
> config rewrite
OK

慢查询阈值根据QPS设置

【4】说以下说什么是流水线操作 答:一次网络连接 执行n条redis指令。

【5】说以下Redis持久化机制?

答:Redis支持两种持久化机制:RDB和AOF。RDB是快照持久化,读写速度快,占用磁盘空间小。但有丢失数据风险。AOF通过记录命令日志持久化,不易丢失数据,但是占用磁盘空间大,读写速度慢。RDB适合做冷备,如一天一备份的常规备份。AOF适合做REDIS正常重启前的数据备份,不会丢失数据。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/597073.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CMake入门教程【核心篇】包含目录(include_directories)

&#x1f608;「CSDN主页」&#xff1a;传送门 &#x1f608;「Bilibil首页」&#xff1a;传送门 &#x1f608;「本专栏容」&#xff1a;CMake入门教程 &#x1f608;「动动你的小手」&#xff1a;点赞&#x1f44d;收藏⭐️评论&#x1f4dd; 文章目录 1. 基本用法2. 添加单个…

快手推荐算法工程师三面回顾

快手三次技术面试一次HR面试的简单回顾&#xff0c;希望对大家有所启发。 一面 面试官一上来就让写算法题&#xff0c;第一个是计算岛屿数量&#xff0c;第二个是最长回文字串。 然后就是介绍自己的论文。对于论文的工作&#xff0c;面试官只是在问关于论文的问题&#xff0…

【PCB专题】Allegro封装更新焊盘

在PCB封装的绘制中&#xff0c;有时会出现需要更新焊盘的情况。比如在制作封装的过程中发现焊盘做的不对而使用PAD_Designer重新更新了焊盘。 那在PCB中如何更新已经修改过的焊盘呢&#xff1f; 打开封装&#xff0c;选择Tools->Padstack->Refresh... 选择Refresh all …

中国FinOps现状调查报告(2023)》亮点解读

今年以来&#xff0c;我们举办了多期FinOps的专题分享&#xff0c;邀请了美图、腾讯、B站、趣丸、知乎等厂商和行业专家&#xff0c;分享他们在FinOps领域的经验。我们也发现越来越多的人对FinOps产生了浓厚的兴趣&#xff0c;而且FinOps的成熟度也在逐渐提升。 降本增效&…

关键字:instanceof关键字

在 Java 中&#xff0c;instanceof关键字用于检查一个对象是否是某个特定类或其子类的实例。它的语法如下&#xff1a; 其中&#xff0c;Object是要检查的对象&#xff0c;Class是要检查的类或接口。 instanceof关键字的返回值是一个布尔值&#xff0c;如果对象Object是类Cla…

Docker介绍、常用命令、项目部署

什么是Docker 简单说&#xff1a;Docker就是一个虚拟机&#xff0c;专业说&#xff1a;它是一个开源的容器平台。它和我们常用的VMware有很多相似的地方。 名词解释 镜像/images 由本体打包出来的文件。并不是文件本身&#xff0c;但是具有该文件的功能。举个不太贴切的例子&…

Android Matrix剪切clipPath缩放scale图片postTranslate圆形放大镜,Kotlin(2)

Android Matrix剪切clipPath缩放scale图片postTranslate圆形放大镜&#xff0c;Kotlin&#xff08;2&#xff09; 在 Android Matrix剪切clipPath缩放scale图片postTranslate圆形放大镜&#xff0c;Kotlin&#xff08;1&#xff09; Android Matrix剪切clipPath缩放scale图片po…

LCR 174. 寻找二叉搜索树中的目标节点

解题思路&#xff1a; 二叉搜索树一般采用中序遍历&#xff08;从小到大排列&#xff09;。 class Solution {int res, cnt;public int findTargetNode(TreeNode root, int cnt) {this.cnt cnt;dfs(root);return res;}void dfs(TreeNode root) {if(root null) return;dfs(ro…

Docker 入门 ------容器互通以及Dockerfile

1. 端口映射以及容器互联 Docker 除了通过网络访问&#xff0c;还提供了两种很方便的功能来满足服务访问的基本需求&#xff1a; 允许映射容器内应用的服务端口到本地宿主主机互联机制实现多个容器间通过容器名来快速访问 1.1 容器映射实现访问容器 1.1.1 从外部访问容器应…

Python 标准库中的 csv 包

0. Abstract 官方文档很罗嗦&#xff0c;长篇大论例子少。本文将举例说明 csv 包的用法&#xff0c;然后补充一些必要的说明。 1.0 CSV 文件 CSV(Comma-Separated Values,逗号分隔值)文件是一种常见的以纯文本形式存储数据的文件格式。它使用逗号作为字段之间的分隔符&#…

解决docker容器内无法连接宿主redis

背景 小程序的发短信服务挂了&#xff0c;随查看日志&#xff0c;该报错日志如下 Error 111 connecting to 127.0.0.1:6379. Connection refused. 6379是监听redis服务的端口&#xff0c;那大概是redis出错了。 首先查看了redis是否正常启动&#xff0c;检查出服务正常。 由于小…

Flappy Bird QDN PyTorch博客 - 代码解读

Flappy Bird QDN PyTorch博客 - 代码解读 介绍环境配置项目目录结构QDN算法重要函数解读preprocess(observation)DeepNetWork(nn.Module)BirdDQN类主程序部分 介绍 在本博客中&#xff0c;我们将介绍如何使用QDN&#xff08;Quantile Dueling Network&#xff09;算法&#xf…

【Mybatis】我抄袭了Mybatis,手写一套MyMybatis框架:编写一个引入MyMybatis框架的正常项目

上一篇文章中&#xff0c;我们学习了使用mybatis框架连接mysql。在这篇文章中&#xff0c;我们将聚焦于我们的调用方&#xff0c;即相应的实际项目&#xff0c;其中包含了对mymybatis框架的引用。以一个常见而又典型的例子来说明这一点——制作一款学生管理系统&#xff08;伪&…

部署清华ChatGLM-6B(Linux版)

引言 前段时间,清华公布了中英双语对话模型 ChatGLM-6B,具有60亿的参数,初具问答和对话功能。最!最!最重要的是它能够支持私有化部署,大部分实验室的服务器基本上都能跑起来。因为条件特殊,实验室网络不通,那么如何进行离线部署呢? 「部署环境」:CUDA Version 11.0,…

Maven简介及环境搭建和基本使用(Java开发中的实用工具)

一、概述 Maven 是 Apache 软件基金会的一个开源项目,是一个优秀的项目构建工具,它 用来帮助开发者管理项目中的 jar,以及 jar 之间的依赖关系、完成项目的编译、 测试、打包和发布等工作。 Maven的相关概念 pom.xml文件&#xff1a;里面可以配置相关信息&#xff0c;指导ma…

【SpringBoot开发】之商城项目案例(沙箱支付)

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《SpringBoot开发之商城项目系列》。&#x1f3af…

MySQL数据库索引优化实战

目录 一、前言 二、准备工作 2.1 用户表&#xff08;TB_USER) 2.2 商品表&#xff08;TB_SKU) 2.3 订单表&#xff08;TB_ORDER&#xff09; 三、实例分析 3.1 索引提升查询性能 3.2 多表查询 3.3 索引失效 四、总结 一、前言 在数据库的应用中&#xff0c;性能优化…

类加载机制之双亲委派模型、作用、源码、SPI打破双亲委派模型

双亲委派模型 双亲委派工作机制双亲委派的作用双亲委派的实现源码SPI打破双亲委派 应用程序是由三种类加载器相互配合&#xff0c;从而实现类加载&#xff0c;除此之外还可以加入自己定义的类的加载器。 类加载器之间的层次关系&#xff0c;称为双亲委派模型&#xff08;Parent…

2024最全面且有知识深度的web3开发工具、web3学习项目资源平台

在Web3技术迅速发展的时代&#xff0c;寻找一个综合且深入的Web3开发工具和学习项目资源平台变得至关重要。今天&#xff0c;我将向大家介绍一个非常有价值的网站&#xff0c;它就是https://web3x.world 。 Web3X是一个全面而深入的Web3开发者社区&#xff0c;为开发者们提供了…

【深度学习】各领域常用的损失函数汇总(2024最新版)

目录 1、L1 损失、平均绝对误差&#xff08;L1 Loss、Mean Absolute Error&#xff0c;MAE&#xff09; 2、L2 损失、均方误差&#xff08;L2 Loss、Mean Squared Error&#xff0c;MSE&#xff09; 3、交叉熵损失&#xff08;Cross-Entropy Loss&#xff09; 4、混合损失&…