加载中...

redis概述

redis,使用教程,常用配置

一、特点

  • 键值(key-value)型,value支持多种不同数据结构,功能丰富
  • 单线程,每个命令具备原子性
  • 低延迟,速度快(基于内存、IO多路复用、良好的编码)。
  • 支持数据持久化
  • 支持主从集群、分片集群
  • 支持多语言客户端

1、redis是单线程的,保证原子性;6.0后网络请求是多线程,但是最终的命令执行依然是单线程

2、为什么快?低延迟,速度快(基于内存、10多路复用、良好的编码、c语言)

二、安装

1
2
3
4
5
6
7
8
9
# 安装依赖
yum install -y gcc tcl

tar -xzf redis-6.2.6.tar.gz
cd redis-6.2.6
# 测试
make test
# 安装
make && make install
Copied!

image

错误的本质是我们在开始执行make 时遇到了错误(大部分是由于gcc未安装),然后我们安装好了gcc 后,我们再执行make ,这时就出现了jemalloc/jemalloc.h: No such file or directory。这是因为上次的

编译失败,有残留的文件,我们需要清理下,然后重新编译就可以了。

1
make distclean
Copied!

默认的安装路径是在 /usr/local/bin目录下:

image-20220523183315613

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

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

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

  • 前台启动

    • 1
      
      redis-server
      Copied!
  • 指定配置启动

    • 1
      
      cp redis.conf redis.conf.bck #配置文件备份
      Copied!
    • 修改配置文件

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

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

    • 1
      2
      3
      4
      
      # 进入redis安装目录 
      cd /usr/local/src/redis-6.2.6
      # 启动
      redis-server redis.conf
      Copied!
    • 停止服务

    • 1
      2
      3
      
      # 利用redis-cli来执行 shutdown 命令,即可停止 Redis 服务,
      # 因为之前配置了密码,因此需要通过 -a 来指定密码
      redis-cli -a 123321 shutdown
      Copied!
  • 开机自启

    • 1
      
      vi /etc/systemd/system/redis.service #新建一个系统服务文件
      Copied!
    •  1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      
      [Unit]
      Description=redis-server
      After=network.target
      
      [Service]
      Type=forking
      ExecStart=/usr/local/bin/redis-server /usr/local/src/redis-6.2.6/redis.conf
      PrivateTmp=true
      
      [Install]
      WantedBy=multi-user.target
      Copied!
    • 1
      
      systemctl daemon-reload #重载系统服务
      Copied!
    • 现在,我们可以用下面这组命令来操作redis了:

    • 1
      2
      3
      4
      5
      6
      7
      8
      
      # 启动
      systemctl start redis
      # 停止
      systemctl stop redis
      # 重启
      systemctl restart redis
      # 查看状态
      systemctl status redis
      Copied!
    • 执行下面的命令,可以让redis开机自启:

    • 1
      
      systemctl enable redis
      Copied!

三、应用

1、全局ID生成器

一位标志位(0)+42位时间戳+21位redis自增 100年

2、缓存

缓存预热 缓存穿透 1、缓存null数据 2、布隆过滤
缓存雪崩 1、设置不同过期时间 2、redis高可用 3、多层缓存 4、缓存预热 5、降级限流
缓存击穿 1、互斥锁(性能差,有死锁风险) 2、逻辑过期

3、秒杀

秒杀 一人一单、超卖问题 三种方式:

  • 1、乐观锁减库存,成功率低,其他判断逻辑不能保证原子性

  • 2、分布式锁执行,性能差

  • 3、使用lua脚本判断资格,有序异步执行数据库逻辑

    • 3.1、放入JDK阻塞队列

      • 内存溢出问题、重启队列内数据丢失问题、取出数据后执行代码逻辑出现异常
    • 3.2、或者redis的消息队列

      • 3.2.1、list-双向链表 模拟 队列(LPUSH+BRPOP)(RPUSH+BLPOP),B:阻塞 支持数据持久化 只支持单消费者 问题:取出数据后执行代码逻辑出现异常

      • 3.2.2、发布订阅 pub sub(天生阻塞) ,

        ​ PUBLISH channel msg ,SUBSCRIBE channel ,PSUBSCRIBE channe* ​ 支持多消费者,多生产者 ​ 问题:不支持数据持久化 ​ 取出数据后执行代码逻辑出现异常 ​ 消息堆积有上限,超出时数据丢失

      • 3.2.3、stream redis5.0后引入的一种新的数据类型,可以实现一个功能完善的消息队列 XADD s1 * k1 v1 k2 v2 发送消息,*表示使用redis自增id XLEN s1 查看消息数量 XREAD 读取消息,读完不会删除 消息可回溯 支持数据持久化 支持多消费者 可以阻塞读取 有消息漏读问题

      • 3.2.4、stream-消费者组 :将多个消费者划分到一个组,监听同一个队列 消息分流:队列中消息会分流给组内的不同消费者,而不是重复消费,加快消息处理速度 消息标志:消费者组会维护一个标志,记录最后一个被处理的消息,消费者重启后,会从标志之后读取消息,避免消息漏读 消息确认:消费者获取消息后,消息处于pending状态,并存入一个pending-list(在redis中) 当处理完成后需要通过XACK来确认消息,标记消息为已处理,才会从pending-list移除。 XGROUP CREATE key groupname ID XREADGROUP GROUP XACK KEY group ID XPENDING

