Redis基础知识——NWU_LK

Redis基础知识

Redis简介

Redis是由c语言开发的一款完全开源免费的key-value数据库,它支持多种语言的API。Redis是非关系型数据库,因为web2.0的兴起,非关系型数据库变得异常火爆,传统的关系型数据库暴露了太多的问题,关系型数据库很难实现高并发,高效率。
Redis的优点是效率高、丰富的数据类型、原子性(多个操作也支持事务)。
缺点是数据缺少结构化、耗内存(因为redis直接将数据保存在内存中,如果需要持久化有两种方案,一种是定时快照(RDB),即每隔一段时间就将内存中的数据存入磁盘,每次均是写全部数据,代价很高;另一种是只追踪语句的变化(AOF),但是这一种需要大量的log,同时所有操作重新执行一遍。)

Redis安装
  1. 到官网下载tar包并上传到虚拟机:redis的tar包下载地址
  2. 将压缩包解压到opt目录下:tar -zxvf 安装包 -C /opt/
  3. 安装gcc环境:apt-get install build-essential
  4. redis的目录下执行make命令安装
  5. 安装完毕后输入make install测试,发现都显示install
  6. 进入/usr/local/bin目录下,redis已经安装成功
  7. 在该目录下创建myconf目录:mkdir myconf
  8. 将redis中的配置文件拷贝到myconf中:cp /opt/redis-6.0.6/redis.conf myconf
  9. 进入myconf目录,修改该配置文件中的daemonizeyes,修改为后台运行
  10. 回到/usr/local/bin目录下使用命令redis-server myconf/redis.conf启动redis服务
  11. 使用redis客户端连接:redis-cli -p 6379
  12. 通过客户端关闭redis服务:shutdown
Redis基本知识

默认有16个数据库,索引从0到15,默认使用的是第0个数据库。redis5.0版本是单线程的,但是6.0开始变为了多线程。redis基于内存,所以CPU并不是redis的瓶颈,其每秒QPS接近10万+,

命令说明
select index切换数据库
dbsize查看当前数据库大小
keys *查看所有键
flushdb清空当前数据库
flushall清空全部数据库的内容
Redis五大基本类型

基本命令

命令类型
expire key_name second为key设置过期时间
ttl key_name查看剩余过期时间
move key_name index将该键值移动到指定数据库
exists key_name查看该key是否存在
del key_name删除某个key
rename key_name1 key_name2修改key的名称
type key_name查看该类型
  • String类型:使用场景比如计数器
命令说明
set key_name value设置key、value
setex key second value设置键值并设置超时
setnx key_name value键不存在则设置,设置成功返回1,否则0
get key得到key的值
append key_name value向该key中追加值
strlen key_name查看该key的value长度
getrange key_name start end得到key中值的一部分
getset key value设置新值,返回旧值
mset key1 value key2 value2批量设置键值
msetnx key1 value key2 value2不存在则设置,有一个不成功都不成功
mget key1 key2批量获取键的值
incr key_name对应的值+1
decr key_name对应的值-1
incrby key_name x对应的值+x
decrby key_name x对应的值-x
  • Hash类型:经常用于保存对象
命令说明
hset key field value设置键值对
hsetnx key field valuefield 不存在时,设置值。
hmset key field1 value1 field2 value2批量设置键值对
hget key field获取指定键的值
hmget key field1 field2批量获取若干个键的值
hgetall key获取全部的键值
hkeys key获取所有的键
hvals key获取所有的值
hlen key获得键值对的个数
hdel key field删除键名为field的键值对
hincrby key field x为指定键的值增加x
hincrbyfloat key field x为指定键的值加浮点型的x
hexists key field查询某个键是否存在
  • List类型
命令说明
lpush key value1 value2左侧头部插入
rpush key value1 value2右侧尾部插入
llen key获取列表长度
lindex key index通过索引获得队列中的元素
lrange key start stop获取start到stop的元素
lpop key左边移除一个
rpop key右边移除一个
lset key index value修改特定位置的值
lrem key count value移除count个指定的值
ltrim key start stop仅保留index在start到stop之间的值
rpoplpush key1 key2将key1移除一个并添加到key2中
linsert key before|after pivot value在列表的元素前或者后插入元素
blpop key1 [key2 ] timeout移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
brpop key1 [key2 ] timeout移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
  • Set类型
命令说明
sadd key member1 [member2]向集合添加一个或多个成员
scard key获取集合的成员数
smembers key返回集合中的所有成员
sismember key member判断 member 元素是否是集合 key 的成员
srandmember key [count]返回集合中一个或多个随机数
srem key member1 [member2]移除集合中一个或多个成员
spop key count随机删除count个元素
smove key1 key2 value将set1中的value移动到set2
sdiff key1 key2返回set11和set2的差集
sdiffstore key3 key1 key2返回set1和set2的差集并存入set3
sinter key1 key2返回set1和set2的交集
sinterstore key3 key1 key2返回set1和set2的交集并存入set3
sunion key1 key2返回set1和set2并集
sunionstore key3 key1 key2返回set1和set2的并集并存入set3
  • ZSet类型(有序集合,实现工资表排序等)
