2024零基础入门redis(通俗易懂)

Redis(Remote Dictionary Server)是一个开源的内存数据结构存储系统,由Salvatore Sanfilippo于2009年开发。最初的开发目的是为了一家意大利初创公司提供实时Web日志分析服务,但由于其卓越的性能和广泛的应用场景,迅速发展成为广受欢迎的数据库、缓存和消息代理。

前沿

Redis的历史可以追溯到2009年,当时Salvatore Sanfilippo在为自己的项目寻找一个高性能的内存缓存解决方案时,发现现有的解决方案无法满足需求。于是,他决定开发一个新的系统,这就是Redis的起源。Redis最初发布于2009年3月,并在2010年被VMware赞助,随后在2013年又转由Pivotal赞助。随着时间的推移,Redis不断发展,增加了许多新的数据结构和功能,如发布/订阅、持久化、Lua脚本、LRU驱动事件等,使其成为现代应用中不可或缺的组成部分。

为什么近年来要使用Redis

近年来,Redis的使用显著增加,主要原因包括以下几个方面:

  1. 性能:Redis以其极高的读写速度著称,能够在毫秒级别内处理数百万次操作,这使其成为实时应用和高吞吐量系统的理想选择。

  2. 多样的数据结构:Redis不仅支持简单的键值对,还支持丰富的数据结构如列表、集合、有序集合、哈希、位图和HyperLogLog等,这使得开发者可以用更少的代码实现复杂的数据操作。

  3. 持久化:尽管Redis是一个内存数据库,但它提供了多种持久化机制,如RDB快照和AOF日志,可以在重启时恢复数据,从而确保数据的可靠性。

  4. 扩展性:Redis支持分片和集群模式,可以轻松扩展以处理更大的数据集和更高的请求量。这对于需要处理大规模并发请求的应用来说非常重要。

  5. 丰富的生态系统:Redis拥有丰富的客户端库和工具支持,几乎覆盖所有主流编程语言,方便开发者在不同平台和环境中使用。

使用Redis的好处

使用Redis的好处显而易见:

  1. 高性能:Redis的内存存储和高效的数据操作使其能够提供极快的响应时间,适用于需要低延迟和高并发的应用,如实时分析、缓存和会话存储等。

  2. 灵活的数据操作:支持多种数据结构和丰富的操作,使得开发者可以方便地实现复杂的应用逻辑,而无需依赖外部系统。

  3. 简化架构:Redis的多功能性减少了系统中需要的组件数量,可以用作数据库、缓存、消息队列等,从而简化系统架构和维护成本。

  4. 高可用性和持久化:通过主从复制、哨兵和集群模式,Redis提供了高可用性和数据持久化支持,确保数据的安全性和系统的稳定性。

总之,Redis凭借其高性能、多样的数据结构、易用性和强大的功能,成为现代应用中广泛使用的数据存储解决方案。无论是在初创公司还是大型企业中,Redis都能有效提升系统性能和可靠性,是不可多得的优秀工具,接下来让我们一起探究redis的巧妙吧。

redis 安装

  1. 先去redis官网选择对应的版本,window下载.zip linux下载.tar
  2. 进入liunx安装目录执行make下载对应的依赖(linux是由c语言编写的需要gcc环境, brew/wget install gcc -c++)
  3. 进入redis的src/redis-server 启动redis服务,默认redis是占用式(启动服务之后就不能在原有的窗口输入命令了)
  4. 进入reds.conf 修改 redis的默认占用式启动,309行daemonize no 改为 yes. 1049行 requirepass 自己的密码
  5. 用配置文件命令的方式启动redis redis-server ./redis.conf
  6. 配置redis接受远程连接
    1. bind 127.0.0.1 -::1 注释掉
    2. protected-mode yes 改为no
    3. 之后将redis的进程清理掉再重启 1 ps -ef | grep redis , redis-server ./redis/conf
    4. 开放远程服务器的防火墙,远程服务器的安全组 => 防火墙打开6379保存即可

redis常用命令

  • redis-cli 连接本地redis客户端
redis-cli [-options] -h -p -a
# -h:host -p:port -a:指定密码 
  • redis-server ./redis.conf 通过配置文件启动redis服务

redis mac m1客户端

通过命令安装

