ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

Redis学习笔记

2022-07-23 14:34:14  阅读:110  来源: 互联网

标签:缓存 Redis redis 笔记 学习 cluster key 服务器


Redis学习笔记

1、Redis安装目录

  • redis-benchmark:性能测试工具

  • redis-check-aof:修复有问题的aof文件

  • redis-check-rdb:修复有问题的rdb文件

  • redis-sentinel:redis集群使用,启动哨兵

  • redis-server:redis启动命令

  • redis-cli:客户端,操作入口

 

2、redis相关知识

  1. redis有16个库,类似数组下标从开始,初始默认==0号数据库==

  2. 使用 “select 数据库编号” 切换数据库,例如:select 1

  3. dbsize:查看当前数据库key的数量

  4. flushdb:清空当前数据库所有key

  5. flushall:清空所有数据库所有key

  6. redis是单线程 + 多路IO复用

 

 

2、Key的操作

 

3、基本数据类型

1、String

String类型是一个二进制安全的,意味着Redis的String类型可以储存任何类型的数据

String类型是Redis中最常用的类型,其Value最多可以存储==512M==

 

 

2、List

List是一个简单的字符串列表

底层是双向链表

 

3、Set

Set提供的功能与List列表相似,但与之不同的是Set可以自动排重

  1. 添加:sadd key value

  2. 查看所有元素:smembers key

  3. 查看集合是否有某个元素:sismember key elem

  4. 查看集合的元素个数:scard key

  5. 删除元素:srem key elem1 elem2 ...

  6. 两个集合的差集:sdiff key1 key2(key1中的,不包含key2中的)

  7. 两个集合的交集:sinter key1 key2

  8. 两个集合的并集:sunion key1 key2

  9. 随机从集合中弹出n个值:spop key count

  10. 从集合1将值移动到集合2中:smove key1 key2 elem

 

4、Hash

 

 

 

5、Zset

Zset与Set相似,区别为Zset是一个有序的不重复的列表

之所以是有序,就是因为每个元素成员关联了一个评分(score),这个评分用来按照从低分到高分的方式排序集合中的成员。

==集合中的成员是唯一的,但分数是可以重复的。==

 

Zset的底层类似于hash<String,Double>,列表的member就是hash的key,列表的score就类似于hash的value

Zset的底层还是一个跳跃表

  1. 添加:zadd key1 score1 value1 key2 score2 value2 ...

  2. 显示集合中的元素:zrange key start end ,例如:zrange users 0 -1

  3. 显示集合中的元素并带上分数:zrange key start end withscores

  4. 根据分数范围显示元素并带上分数:zrangebysocre key min max withscores

  5. 元素从大到小排序并显示分数:zrevrangebyscore key max min withscores

  6. 分数增加:zincrby key increment member

  7. 删除元素:zrem key member1 member2 ...

  8. 根据分数范围统计个数:zcount key min max

  9. 返回指定成员的排名:zrank key member

 

4、Redis配置

 

 

5、Redis发布订阅

redis发布订阅(pub/sub)是一种消息通信模式:发布者(pub)发布消息,订阅者(sub)订阅消息

redis客户端可以订阅任意数据的频道

  1. 订阅频道:subscribe channel [channel ...]

  2. 发布消息:publish channel message

  3. 退订频道:unsubscribe channel [channel ...]

 

6、新数据类型

1、Bitmaps

Bitmaps本身并不是新的数据类型,底层就是key-value形式的字符串

它是对字符串进行位操作,正因为它是操作位的,所以它的==value只有0和1==

  1. 设置值:setbit key offset value

  2. 取值:getbit key offset

  3. 统计个数:bitcount key [start end]

 

 

3、Geospatial

对地理位置和经纬度的操作,能通过添加地理位置实现地理位置的直线距离

  1. 添加:geoadd key longitude latitude member [longitude latitude member ...]

  2. 获取:geopos key member [member ...]

  3. 获取地理位置的直线距离:geodist key member1 member2 [m|km|ft|mi]

  4. 给定以经纬度为中心,指定半径内所有的地理位置:georadius key longitude latitude radius [m|km|ft|mi]

 

7、Jedis操作Redis

 

 

8、SpringBoot集成Redis

