首页 > 数据库 >redis高级用法

redis高级用法

时间:2023-01-03 16:33:09浏览次数:39  
标签:aof redis 高级 用法 命令 rdb 日志 save

1 高级用法之慢查询

# 讲5大数据类型,O(n), 命令执行时间很长,redis 命令操作 单线程架构 ,阻塞
    -单线程架构:并发操作不需要锁
  -mysql:行锁,表锁,并发操作数据错乱的问题
  
  
# 慢查询命令 记录下来,以备后期查看,排查,redis的配置,用来记录慢查询,如果符合这个配置,这条命令就会被记录

# 命令操作生命周期
    -客户端到服务端的网络时间
  -执行命令时间  (咱们指的慢查询指这里),设定一个时间,如果超过了这个时间,咱们就认为是慢查询
  -服务端返回客户端时间

  
  
# 配置:两个配置项
config get slowlog-max-len=128   # 慢查询队列是128 
config get slowly-log-slower-than=10000 # 微秒,超过这个时间,我们就记录


# 动态配置
config set slowlog-log-slower-than 0   # 记录所有
config set slowlog-max-len 128
# 持久化到本地配置文件
config rewrite

# 查看慢命令队列
slowlog get [n]  #获取慢查询队列
'''
日志由4个属性组成:
1)日志的标识id
2)发生的时间戳
3)命令耗时
4)执行的命令和参数
'''
slowlog len #获取慢查询队列长度

slowlog reset #清空慢查询队列



# 作用
    -后期发现redis速度非常慢,开启慢日志,过一会,查看一下慢命令,取出慢命令,分析这个命令是不是必须要执行,把这个慢命令换一种方式实现,从而加快操作速度

2 pipline与事务

# redis 本身不支持事务,通过管道实现部分事务

Redis的pipeline(管道)功能在命令行中没有,但redis是支持pipeline的,而且在各个语言版的client中都有相应的实现
将一批命令,批量打包,在redis服务端批量计算(执行),然后把结果批量返回
1次pipeline(n条命令)=1次网络时间+n次命令时间

# python代码实现

import redis
pool = redis.ConnectionPool(host='127.0.0.1', port=6379)
r = redis.Redis(connection_pool=pool)
#创建pipeline
pipe = r.pipeline(transaction=True)
#开启事务
pipe.multi()
pipe.set('name', 'lqz')
#其他代码,可能出异常

pipe.set('role', 'nb')
 
pipe.execute()  # 一次性执行命令  ,在这之前,如果处理异常,所有命令都不会执行,保证了一致性



# 了解,原生事务操作


# 1 mutil  开启事务,放到管道中一次性执行
multi   # 开启事务
set name lqz
set age 18
exec
# 原生redis使用管道




# 2 模拟事务
# 在开启事务之前,先watch,只有这个age,在整个过程中没有被改变,才能正常修改成功,如果在执行exec时发现,age被改了,就修失败
watch age
multi
decr age
exec

# 另一台机器
multi
decr age
exec  # 先执行,上面的执行就会失败(乐观锁,被wathc的事务不会执行成功)

3 发布订阅

# 观察者模式:我们现在订阅了一个人,只要这个人发生变化,我们都能收到变化
发布者发布了消息,所有的订阅者都可以收到,就是生产者消费者模型(后订阅了,无法获取历史消息)

# 关注了某个明星,只要明星发布动态,大家都能收到
# 订阅了某个人的博客,只要它发布新博客,都能收到
# 订阅了某个商品的抢购提醒,当要开始抢购的时候,你收到短信通知


# redis实现发布订阅

# 1 发布消息
publish souhu:tv "hello world"

# 2 订阅消息
subscribe souhu:tv



# 发布订阅和消息队列区别
    -只要订阅了,所有人都能收到消息
  -消息队列,只有一个人能抢到消息

 

 4 bitmap位图

# 本质是字符串,可以操作某个比特位
# 比如字符串是 big,设置和获取某个比特位
set hello big #放入key位hello 值为big的字符串  00000000 00000000 00000000
# 获取比特位
getbit hello 0 #取位图的第0个位置,返回0
getbit hello 1 #取位图的第1个位置,返回1 如上图

# 设置比特位
setbit hello 7 1

# 获取对应的字符串
get hello 