brew install --cask another-redis-desktop-manager
  • 连接本地redis服务器出现 Client On Error: ReplyError: WRONGPASS invalid username-password pair or user is disabled. Config right?

    解决办法就是name/username空着就行不需要填写

linux配置环境变量

  • 编辑/etc/profile
redis/src # vim /etc/profile 
export PATH = ${PATH}:/redis/redis-7.02/src
  • 遇到/private/etc/profile E212 Can open file for writing无法写入的情况可以试试
1.点击esc  2.输入: w ! sudo tee % 即可保存

Geospatial地理位置

  1. geoadd city 添加城市经度 116.20 39.56 beijing 120.52 30.40 shanghai 添加两座城市的经度
  2. geopos city xxxx 查看该城市的经度纬度
  3. geodist city xxx xxx m/km/ft 两地城市的距离 默认是m
  4. geoserach frommember|经纬度 beijing byradius 500km 以某个城市为圆心搜索指定半径范围内的元素

HperLoglog 基数统计

基数:统计集合中去重之后的个数。

常用场景:

  1. 统计网站的访问uv(独立访问次数)
  2. 一首音乐的独立用户播放
  3. 一段视频的独立用户播放

常用命令

# 1.PFADD KEY NUM 添加
PFADD userlogin 1 2 3 4 5 6 
# 2.PFCOUNT KEY 统计某个key的基数
PFCOUNT userlogin    6
# 3.PFMERGE key1 key2 合并两个key
PFMERGE hll1 hll2

BitMaps

redis 的bitmaps是一种紧凑的数据类型,用于存储二进制的逻辑和状态,bitmaps不是实际的数据类型,而是定义在string上的一组位操作。占用空间及其的少1bit。

常用场景

  1. 打卡 0表示未打 1表示打卡
  2. 登陆状态

常用命令

# SETBIT key index val
SETBIT user1:week 0 1 # 统计一周员工打卡情况
# GETBIT key 
GETBIT user1:week
# BITOP and destkey [key...] 该命令可以用位操作 AND OR XOR NOT
# 统计连续登录的用户
BITOP AND distkey user1:week user2:week
# BITCOUNT key start end
# 统计员工打卡情况
BITCOUNT user1:week 0 0
# STRLEN key 查看某个key内存占用情况
STRLEN user1:week

Redis事务处理

redis事务不保证原子性,事务中有个命令错了(非语法错误,例如 incr str ),不会影响其他命令的执行,但是如果开启了事务,并且写的命令存在语法错误则提交事务时会失败。

事务:业务中整体执行,整体成功or整体失败,以整体的形式去执行,一次性执行多个命令

redis事务命令
  1. multi 开启事务 尾部会有个TX标识 ,输入的命令都会进入queued事务队列中等待exec来执行
  2. discard 取消事务
  3. exec 执行事务
redis乐观锁

redis如何完成乐观锁:就是说redis自带的watch监听的机制

秒杀业务就是通过redis的watch命令来实现了乐观锁的,**如果在事务执行之前watch监听的这些值发生了变化,那么事务会被打断,一旦执行了EXEC or DISCARD命令,所有的watch监控都会被取消。**并发安全问题。

乐观锁:为了保证数据的一致性。

例子:有同台客户端同时操作redis
set age 21
b1开启了事务
b1 (TX)> incr age // 自增年龄 
queued
b2> incr age // 22
b1(TX)> exec 
b1> get age 
b1> 23
----------watch监听解决--------
开启事务前先用watch监控,最后用unwatch释放监控
watch age name 
...
unwatch

watch key 在事务提交时,如果watch所监听到的key的值,被其他客户端所更改时,当执行exec命令时就会出现nil,该事务的整体都不会进行更改。

Redis持久化

redis单线程,redis提供两种持久化机制RDB和AOF ,默认是RDB

RDB快照模式

RDB即快照模式,它是redis默认的持久化方式,它将redis数据库的快照保存在dump.rdb这个二进制文件中。快照:就是将内存数据以二进制文件的形式保存起来,通过时间间隔以快照的方式保存。

redis使用操作系统的多进程COW(copy on writer)机制来实现快照持久化操作。

RDB实际上是redis内部的一个定时器事件