命令说明
zadd key score value添加成员,用score排序
zcard key查看成员数
zcount key min max返回在指定区间的成员数
zrank key value返回指定值的索引
zrange key start stop返回索引start到stop之间的值
zrevrange key start stop返回索引start到stop之间的值,且是倒序
zrangebyscore key -inf inf返回根据score排序的从小到大序列
zrangebyscore key -inf inf withscores返回根据score排序的从小到大序列并附带分数
zrem key value删除某个成员
zremrangebyrank key start stop移除下标从start到stop之间的值
zremrangebyscore key score1 score2移除分数介于二者之间的所有值
zincreby key x value给该value加x
三种特殊的数据类型(了解)
  • geospatial indexes:可以推算地理位置信息,两地之间的距离等,基于Zset编写,所以zset的一些指令可以使用。
指令说明
geoadd key 经度 纬度 城市向key中添加一个城市的经纬度信息(经度从-180到180,纬度从-85.05到85.05)
geopso key 城市1 城市2获取该城市的经纬度
geodist key 城市1 城市2 km获取城市1和城市2的距离,单位是km
georadius key 经度 纬度 距离 km 【withdist | withcoord】获取key中距离该经纬度指定半径的所有城市
georadiusbymember key 城市 距离 km【withdist | withcoord】获取key中距离该城市指定半径的所有城市
geohash key 城市返回该城市对应位置的hash
  • hyperloglogs:网站统计访问次数等可以使用
指令说明
pfadd key value1 value2定义key
pfcount key查询不重复的元素个数
pfmerge key3 key1 key2将key1和key2中的并集合并到key3
  • bigmaps:位存储,每个键只有两个值,分别是0和1。
指令说明
setbit key offset 0|1定义key
getbit key offset获取信息
bitcount key获取为1的数目
Redis事务

redis的事务不保证原子性,redis事务的本质是一组命令的集合,按照顺序执行。redis的事务没有隔离级别的概念redis的事务可以分为三个步骤:

  1. 开启事务:multi
  2. 命令入队:各种redis的命令
  3. 执行事务或放弃事务:exec(提交)或discard(取消)

如果事务中有编译型异常,也就是语法有错误,那么该事务中所有的命令都不会执行。如果有运行时异常,那么只有产生异常的命令才会执行失败。

  • redis实现乐观锁
    通过watch命令来实现,语法为watch key,表示对某个key进行监视,然后开启事务操作该事务,若此时其他线程对该key进行操作,修改了key中的值,那么会使得该事务执行失败,自动实施unwatch命令
Jedis操作redis

引入Jedis依赖即可,通过Jedis jedis=new Jedis(IP地址,端口号)获取jedis对象,该对象的方法和redis的命令完全相同。前提要关闭redis的只允许本机访问的限制,将redis.conf中的bind 127.0.0.1注释掉;关闭保护模式,将redis.conf中的protected-mode改为no

Springboot整合redis

SpringBoot2.0之后,底层采用lettuce替换了jedis,springboot操作redis主要通过reidsTemplate和stringRedisTemplate。

redisTemplate主要通过以下几个方法去操作不同的数据类型:

  • opsForValue:操作字符串类型
  • opsForHash:操作哈希类型
  • opsForList:操作列表
  • opsForSet:操作集合
  • opsForZset:操作有序集合
  • opsForGeo:操作地理信息
  • opsForHyperLogLog:操作基数

也可以通过redisTemplate.getConnectionFactory().getConnection()获取connection对象后直接操作数据库。但是redis默认的序列化方式为jdk序列器,需要自己手动编写配置类并修改配置信息。

redis配置文件
通用配置说明
bind 127.0.0.1绑定的ip
protected-mode yes保护模式
port 6379绑定的端口号
daemonsize yes是否守护态运行
pidfile /var/run/redis_6379.pid以守护态运行需要指定的pid文件
requirepass 密码设置redis密码
日志配置说明
loglevel notice日志级别
logfile /日志文件的地址
databases 16默认的数据库数量
always-show-logs yes是否总是显示log
持久化配置说明
save 次数 时间表示在一定时间内超过指定的次数就持久化
stop-writes-on-bgsave-error yes持久化产生错误是否正常工作
rdbcompression yes是否压缩rdb文件
rdbchecksum yes保存rdb文件时,进行错误检查
appendonly no默认为rdb,不开启aof模式
appendfilename appendonly.aofaof的持久化文件名称
appendfsync always|everysec每次修改同步或者每秒同步
redis持久化
  • RDB模式(Redis Database)
    在指定的时间内将数据快照写入磁盘,redis会单独创建一个进程来持久化,先将数据快照保存为临时rdb文件,然后替换掉上次保存的快照,文件名为dump.rdb。期间主进程不进行任何操作,rdb比aof更加高效,适合大规模的数据恢复。缺点就是最后一次持久化的数据可能丢失。

    触发的规则:

    1. save规则满足时,自动触发rdb持久化
    2. 执行flushall命令也会触发
    3. 退出redis也会产生rdb文件

    恢复rdb:放到redis的启动目录下(也就是/usr/local/bin目录下)

  • AOP模式
    以日志的形式来记录每一次写操作,只许追加文件但不许修改文件,redis在启动之初会读取该文件重新构建数据,该文件的默认名称为appendonly.aof。该模式默认是不开启的,需要在配置文件中手动开启。

    如果aof文件发生了错误,redis是不能启动的,此时需要redis-check-aof工具修复aof文件,命令为redis-check-aof --check aof文件名