# 获取指定范围内1 的个数  ,前闭后闭区间
bitcount key start到end,    单位为字节,注意按字节一个字节8个bit为


# 作用:做独立用户统计,日活用户统计,大数据量的日活统计,使用它会节约内存
    -用户id 是数字,1,2,3....
  -日活:每日的用户活跃数,用户登录后,把id号放到集合中
      - 1   2   3    9999  字符串 9999四个字符 4*8 32个比特位,用户量越多,存储用户id用的空间就越大
       -使用setbit设置 ,只要用户登录了,就在对应的位置设为1,没有登录就是0
    setbit users 9999 1
    setbit users 1 1
    最终通过bitcount计算出总共有多少个1,就是多少个活跃用户
    
    
  -抖音日活
      -集合 : 用户id方式   3亿用户*32比特位
    -位图 方式           3亿*1 个比特位
     setbit users 10亿 1  
      
      
      
      
# 做日活,使用集合和位图比较
1 使用set和Bitmap对比
2 1亿用户,5千万独立(1亿用户量,约5千万人访问,统计活跃用户数量)
数据类型    每个userid占用空间    需要存储用户量    全部内存量
set    32位(假设userid是整形,占32位)    5千万    32位*5千万=200MB
bitmap    1位    1亿    1位*1亿=12.5MB
假设有10万独立用户,使用位图还是占用12.5mb,使用set需要32位*1万=4MB

5 HyperLogLog

# HyperLogLog:本质还是字符串
基于HyperLogLog算法:极小的空间完成独立数量统计

# 用来统计某个值是否在其中,只能统计,不能取出来
# 集合可以取值,统计是否在其中,但是集合占的空间大


# 使用
pfadd key element #向hyperloglog添加元素,可以同时添加多个
pfcount key #计算hyperloglog的独立总数


# 类似于集合,去重,统计某个元素是否在其中,之前使用去重的地方,就可以使用它


# 独立用户统计,也可以使用HyperLogLog
    -如果用户id不是数字,而是uuid无规律的形式  asdf-asdfw-dsdf-asdf
  
  
# 错误率,布隆过滤器本质是一样的,使用HyperLogLog算法
百万级别独立用户统计,百万条数据只占15k
错误率 0.81%
无法取出单条数据,只能统计个数

6 GEO

# GEO(地理信息定位):存储经纬度,计算两地距离,范围等
    -抖音,附近的人
  -美团,附近的美食
  -交友软件,附近的美女
  
 
# 存储经纬度,通过经纬度,计算距离
    -经纬度哪里来?前端(app,网页),前端获取用户授权,用户授权后,通过某个方法,可以直接获取到手机的位置,获取出来就是经纬度
  -通过后台某个接口,把此时的经纬度,提交到后台,后台保存到redis的geo中
  
  
  
  
#1 存数据
geoadd user:locations 116.28 39.55 1
geoadd user:locations 116.28 42.55 2

geoadd cities:locations 116.28 39.55 beijing 
geoadd cities:locations 117.12 39.08 tianjin
geoadd cities:locations 114.29 38.02 shijiazhuang
geoadd cities:locations 118.01 39.38 tangshan
geoadd cities:locations 115.29 38.51 baoding


# 2 获取地理位置信息 ---->获取张三的位置
# geopos user:locations 2  --->经纬度----》开放的接口,通过经纬度获得具体的位置信息
geopos cities:locations beijing #获取北京地理信息


# 3 获取两个地点的距离
geodist cities:locations beijing tianjin km
  
  
# 4 方圆100km内有哪些城市
# 改一个接口,交友类app,附近5公里的美女,每次都会把它自己查出来,不显示自己,只查别人
georadiusbymember cities:locations beijing 150 km



# geo 本质是zset类型

7 持久化

# redis redis的所有数据保存在内存中,对数据的更新将异步的保存到硬盘上,更新到硬盘上这个操作称之为持久化

# 常见的持久化方案
快照:某时某刻数据的一个完成备份
    -mysql的Dump
  -redis的RDB
写日志:任何操作记录日志,要恢复数据,只要把日志重新走一遍即可
    -mysql的 Binlog
  -Redis的 AOF
  
  
  
  
# redis 支持两种持久化方案
    -rdb :快照,某一时刻完整备份
  -aof: 日志,进行了操作就记录日志
  -混合持久化:rdb+aof方案,后来加入的,为了快速恢复数据