1、导入依赖

 <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
 </dependency>
 ​
 <!--SpringBoot 2.x集成redis所用的连接池-->
 <dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
 </dependency>

2、application.yml配置

 spring:
  redis:
    host: 主机ip
    port: 端口
    timeout: 超时时间(毫秒)
    lettuce:
      pool:
         # 最大连接数
        max-active: 20
         # 最大阻塞等待时间(负数表示没有限制)
        max-wait: -1
         # 连接池最大空闲连接
        max-idle: 5
         # 连接池最小空闲连接
        min-idle: 0

3、config配置类

 import com.fasterxml.jackson.annotation.JsonAutoDetect;
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.annotation.PropertyAccessor;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
 import org.springframework.cache.annotation.EnableCaching;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.data.redis.connection.RedisConnectionFactory;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 ​
 @Configuration
 @EnableCaching
 public class RedisConfig {
 ​
     @Bean
     public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
 ​
         RedisTemplate<String,Object> template = new RedisTemplate<>();
         template.setConnectionFactory(factory);
 ​
         //采用json序列化并对其作出配置
         Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
         ObjectMapper om = new ObjectMapper();
         om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
         //该方法是指定序列化输入的类型,就是将数据库里的数据安装一定类型存储到redis缓存中。
         om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
                 ObjectMapper.DefaultTyping.NON_FINAL,
                 JsonTypeInfo.As.WRAPPER_ARRAY);
         //完成配置,放在jackson2JsonRedisSerializer序列化中
         jackson2JsonRedisSerializer.setObjectMapper(om);
 ​
 ​
         //创建一个String类型的序列化对象
         StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
 ​
         //key采用String的序列化方式
         template.setKeySerializer(stringRedisSerializer);
         //value采用上面定义的json序列化方式
         template.setValueSerializer(jackson2JsonRedisSerializer);
         //hash采用上面定义的json序列化方式
         template.setHashKeySerializer(jackson2JsonRedisSerializer);
         //hash的value采用上面定义的json序列化方式
         template.setHashValueSerializer(jackson2JsonRedisSerializer);
         template.afterPropertiesSet();
 ​
         return template;
    }
 }

 

9、Redis事务

redis事务是一个单独的隔离操作,事务中的所有命令都会序列化,按顺序执行。

事务在执行过程中不会被打断

redis事务最主要的作用就是==串联多个命令,防止别的命令插队==

 

1、Multi、Exec、Discard

输入multi开始,后面输入的命令会放入队列中,但命令不会执行。直到输入exec,命令会按顺序执行。

组队过程中可以通过discard放弃组队

 192.168.40.128:6380> multi
 OK
 192.168.40.128:6380> set age 21
 QUEUED
 192.168.40.128:6380> set name zhangsan
 QUEUED
 192.168.40.128:6380> incr age
 QUEUED
 192.168.40.128:6380> exec
 1) OK
 2) OK
 3) (integer) 22

==注意:redis的事务并不保证原子性,执行过程中有执行错误的命令并不影响其它命令执行成功==

 

2、WATCH key [key ...]

watch与multi配合使用可以实现乐观锁

通过watch命令,我们可以在执行multi之前监视一个或多个key。==当事务执行之前,这些key如果被其它命令改动,那么事务将被打断。==

 

3、UNWATCH key

取消对key的监视

 

4、秒杀案列实现

1、centos7安装ab压力测试工具

 yum install httpd-tools

2、命令

 ab -n 1000 -c 100 -p /opt/postfile -T application/x-www-form-urlencoded http://192.168.182.1:8080/seckill/start/0101/6

 

 ab -n 1000 -c 100  http://192.168.182.1:8080/lock/

 

 

10、Redis持久化

1、RDB

RDB(Redis Database):在指定时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读取到内存

 

RDB的缺点:==最后一次持久化的数据可能丢失==

 

2、AOF

AOF(Append Only File)以日志的形式记录每个写操作(增量保存),将Redis执行过所有写操作的命令记录下来(读操作不记录)。只需追加文件,但不可以改文件。但redis重启之后,就会根据日志文件的内容将写指令从前到后执行一次,以完成数据的恢复操作。

 

注意:AOF默认是不开启的,当AOF和RDB同时开启时,Redis是默认使用AOF。