数据备份策略:

  1. 手动策略
    • 通过save / bgsave来保存二进制指令到dump.rdb,推荐使用basave它是开启个子进程来调用fork()来将数据保存到dump.rdb文件,而save则是同步的,写入数据量庞大时,会面临阻塞或者是redis断开连接。
  2. 自动策略
    • 进入redis.conf文件中 找到save 900 1 300 这个是 redis的自动保存策略。900秒 至少有一个key被更改,则创建副本备份数据。

RDB持久化的优劣势

RDB持久化的过程中会开个子进程将redis所有的数据都保存到dump.rdb文件中,即消耗资源也浪费时间。所以不能频繁的创建rdb文件,会严重影响服务器的性能。

RDB最大的不足就是最后一次持久化可能会丢失一部分的数据,在持久化的过程中服务器宕机了,这时存储的数据就并不完整,比如子进程创建好了rdb文件,但服务器还没来得及用它来覆盖旧的rdb文件,这样就会把最后一次持久化的数据丢失。

RDB数据持久化适用于大规模的数据恢复,并且还原速度快,如果对数据完整性不特别的敏感,推荐使用RDB。

AOF追加模式

AOF被称为追加模式,日志模式,它只储存redis服务器已经执行的命令,并且只记录对内存有过修改的命令,这种记录方式叫做增量复制。默认存储文件为appendonly.aof

# 默认情况下appendonly no关闭的,需要在redis.conf中自行打开

重写机制

redis长期运行,aof的文件会越来越大,我们可以通过BGREWRITEAOF命令来为aof文件瘦身

自动触发AOF重写

# redis.conf 默认配置项
auto-aof-rewrite-percentage 100 # 100则表示1倍,200,则2倍
auto-aof-rewrite-min-size 64mb #触发自动重写aof最小的体积,大于or等于64mb则自动触发

redis主从模式

主从模式:一matser多slave,master负责写读,而slave只能读。

主节点一旦宕机,从节点一直等待主节点重新连接

# 单机部署多应用 用端口隔离
  127.0.0.1 6379 master
  127.0.0.1 6380 slave
  127.0.0.1 6381 slave
# 多机部署 ip隔离
  127.0.0.1 6379 master
  127.0.0.2 6379 slave
  127.0.0.3 6379 slave
搭建主从模式
# 通过命令开启一个端口为6300的从机
 redis-server --prot 6300 --slaveof 127.0.0.1 6379 --masterauth sanyueshui --requirepass sanyueshui
  • 取消主从关联
# 在从服务器中使用 即可取消主从模式
slaveof no one 
  • 查看主从情况信息
info replication
配置文件实现主从模式
# 拷贝三份redis的配置文件 redis6300.conf/redis6301.conf
cp ./redis7.2.4/redis.conf ./redis7.2.4/redis6300.conf
# 修改redis6300.conf的端口,主节点密码和6300本机的密码,并关联主节点
port 6300
masterauth 主节点的密码
requirepass 6300从节点的密码
slaveof 127.0.0.1 6379 or replicaof 127.0.0.1 6379 关联主节点
# 保存启动服务即可

# 用配置文件的方式,就写死了主从关系,不灵活。

哨兵模式

哨兵模式是基于主从模式上的改进,自动版主从模式,哨兵模式默认会每30秒轮询一次,查看主节点是否正常工作,如果出现宕机则会触发故障转移,投票选举新的主节点。旧的主节点恢复正常之后会变成从节点跟主节点关联。

主观下线

哨兵是基于心跳机制来检测服务器的状态,每隔一秒向服务器ping ,如果sentinel发现某个实例为在指定时间范围内响应,则认为该实例主观下线

客观下线

若超过一定数量的sentinel都认为该实例主观下线,则被称为客观下线,数量一般是一半以上。

故障转移
  1. sentinel会给备选的节点发送slaveof on one,让该节点成为主节点。
  2. sentinel给其他slave发送slaveof host port命令,开始从master上同步数据。
  3. 最后sentinel将故障节点标记为slave,故障节点恢复后会成为新的主节点的slave。
单机部署哨兵模式
# 复制一份sentinel.conf 文件
cp ./redis/sentinel.conf ./sentinel6300.conf
# 覆盖sentinel6300.conf文件的内容
sentinel monitor myredis 127.0.0.1 6379 1 # sentinel/2+1
sentinel auth-pass myredis sanyueshui

# 主节点宕机以后选举的间隔时间为多少s 单位毫秒
sentinel down-after-milliseconds myredis 10000