7.1 rdb持久化方案

# 三种触发机制
    -手动:save
  -手动:bgsave
  -配置文件:符合条件就触发
  
  
# 方式一:
    -在客户端执行save,把此时内存中的数据,完整的备份到硬盘上,生成一个xx.rdb 文件,当redis服务器停止,再启动,会加载rdb文件数据到内存,达到快速恢复的效果
  -sava 会阻塞住,导致其他命令执行不了
  
# 方式二:
    -在客户端执行bgsave,异步备份,不会阻塞其他命令的执行
  
  
  
# 方式三:配置文件 ,用它比较多
save   900        1
save   300        10
save   60         10000

# 如果60s中改变了1w条数据,自动生成rdb
# 如果300s中改变了10条数据,自动生成rdb
# 如果900s中改变了1条数据,自动生成rdb


# 我的配置
save 900 20
save 300 10
save 60  5 
dbfilename dump.rdb 
  
  
  
# 客户端主动关闭服务端时,也会触发


# rdb 方案会存在数据丢失的情况,一般咱们用redis做缓存,可以使用这种方案,缓存丢失,影响不大,但如果对数据准确性要求比较高,应该使用aof方案

7.2 aof 方案

# 客户端每写入一条命令,都记录一条日志,放到日志文件中,如果出现宕机,可以将数据完全恢复

# AOF的三种策略
日志不是直接写到硬盘上,而是先放在缓冲区,缓冲区根据一些策略,写到硬盘上
always:redis–》写命令刷新的缓冲区—》每条命令fsync到硬盘—》AOF文件  # redis写入速度很快,每条日志都立马写到硬盘上,硬盘性能跟不上
everysec(默认值):redis——》写命令刷新的缓冲区—》每秒把缓冲区fsync到硬盘–》AOF文件 # 每s把日志写到硬盘上
no:redis——》写命令刷新的缓冲区—》操作系统决定,缓冲区fsync到硬盘–》AOF文件  # 操作系统决定



# AOF 重写策略
随着命令的逐步写入,并发量的变大, AOF文件会越来越大,通过AOF重写来解决该问题
本质就是把过期的,无用的,重复的,可以优化的命令,来优化
这样可以减少磁盘占用量,加速恢复速度 

# 配置文件配置好,会自动开启aof重写,优化aof日志文件

auto-aof-rewrite-min-size # AOF文件到达某个尺寸,就触发aof重写
auto-aof-rewrite-percentage    # AOF文件增长率,到达某个比率,就触发aof重写







# 最佳配置

appendonly yes #将该选项设置为yes,打开,开启aof
appendfilename appendonly.aof #文件保存的名字
appendfsync everysec #采用第二种策略
no-appendfsync-on-rewrite yes #在aof重写的时候,是否要做aof的append操作,因为aof重写消耗性能,磁盘消耗,正常aof写磁盘有一定的冲突,这段期间的数据,允许丢失



# 我们公司采用了什么持久化方案
    -如果是缓存,就用rdb
  -如果对数据准确性要求高,就用aof
  
  -混合持久化:两个都开启

8 主从复制

# mysql 主从复制 ,原理  binlog,relaylog,io线程,sql线程
# redis 主从复制

# 主从复制出现原因
问题:机器故障;容量瓶颈;QPS瓶颈
解决问题:一主一从,一主多从,做读写分离,做数据副本
扩展数据性能
一个master可以有多个slave
一个slave只能有一个master
数据流向是单向的,从master到slave


# redis主从复制原理
1. 副本库通过slaveof 127.0.0.1 6379命令,连接主库,并发送SYNC给主库 
2. 主库收到SYNC,会立即触发BGSAVE,后台保存RDB,发送给副本库
3. 副本库接收后会应用RDB快照
4. 主库会陆续将中间产生的新的操作,保存并发送给副本库
5. 到此,我们主复制集就正常工作了
6. 再此以后,主库只要发生新的操作,都会以命令传播的形式自动发送给副本库.
7. 所有复制相关信息,从info信息中都可以查到.即使重启任何节点,他的主从关系依然都在.
8. 如果发生主从关系断开时,从库数据没有任何损坏,在下次重连之后,从库发送PSYNC给主库
9. 主库只会将从库缺失部分的数据同步给从库应用,达到快速恢复主从的目的