4、点赞和关注

大V 普通 僵尸粉-活跃粉丝 , 拉取关注的用户发布的内容,sortedSet 滚动分页查询,按照时间戳倒序排序。 因为查完第一页后,可能会新增数据,所以不能用索引来查,所以用score存时间戳,用时间戳筛选数据 ZREVRANGEBYSCORE key max min WITHSCORES LIMIT offset count max:第一次查询时,max=当前时间戳;当前查询的score的最大值,在本业务中即上一次排序列表中的最后一个元素的score-时间戳; min=0 不变 offset:第一次查询时,为0;后面查询时,offset为上一次查询结果中,与最后一个元素的score相等的元素个数,即跳过这些元素,避免重复显示 count=3 不变,每页查多少数据

5、附近商户-地理坐标

​ GEO数据结构,底层就时一个sortedset,经纬度转换为score ​ GEOADD:添加一个地理空间信息,包含:经度(longitude)、纬度(latitude)、值(member) ​ GEOADD g1 116.42803 39.903738 bjz 116.322287 39.893729 bjx ​ GEODIST:计算指定的两个点之间的距离并返回 ​ GEODIST g1 bjx bjz km ​ GEOHASH:将指定member的坐标转为hash字符串形式并返回 ​ GEOPOS:返回指定member的坐标 ​ GEOPOS g1 bjz ​ GEORADIUS:指定圆心、半径,找到该圆内包含的所有member,并按照与圆心之间的距离排序后返回。6.2以后已废弃 ​ GEOSEARCH:在指定范围内搜索member,并按照与指定点之间的距离排序后返回。范围可以是圆形或矩形。6.2.新功能 ​ GEOSEARCH g1 FROMMEMBER bjx BYRADIUS 300 km ASC WITHDIST 默认升序 ​ GEOSEARCH g1 FROMLONLAT 116 39 BYRADIUS 300 km ASC WITHDIST ​ GEOSEARCHSTORE:与GEOSEARCH功能一致,不过可以把结果存储到一个指定的key。 6.2.新功能

6、用户签到

BitMap - 位图 - 假设一次签到数据库中生成一行,每行占22字节,那么1000万个用户签到一个月=非常大的内存和行数 BitMap把每天签到与否抽象为bit的0或1,一个月31天,4个字节就能存下 BitMap利用redis的String类型数据结构(key-value),最大上限为512M,转为bit为2^32bit key为用户id:月份,value为bit转换成的string SETBIT key offset value –value为0或1 GETBIT key offset BITCOUNT key [start end] 从0开始,统计一个月内签到次数 BITFIELD查询、BITOP位运算、BITPOS查找第一个出现的位置 连续签到次数:从最后一次签到开始向前统计 BIFIELD key GET u5 0 ,获取0号到5号的所有签到数据,u表示返回无符号数 // num为取出签到数据bit转换成的十进制数 int count = 0; while (true) { // 6.1.让这个数字与1做与运算,得到数字的最后一个bit位 // 判断这个bit位是否为0 if ((num & 1) == 0) { // 如果为0,说明未签到,结束 break; } else { // 如果不为0,说明已签到,计数器+1 count++; } // 把数字右移一位,抛弃最后一个bit位,继续下一个bit位 num »>= 1; }

7、UV PV统计

HyperLogLog UV:Unique Visitor ,浏览网页的自然人,一天内同一个用户访问多次,只记录一次 PV:Page View,页面访问量,用户多次打开页面,记录多次 HyperLogLog:基于LogLog算法,用于确定非常大的集合的基数,而不需要存储所有值;伯努利实验,抛硬币 基于redis中的string结构实现,单个HLL内存永远小于16KB,测量结果有小于0.81%的误差,对于UV统计来说可以忽略 PFADD key element [element …] 添加 PFCOUNT key [key …] 统计数量 PFMERGE destkey sourcekey [sourcekey …] 合并 HyperLogLog存储数据天生是唯一的,适合做UV

8、分布式锁

redlock和mutilock 某台节点时钟漂移

四、分布式

单点问题:

  • 数据丢失问题 – redis持久化
  • 并发能力 - 主从,读写分离
  • 存储空间 - 分片集群,利用插槽机制实现动态扩容
  • 单点故障 -redis哨兵,健康监测和自动恢复
Licensed under CC BY-NC-SA 4.0
最后更新于 2024年5月24日 16:57
发表了90篇文章 · 总计613.27k字
本站总访问量本站访客数人次

目录