# 通过redis-sentinel命令启动 哨兵模式
redis-sentinel ./sentinel6300.conf

redis集群模式

redis集群模式有16384个槽,redis会将每个key进行hash来决定存储在哪个槽中。

  • 集群命令
# 查看当前节点集群信息
cluster info
# 查看所有集群的信息
cluster nodes
单机搭建集群模式
# 创建6个目录 并拷贝redis.conf至目录中
mkdir ./cluster -p 8001 8002 8003 8004 8005 8006 
cp ./redis.conf ../redis/800x

# 编辑reedis.conf配置文件

daemonize yes
port 8001
# 修改数据存储的目录,这里必须要指定不同的目录位置,否者会造成数据的丢失
dir /redis/cluster/8001
# 开启集群模式
cluster-enabled yes
# 集群节点信息文件,这里最好和端口保持一致
cluster-config-file nodes-8001.conf
# 集群节点的超时时限,单位是毫秒
cluster-node-timeout 10000
# 如果是多机设置,阿里云的内网IP或者注释掉或者bind:0.0.0.0、
bind 0.0.0.0
# 受保护模式
protected-mode no 
# 开启aof数据持久化
appendonly yes
# aof持久化文件名
appendfilename "appendonly8001.aof"
# aof文件所存放的位置,它是和dir一起拼接形成的,比如:/redis/redis7.2.4/cluster/8001/aof/appendonly8001.aof
appenddirname "aof"
# 当前服务节点的密码
requirepass sanyueshui
# 主节点的密码
masterauth sanyueushui


# 用redis-server ./cluster/8001/redis8001.conf 分别启动6个服务


# 使用redis-cli创建redis集群 num:代表1主多少从 -a:每个节点的密码
# redis-cli --cluster create --cluster-replicas num host:port -a password
redis-cli --clutser  create --cluster-replicas 1 127.0.0.1:8001 127.0.0.1:8002
127.0.0.1:8003 127.0.0.1:8004 127.0.0.1:8005 127.0.0.1:8006 -a sanyueshui


# 集群的关闭
redis-cli -c -h 127.0.0.1 -p 8001 -a sanyueshui shutdown
集群节点的增加
# 新增个8007的主节点
redis-server ./redis/cluster/8007/redis.conf
# 通过add-node添加节点 这里的127.0.0.1:8001是做陪衬
redis-cli  --cluster add-node 127.0.0.1:8007 127.0.0.1:8001 -a sanyueshui
# 给新添加的主节点添加hash槽 
redis-cli --cluster reshard 127.0.0.1:8007 -a sanyueshui
# How many slots do you want to move ? 分配多少空间   1000
# what is the receiving node ID ? 给谁分配空间   输入需要分配空间节点uuid即可
# Please enter all the source node IDs 是否为其他的节点重新分配hash槽    all  
集群主从节点关系绑定
# 进入从节点的客户端
cluster replicate 绑定主节点的uuid
集群节点删除
# 删除从节点
redis-cli --cluster del-node 127.0.0.1:8008 uuid -a sanyeushui

# 删除主节点 需要将主节点占用的槽位先释放或者是迁移
redis-cli --cluster reshard 127.0.0.1:8087 -a sanyueshui --cluster-from 被删除主节点的uuid
# How many slots do you want to move ? 分配多少空间   1000
# what is the receiving node ID ? 将槽空间给哪个节点   主节点的uuid

缓存穿透 key不存在

当用户去查询某个数据时,会先进入redis缓存,redis缓存没有之后才会去查询数据库,数据库也查询不到的话,就会返回一个空对象,表示查询失败,列如这种请求特别的多,或者是用户利用这种请求来恶意攻击,就会给mysql数据库造成很大的压力,甚至是奔溃,这种现象就叫缓存穿透。

解决方案一:缓存空对象

当mysql返回空对象时,redis将这个对象存储起来,同时为其设置一个过期时间,当用户再次发起相同的请求时,就会从缓存中拿到这个空对象,用户的请求阻断在了redis的缓存层,从而保护了后端数据库,但这种策略会占用redis的缓存空间。

解决方案二:布隆过滤器

用布隆过滤器来判断数据是否存在,可以预防缓存穿透,首先将用户可能会访问的热点数据都存储在布隆过滤器中(也成为缓存预热)当用户请求时会先进入布隆过滤器,如果请求的数据不存在,布隆过滤器会拒绝该请求,用布隆过滤器更高效。