8.1 主从复制搭建

# 方式一:
    -两台机器,启动两个redis进程
  
  
    # 第一台机器配置
  daemonize yes
  port 6379
  dir "/root/redis/data"
  logfile "6379.log"
  save 900 20
  save 300 10
  save 60  5 
  dbfilename dump.rdb
  appendonly yes
  appendfilename appendonly.aof
  appendfsync everysec
  no-appendfsync-on-rewrite yes
  
  
  # 第二台机器配置
  daemonize yes
  port 6380
  dir "/root/redis/data2"
  logfile "6380.log"
  save 900 20
  save 300 10
  save 60  5 
  dbfilename dump.rdb


  appendonly yes
  appendfilename appendonly.aof
  appendfsync everysec
  no-appendfsync-on-rewrite yes
  
  
  # 启动两个redis-server服务
     redis-server ./redis_6379.conf 
    redis-server ./redis_6380.conf 
  ps aux |grep redis
  
  # 在6380库上执行
  slaveof 127.0.0.1 6379
  以后6380库就是6379的从库了,不能再写数据了 #  (error) READONLY You can't write against a read only replica.
  
  # info 命令查看主从关系
  
  
  
  
  # 一主多从也是同理

8.2 配置文件搭建方式

# 在从库配置文件加入

slaveof 127.0.0.1 6379
slave-read-only yes

# 在俩从库配置文件中加入

# 启动三个redis服务
    -6379  主
  -6380 从
  -6381 从
  
# 停掉一个从库,主从关系还在
# 停掉主库,就不能写数据了

 

标签:aof,redis,高级,用法,命令,rdb,日志,save
From: https://www.cnblogs.com/shangxin-bai/p/17022626.html

相关文章

  • C++数据结构map中的begin()和rbegin()具体区别及erase()具体用法
    1.前言 昨天写的LeetCode打卡题,用到了map数据结构,并且需要顺序和逆序遍历map并删除key对应value为0的这个对象。本以为begin()和rbegin()是一样的迭代器,只不过是一个指......
  • windows下启动redis
    首先下载安装redis省略1、找到redis的安装目录,一般在C盘的programfiles文件夹下,进入redis文件夹2、打开命令行窗口,输入redis-server.exeredis.windows.conf3、......
  • Redis基础
    参考资料:https://www.cnblogs.com/ciel717/p/16466230.htmlhttps://www.cnblogs.com/lzh1995/p/16757991.htmlRedis数据类型Redis是key-value存储数据库,所有的key......
  • docker部署redis实战
    点击上方“编程三分钟”,马上关注,每天早上8:50准时推送。“ 换电脑的时候不想再搭建开发环境了!——编程三分钟”什么是dockerDocker是一个用来管理......
  • 从Redis、HTTP协议,看Nett协议设计,我发现了个惊天大秘密
    1.协议的作用TCP/IP中消息传输基于流的方式,没有边界协议的目的就是划定消息的边界,制定通信双方要共同遵守的通信规则2.Redis协议如果我们要向Redis服务器发送一......
  • Redis实现消息队列
    异步消息队列说道消息队列,你肯定会想到Kafka、Rabbitmq等消息中间件,这些专业的消息中间件提供了很多功能特性,当然他的部署使用维护都是比较麻烦的。如果你对消息队列没那......
  • Java里if和else的用法
    前言在上一篇文章中,壹哥给大家讲解了Java里的输入与输出语句,现在你知道怎么用了吗?接下来我们继续往下学习Java里的流程控制语句,今天先给大家讲一下if和else这一对好基友,......
  • redis集群配置
    redis集群配置1、三主三从redis集群配置1、新建6个docker容器实例##--cluster-enabledyes 开启redis集群##--nethost 使用宿主机的ip和端口默认##--appendonlyyes ......
  • 简单聊聊:Stream.reduce()用法解析
    基本使用先举一个简单的例子:算法题:Words题目描述每个句子由多个单词组成,句子中的每个单词的长度都可能不一样,我们假设每个单词的长度Ni为该单词的重量,你需要做的就是给出......
  • 高级性能02-系统监控软件安装部署
    查看系统版本cat/etc/redhat-releaseJava安装yuminstall-yjava查看Java版本java-version配置node_exporter作用:负责收集系统信息cd/optmkdirpackage......