redis发布订阅

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

指令说明
subscribe 频道1 频道2…订阅某个频道
unsubscribe 频道1 频道2…退订某个频道
public 频道1 message向频道1发送消息
psubscribe pattern [pattern …]订阅一个或多个符合给定模式的频道
punsubscribe [pattern [pattern …]]退订所有给定模式的频道。
redis主从复制

redis的最大内存尽量不超过20G,否则最好切换成集群模式。redis可以实现一主多从,将主机的数据复制到从机上面,可以进行故障恢复。redis主机以写为主,从机以读为主,实现了负载均衡。用命令info replication可以查看当前机器的主从信息。

  • 主从配置
  1. 临时配置主从机:默认情况每一台redis都是主机,配置成从机需要用命令slaveof 主机IP地址 主机端口号去将另一台redis配置为主机,当前机器就变为了另一台的从机,该配置重启后又变为主机。
  2. 永久配置主从机:通过配置文件,找到replicaof masterip masterport将其配置为主机的IP和port即可。如果主机的redis有密码,就在masterauth 密码处填写主机的密码即可

主机追加了key-value后,从机中也会有相应的key-value,但是从机默认是只读的,不能修改该key-value。

  • 复制原理
    从机连到主机上后,会执行一次sync命令,去同步主机的全部数据
  1. 全量复制
    从机启动时会去主机复制全部的数据
  2. 增量复制
    从机运行过程中,主机写入的任何数据都会写入从机中

当主节点断了之后,从节点可以手动用命令slaveof no one让自己成为主节点

  • 哨兵模式
    如果主节点断了之后从节点需要手动配置的话,费时费力,也会造成一段时间内服务不可用
    在这里插入图片描述
    当主服务器宕机后,哨兵1检测到了该情况,此时还不会立即选举主节点,当其他哨兵也陆续发现该主机宕机并且数量达到一定的值后,其中一个哨兵就会发起一次投票,票数最多的从机会当选为新的主机。
    配置哨兵模式:
    1. 在myconf目录下创建配置文件sentinel.conf

    2. 输入配置信息:sentinel monitor 被监控主机点的名称 主机 端口号 1
      sentinel中的配置信息还有很多:

      #配置端口
      port 26379
      #以守护进程模式启动
      daemonize yes
      #日志文件名
      logfile "sentinel_26379.log"
      #存放备份文件以及日志等文件的目录
      dir "/opt/redis/data"
      #监控的名称 IP 端口号  sentinel通过投票后认为mater宕机的数量,此处为至少2个
      sentinel monitor mymaster 192.168.192.129 6379 2
      #30秒ping不通主节点的信息,主观认为master宕机
      sentinel down-after-milliseconds mymaster 30000
      #故障转移后重新主从复制,1表示串行,>1并行
      sentinel parallel-syncs mymaster 1
      #故障转移开始,三分钟内没有完成,则认为转移失败
      sentinel failover-timeout mymaster 180000
      
    3. 启动sentinel的进程:redis-sentinel myconf/sentinel.conf

redis的缓存穿透和雪崩

缓存穿透:就是当用户要查询某条数据时,在redis缓存数据库中没查找到,也就是缓存没有命中,那么就会去mysql数据库中查找,如果访问量特别大,那么就会给持久层的数据库(mysql)造成很大的压力。这就叫缓存穿透。这种情况一般都是恶意用户的请求,比如查询id为-1的用户,数据库中一直查不出来,因此就一直不会放入redis,所以会一直穿透redis进入数据库的查询。解决方案:

  1. 布隆过滤器。
  2. 参数的合法性检验,如果不合法直接返回错误
  3. 缓存空对象,然后设置过期时间,可能产生的问题就是数据库已经有了,但缓存中还没有,因为设置了延时。

缓存击穿:缓存击穿是指对某个热点key查询时,该key过了设置的过期时间,那么请求会大量的走到mysql中,造成持久层压力大。解决方案:

  1. 是设置热点key不过期(不推荐)
  2. 加互斥锁,一个时刻只能有一个线程去访问mysql,其他线程只许等待即可
  3. 分布式锁

缓存雪崩:一段时间内,key全部过期或者redis发生了宕机。解决方案:

  1. 实现redis高可用,将热点数据存放在不同节点上
  2. 限流降级,利用hystrix或者sentinel等技术配置服务兜底方案。
  3. 数据预热:手动的添加key,即把可能访问的数据先访问一边保存在缓存中,可以设置不同的过期时间,让缓存过期的时间尽量均衡
  4. 随机设置缓存的失效时间,让缓存不要再同一时间失效
  5. 设置定时任务,当缓存快要过期时再次将缓存放入redis
写在后面

该笔记是在B站狂神说java的课程学习中记录的,感谢狂神带我入门。在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值