缓存击穿 key过期

用户查询的数据在redis缓存中不存在,但是在数据库中存在,这种原因是由于redis缓存中方的key过期导致的,比如一个热点数据key,在某个时间段失效了,但是它无时无刻都在接受大量的并发访问,则这些请求就会进入后端数据库,导致压力瞬间增大。

解决方案一:改变key的过期时间

设置热点数据永不过期。

把时间全部错开

解决方案二:分布式锁

重新设计缓存的使用方式:

  • 上锁:当我们通过key去查询数据时,首先查询缓存,如果没有,就通过分布式锁进行加锁,第一个获取锁的进程进入后端数据进行查询,并将查询结果缓存到redis中。
  • 解锁:当其他进程发现锁被某个进程占用时,就进入等待状态,直至解锁之后其余进程在以此访问被缓存的key。

缓存雪崩 大量key同时过期

缓存中大量的key同时过期,此时数据访问量又非常大,从而导致后端数据库压力突然暴增,甚至会挂掉,它和缓存击穿不同,击穿是在并发量特别大,某个key突然过期,而雪崩是大量的key同时过期,它们不是一个量级的。

解决方案
  • 高可用
  • 集群

布隆过滤器

布隆过滤器是redis4.0的新功能,它是以插件的形式加载到redis中,给redis提供强大的去重功能。

布隆过滤器在空间上能节省90%以上,但他的不足之处是去重率99%左右,也就是说有1%左右的误判率,在处理海量数据时,几乎可以忽略。

黑白名单,邮件判重,缓存穿透,过滤

布隆过滤器原理

当布隆过滤器添加key时,会使用不同的hash函数对key存储的元素值进行哈希计算,从而会得到多个哈希值,根据哈希值计算出一个整数索引值,将该索引值与位数组长度做取余运算,最终得到一个为数组位置,并将该位置的值变为1,每个hash函数都会计算出一个不同的位置,然后吧数组中与之对应订单位置变为1。通过上述过程就完成了元素的添加(add)操作。

下载安装bloom
  • 通过wget 命令下载
wget https://github.com/RedisBloom/RedisBloom
  • 解压并安装依赖
tar -zxvf ./redis/RedisBloom 

make 
  • 在redis.conf文件末尾添加
loadmodule /redis/redis-7.2.4/RedisBloom-2.2.8/redisbloom.so
  • 重启配置文件
redis-server ./redis/redis.conf
常用命令
bf.add     # 添加元素到布隆过滤器

bf.exists  # 判断某个元素是否存在于布隆过滤器

bf.madd    # 同时添加多个元素到布隆过滤器

bf.mexists # 同时判断多个元素是否存在布隆过滤器

bf.reserve # 以自定义的方式设置布隆过滤器参数值,共3个参数 key error_rate(错误率) initial_size(初始大小)
bf.reserve recard 0.01 1000 # 设定recard 的出错率为 1000中的0.0.1

Go操作redis

  • 下载go的redis模块
go get github.com/gomodule/redigo/redis
var RedisClientPool *redis.Pool

func InitJimDb() {
  RedisClientPool = &redis.Pool{
    MaxIdle:     100,
    MaxActive:   12000,
    IdleTimeout: time.Duration(180),
    Dial: func() (redis.Conn, error) {
      c, err := redis.Dial("tcp", "127.0.0.1:6379", redis.DialPassword("xxxxxx"),redis.DialReadTimeout(time.Second),redis.DialWriteTimeout(time.Second))
      if err != nil {
        logger.Errorf("redisClient dial host: %s, auth: %s err: %s", "127.0.0.1:6379", "xxxxxx", err.Error())
        return nil, err
      }
      return c, nil
    },
    TestOnBorrow: func(c redis.Conn, t time.Time) error {
      if time.Since(t) < time.Minute {
        return nil
      }
      _, err := c.Do("PING")
      if err != nil {
        logger.Errorf("redisClient ping err: %s", err.Error())
      }
      return err
    },
  }

  logger.Infof("init jimDb ok")
}

func CloseJimDb() {
  if RedisClientPool != nil {
    err := RedisClientPool.Close()
    if err != nil {
      logger.Errorf("do CloseJimDb error:%s", err.Error())
    }
  }
}
  • 22
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sanyueshui_Go

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值