AOF不会照成数据的丢失

 

 

11、主从复制

优势:1.读写分离,性能扩展

2.容灾快速恢复

1、主从复制配置文件需要修改的属性

多个配置文件有相同内容时,可以选择用:==include redis.conf==命令导入文件作为相同的内用,不同的内容再做覆盖

 pidfile: 进程文件
 port: 端口
 dir: redis安装目录
 dbfilename: rdb文件名
 logfile: 日志文件路径
 replicaof: 从机

示例:

 port 6379
 pidfile /var/run/redis_6379.pid
 logfile "/usr/local/bin/log/redis6379.log"
 dbfilename dump6379.rdb
 dir "/usr/local/bin"

2、查看是主机还是从机的命令

 info replication

3、配从(库)不配主(库)

1、使用命令配置

 slaceof 主机ip 端口

2、在配置文件配置

 replicaof 主机ip 端口

 

4、主从复制原理

从服务器:当从服务器连接到主服务器时,它会向主服务器发送要进行数据同步的消息

主服务器:当接收到从服务器发送过来的数据同步消息后,主服务器会把数据持久化到rdb文件,再把rdb文件发送给从服务器,从服务器再读取rdb文件进行数据同步。

之后每次主服务器进行写操作的时候,会和从服务器进行数据同步。

 

12、薪火相传和反客为主

1、薪火相传

原理:从服务器下还可以允许有从服务器

缺点:但某个从服务器节点挂掉以后,它下面的从服务器不能直接跟主服务器先连

 

2、反客为主

原理:但主服务器挂掉以后,从服务器可以自动上位做主服务器

1、在从机上输入命令:

 slaveof no one

 

13、哨兵模式

作用:能监视Redis服务是否宕机,如果主服务器宕机,哨兵会通过投票机制选出一台主服务器

==原主机重启后会变成从机==

1、创建sentonel.conf配置文件,内容如下

sentinel monitor myredis 127.0.0.1 6380 1
  1. sentinel:代表哨兵

  2. monitor:监视

  3. myredis:为监控对象起的服务名称

  4. 127.0.0.1:主服务器ip

  5. 6380:主服务器端口号

  6. 1:至少有多少个哨兵同意迁移的数量

 

2、启动哨兵命令:redis-sentinel sentinel.conf

 

3、哨兵选举服务器规则:

  1. 选择优先级靠前的

  2. 选择偏移量最大的

  3. 选择runid最小的服务器

优先级在redis.conf中默认:replica-priority 100,值越小,优先级越高

偏移量:从服务器数据与主服务器数据的相似度,相似度越高,偏移量越大

runid:每个redis实例启动后都会随机生成一个40位的runid

 

4、Java连接哨兵模式的redis:只需要连哨兵启动的端口

 

14、Redis集群

问题:在主从模式,薪火相传模式中,主机宕机,导致ip地址发生变化,应用配置中需要修改对应的主机、端口

解决:在Redis3.0中提供了解决方案。就是无中心化集群配置。

1、Redis cluster 配置修改

  1. 打开集群模式:cluster-enabled yes

  2. 设置节点配置文件:cluster-config-file nodes-6379.conf

  3. 设置节点失联时间,超过该时间(毫秒),集群自动进行主从切换:cluster-node-timeout 15000

 

2、将所有节点合成一个集群

组合之前,请确保所有redis实例启动成功后,nodes-xxxx.conf都生成正常。

  1. 进入redis原安装目录的src文件目录下:cd /opt/redis-6.0.6/src/

  2. 组合命令:redis-cli --cluster create --cluster-replicas 1 主机ip1:端口号1 主机ip2:端口号2 [主机ip3:端口号3 ...]

    • -replicas 1 :采用最简单的方式配置集群,一台主机,一台从机

    • 注意:主机ip不能用127.0.0.1

  3. 连接客户端时要以集群的方式连接,加上==-c==:redis-cli -c -h 主机ip -p 端口号

  4. 查看节点中的信息:cluster nodes

  5. 查看key的插槽值:cluster keyslot key

  6. 查看插槽有多少个key:cluster countkeysinslot 插槽值,==注意:只能看自己主机插槽范围的==

  7. 返回插槽中指定数量的key:cluster getkeysinslot 插槽值 count

==集群启动后,会显示集群一共有多少插槽。==

==每台主机分配有固定的插槽个数,redis会根据特定的算法算出key存放在哪台主机的插槽==

 

集群中批量添加问题:

在集群中,如果我们使用过去的方法:mset key1 value1 [key2 value2 ...]来批量添加key,这时我们会发现报错。

原因:多个key的插入集群无法根据多个key来计算插槽

解决:我们可以使用组的方式进行插入,示例:mset id{user} 1 name{user} zhangsan age{user} 23

 

故障恢复:

1、如果某个主节点挂掉,它的从节点会变成主机。我们通过配置文件再次启动挂掉的节点,这时候这个节点会变成从机。

2、但某一段插槽的主从都挂掉:

  • redis.conf配置文件中的参数:cluster-require-full-coverage

  • 如果cluster-require-full-coverage为yes时,那么整个集群都挂掉。

  • 如果cluster-require-full-coverage为no时,该插槽数据全部不能用,也无法储存。但其它插槽都可以用

 

15、Java使用Redis集群

 public static void main(String[] args) {
     // 连接集群中任意一台服务器
     HostAndPort hostAndPort = new HostAndPort("192.168.0.1",6379);
     JedisCluster jedisCluster = new JedisCluster(hostAndPort);
     String value = jedisCluster.set("key","value");
     jedisCluster.close();
 }

 

16、缓存穿透

问题描述:当对一个不存在的数据进行大量的访问时,在redis里面拿不到,那么就会访问数据库获取,数据库查询为空则不进行缓存。这导致这个不存在的数据每次请求都要到数据库去查,最终导致数据库压力变大甚至奔溃。

解决:

  1. 对空值进行缓存:在数据库不存在,把null在redis进行缓存,并设置个过期时间,最长不超过5分钟。

  2. 设置可访问的白名单:用bitmaps设置一个白名单,用id作为bitmaps的偏移量,每次访问与bitmaps的id进行比较,如果不存在,则进行拦截,不允许访问。

  3. 采用布隆过滤器

  4. 进行实时监控:当发现redis的命中率开始急速降低,需要排查访问对象和访问数据,和运维人员配合,设置黑名单限制服务。

 

17、缓存击穿

问题描述:但redis中某个热门的key过期了,但有大量的请求访问这个key,这时候,redis中无法命中,所以这大量的请求落到了数据库上,给数据库照成压力。

解决

  1. 预先设置热门数据:将一些热门数据提前存入redis中,加大这些热门数据key的时长。

  2. 实时调整:现场监控哪些数据热门,实时调整key的过期时间。

  3. 使用锁:缓存失效的时候(判断拿出来的值为),不是立即去load db。而是设置锁,过一段时间再访问。

 

18、缓存雪崩

问题:在极少时间段,大量key集中过期的情况,请求的访问落到数据库,照成数据库奔溃。

解决

  1. 构建多级缓存架构:Nginx缓存 + Redis缓存 + 其它缓存(ehcache缓存等)

  2. 使用锁或队列:使用加锁和队列方式保证不会有大量的访问,但效率也会变低。

  3. 设置过期标志更新缓存:记录缓存数据是否过期(设置提前量),如果过期会触发通知另外线程在后台去更新实际key的缓存。

  4. 将缓存失效的时间分开:比如在原来的失效时间的基础上增加一个随机值,比如随机1-5分钟。

 

 

19、Redis分布式锁

1、分布式锁必须满足的4个条件

  1. 互斥性:任意时刻,只能有一个客户端持有锁。

  2. 不会发生死锁:即使一个客户端在持有锁的时候发生奔溃无法释放锁,也能保证其它客户端能正常加锁

  3. 解铃还须系铃人:加锁和解锁必须是同一个客户端,客户端自己不能把别人的锁给解了。

  4. 加锁和解锁必须具有原子性

 

 

20、Redis6.0新功能

1、ACL

设置哪些命令的操作权限

 

2、IO多线程

 

3、工具支持Cluster

标签:缓存,Redis,redis,笔记,学习,cluster,key,服务器
来源: https://www.cnblogs.com/zhouqiangshuo/p/16511954.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有