redis知识大纲(持续更新)

下载安装

  1. 官网:https://redis.io
  2. 解压直接可以使用:
    • redis.windows.conf:配置文件
    • redis-cli.exe:redis的客户端
    • redis-server.exe:redis服务器端

命令操作

通用命令

  • 默认有16个数据库
      	1. select 1~16 进入指定数据库
		2. keys* 	查看数据库所有key
		3.flushdb	清除当前数据库
		4.flushall 	清除所有数据库
		5. keys * 查看所有key
		6. exists  name #判断名字是否存在
		7. move name 1 #移除 key为name的数据
		8. del name #删除key
		9. expire name 10 #设置key的过期时间,单位为秒
		10. ttl name  #查看当前key的剩余时间
		11. type name #查看当前key的类型

更多请查看官网:
redis命令

  • redis是单线程的,为什么单线程速度还是非常快
    核心:redis将所有的数据全部放在内存中,单线程操作效率是最高的,多线程(CPU上下文切换:耗时操作)

redis的数据结构:

  • redis存储的是:key,value格式的数据,其中key都是字符串,value有5种不同的数据结构
    * value的数据结构:
    1) 字符串类型 string
    2) 哈希类型 hash : map格式
    3) 列表类型 list : linkedlist格式。支持重复元素
    4) 集合类型set : 不允许重复元素
    5) 有序集合类型 sortedset:不允许重复元素,且元素有顺序

字符串类型 string

	1. 存储: set key value
	2. 获取: get key
	3. 删除: del key
	4. 追加:append key value
	5. 获取长度:strlen key
	6. 自增+1:incr key
	7. 自增指定步长:incrby key step
	8. 自减-1:decr key
	9. 截取:getrange key start end  #0开始   
	10. 替换指定位置字符:setrange key
	11. setex   #set with expire 赋值并设置过期时间
	12. setnx  #set with not exists 若不存在则设置(在分布式锁中会常常用到)
	13. 批量赋值:  mset key value ....
	14. 批量获取:  mget key key ......
	15. 先get再set:getset key

列表类型 list:双向链表

  • 每一个节点都有指向前一个节点和后一个节点的指针。
  • 头节点和尾节点的prev和next指针指向为null,所以链表是无环的。
  • 可以添加一个元素到列表的头部(左边)或者尾部(右边)
     1. 添加:
         1. lpush key value: 将元素加入列表左表
         2. rpush key value:将元素加入列表右边
         3. lindex key 下标:获取指定下标元素
         4. Linsert key BEFORE|AFTER value1 value2:将value2插入到value1之前 | 后 
     2. 获取:
         * lrange key start end :范围获取
     3. 删除:
         * lpop key: 删除列表最左边的元素,并将元素返回
         * rpop key: 删除列表最右边的元素,并将元素返回
     	 * Lrem key count value:删除 num 个值为 value 的元素
     4. 修改:
     	* lset key index value:修改指定位置元素的值,下标越界爆错  
     6. Llen:获取长度 
     7. Ltrim key start end:截取指定范围的数组,改变 list(被截断)
     8. RpopLpush 源集合 目标集合:源集合右侧弹出一个元素并添加到目标集合

集合类型 set : 不允许重复元素

  • 整数集合和字典两种方式来实现,当满足如下两个条件的时候,采用整数集合实现;一旦有一个条件不满足时则采用字典来实现。
    1. Set 集合中的所有元素都为整数
    2. Set 集合中的元素个数不大于 512(默认 512,可以通过修改 set-max-intset-entries 配置调整集合大小)
     1. 存储:sadd key value
     2. 获取:
	     * smembers key:获取set集合中所有元素
	     * SrandMember key [count]:随机获取 count 个元素(默认一条)
	     *  sdiff key1 key2 	#获取差集
       	 * sinter key1 key2 	#获取交集
       	 * sunion key1 key2	#获取并集
     3. 删除:
     	 * srem key value:删除set集合中的某个元素
     	 * spop key [count]:随机删除 count 个元素,默认1一条
     4. 其它:
   		*  判断是否包含指定值(返回1 | 0):Sismember key member	
   		* 移动指定元素至其它集合:Smove  源 目标 元素

哈希类型 Hash

相当于 key-map,值为一个map集合

 1. 存储: 
   	  * hset key field value
   	  * hsetnx key field value	#如果不存在则设置反之存在不设置
 3. 获取: 
      * hget key field		# 获取指定的field对应的值
      * hgetall key			#获取所有的field和value
      * hkeys key			#获取所有 field
      * hvals key			#获取所有的值
      * hlen key			#获取hash表的字段数量
 4. 删除: hdel key field 
 5. 其它:
 	* Hexists key field		#判断hash中指定字段是否存在
 	* HincrBy key field num	#将指定值自增 num

有序集合类型 Zset:

  • 有序不重复,每个元素关联一个double类型的分数。通过分数进行从小到大的排序。
     1.存储:zadd key score value
     2. 获取:
     	* zrange key start end [withscores]		# 查询所有 升序排序
     	* zRevRange key start end 				# 查询所有  降序排序
     	* zrangeByScore key min max				# 查询 score 在 最小值和最大值之间的数据
     	* zcard key								# 获取有序集合中的个数
     	* zcount key score1 score2				# 获取分数区间元素的个书
     3. 删除:zrem key value

三大特殊类型

geospatial 地理位置


地理位置查询

GEO底层的实现原理就是Zset,可以使用Zset命令操作GEO
redis 1. 添加 * geoAdd key 经度 维度 名称 2. 查看 * geoPos key 名称 #获取指定城市的精确经纬度 * geoDist key 名称1 名称2 单位(mi/km/ft) #获取两城市之间的直线距离 * geoRadius key 经度 维度 num 单位 #查询指定经纬度范围内 key中存在的元素 3. 删除 * zrem key 名称

Hyperloglog 基数统计 不重复

优点:占用的内存是固定的,12KB内存
	1. 添加:
		* PFadd key 元素		#添加元素到key(不重复)
		* PFmerge key1 key2 # 合并 key1 key2 => key1 并集
	2. 查看:
		* PFcount key		# 查看key中元素的个数
	3. 删除:

Bitmap 位存储

统计用户信息,活跃,不活跃,登录,未登录,打卡,365打卡
bitmap:位图,数据结构。都是操作二进制来进行记录,只有0和1两个状态
在这里插入图片描述

	1. 添加
		*  setbit  key 下标 1|0
	2. 查看
		* getbit key 下标
	3. 删除
	4. 其它:
		* 统计区间1的个数:bitcount key start end

在这里插入图片描述

事务

redis 事务本质:一组命令的集合!一个事务中的所有命令都会被序列化,会顺序执行

redis 单条命令式保持原子性的,但是事务不保证原子性
redis 事务中没有隔离级别的概念

  1. 开启事务(multi)
  2. 命令入队(… )
  3. 执行事务(exec )
  4. 放弃事务(discard)
  • 编译型异常( 命令有错 ),事务中所有命令不执行,
  • 运行时异常(1/0),其它命令正常执行
    示例:
    127.0.0.1:6379> multi 		#开启事务
    OK
    127.0.0.1:6379> set name zhangsan # 命令入队
    QUEUED
    127.0.0.1:6379> set gender sex  # 命令入队
    QUEUED
    127.0.0.1:6379> get name  	# 命令入队
    QUEUED
    127.0.0.1:6379> get gender  # 命令入队
    QUEUED
    
    127.0.0.1:6379> exec		# 执行事务
    1) OK
    2) OK
    3) "zhangsan"
    4) "sex"
    

redis实现乐观锁

	加锁:watch key		#监视该key的值,对key进行操作之前,先比较值是否相同,相同则继续,否则失败
	解锁:unwatch		#解锁

Jedis

  • jedis:redis官方推荐的 java连接开发工具,即使用 java 操作 redis
  1. pom.xml 导入依赖
    		<!-- jedis -->
            <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
                <version>3.6.0</version>
            </dependency>
            <!-- fastjson-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.75</version>
            </dependency>
    
  2. 编码测试:
    可看到,jedis对象中存在客户端的所有命令
    在这里插入图片描述

SpringBoot整合redis

说明:springboot2.x之后,原来使用的jedis 被替换为了 lettuce
jedis:采用的直连,多个线程操作的话,是不安全的,如果想要避免不安全,使用jedis pool连接池
lettuce:采用netty,实例可以在多个线程中进行共享,不存在进程不安全的情况!可以减少线程数据

  • pom.xml导包
    		<!-- 	redis	-->
    		<dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
            <!-- 	web	-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
  • 可在 RedisProperties 中查看可以配置的参数
    在这里插入图片描述
  • 使用
    	@Autowired
        private RedisTemplate redisTemplate;
    
        @Test
        void contextLoads() {
            // opsForXXX        操作 XXX
            // opsForValue()    操作 String
            // opsForHash()     操作 hash
            redisTemplate.opsForValue().set("key1","hello");
        }
    
  • 序列化
    @Configuration
    public class RedisConfig {
    
        @Bean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
            RedisTemplate<String, Object> template = new RedisTemplate();
            template.setConnectionFactory(redisConnectionFactory);
            // value 序列化配置
            Jackson2JsonRedisSerializer<Object> objectJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
            template.setDefaultSerializer(objectJackson2JsonRedisSerializer);
    
            // key 序列化配置
            StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
            template.setKeySerializer(stringRedisSerializer);
            template.setHashKeySerializer(stringRedisSerializer);
            return template;
        }
    }
    
    

Redis.conf 详解

  • 单位
    在这里插入图片描述
  • 包含:可包含其它配置文件
    在这里插入图片描述
  • 网络
    	* bind 127.0.0.1 			# 绑定 ip
    	* protected-mode yes		# 保护模式
    	* port 6379					# 端口
    
  • GENERAL 通用
    	* daemonized yes			# 以守护进程的方式运行,默认 no 
    	* pidfile /var/run/redis.pid #如果以后台方式运行,需要指定一个pid文件
    	* loglevel notice			# 日志
    	* logfile ""				# 日志的文件位置名
    	* databases 16				# 数据库数量,默认16个
    	
    
  • 快照:持久化,规定时间内,执行了多少次操作,则会持久化到文件 .rdb .aof
    	* save 900 1				# 900秒内,如果至少有 1个 key 进行了修改,则进行持久化
    	* save 300 10				# 300秒内,如果至少有 10个 key 进行了修改,则进行持久化
    	* save 60 10000				# 60秒内,如果至少有 10000个 key 进行了修改,则进行持久化
    	* stop-writes-on-bgsave-error yes	# 持久化如果出错,是否继续工作
    	* rdbcompression yes		# 是否压缩 rdb 文件,需要消耗一些 cpu 资源
    	* rdbchecksum yes			# 保存rdb文件时,进行错误的检查校验
    	* dir ./					# rdb 文件保存的目录
    
  • 复制:REPLICATION
  • 安全:SECURITY
    	* requirepass				# 密码
    
  • 限制:LIMITS
    	* maxclients 10000			# 设置能连接上reids的最大限制
    	* maxmemory <bytes>			# 设置最大的内存容量
    	
    	* maxmemory-policy noeviction  # 内存上限之后的处理策略(六种)
    								1、volatile-lru:只对设置了过期时间的key进行LRU(默认值) 
    								2、allkeys-lru : 删除lru算法的key   
    								3、volatile-random:随机删除即将过期key   
    								4、allkeys-random:随机删除   
    								5、volatile-ttl : 删除即将过期的   
    								6、noeviction : 永不过期,返回错误
    
  • APPEND ONLY MODE:模式,aof配置
    	* appendonly no				# 默认不开启aof模,默认使用rdb方式进行持久化操作
    	* appendfilename "appendonly.aof"	# 持久化文件的名字
    	# appendfsync always				# 每次修改都会 sync,消耗性能
    	* appendfsync everysec				# 每秒执行一次 sync,可能会丢失这1s的数据
    	# appendfsync no					# 不执行 sync,这时候操作系统自己同步数据,速度最快
    

持久化

  • redis持久化机制:指定间隔时间内,检测key的变化,持久化数据
  1. RDB:默认
    保存的文件:dbfilename dump.rdb

    1. 配置redis.windwos.conf文件
      	* save 900 1			# 900秒后,至少有一个键被改变
      	* save 300 10			# 300秒后,至少有10个键被改变
      	* save 60 10000			# 60秒后,至少有10000个key被改变
      	* save 50  3				#自定义策略
      
     2. 触发机制
     	> 1. save规则满足
     	> 2. 执行 flushall 命令
     	> 3. 退出redis时
     3. 恢复
     	> 将 rdb 文件放在我们redis启动目录即可,redis启动时自动检查dump.rdb 恢复其中的数据
     	> 查看存放的位置:  
     			```
     					127.0.0.1:6379>    config get dir
     					```
     4. 优点:
     	* 适合大规模的数据恢复
     	* 对数据的完整性要求不高
     5. 缺点
     	* 需要一定的时间间隔进程操作!若redis意外宕机,则最后一次修改数据消失
     	* fork 进程时,会占用一定的内存空间
    
  2. AOF(append only file):将操作过的所有命令(写操作)记录下来,恢复时执行该文件的全部命令
    保存的文件:appendonly.aop

    1. 配置 redis.windwos.conf
      appendonly yes (开启aof)
      
    2. 持久化配置
       1. appendfsync always : 每一次操作都进行持久化
       2. appendfsync everysec : 每隔一秒进行一次持久化
       3. appendfsync no	 : 不进行持久化 
      
    3. 修复工具:redis-check-aof
      	redis-check-aof --fix appendonly.aop    	
      
    4. 优点:
      1. 每一次修改都同步,文件的完整会更好
      2. 每秒同步一次,可能丢失一秒的数据
      3. 从不同步,效率最高
    5. 缺点:
      1. 相对于数据文件来说,aof 大于rdb,修复速度也比 rdb 慢
      2. aof 运行效率比 rdb 慢,所以redis默认配置为 rdb 持久化

Redis 发布订阅


	@Configuration
	//@EnableCaching // spring缓存需要就开启
	public class RedisConfig {
    /*序列化*/
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setConnectionFactory(factory);
        //key序列化方式
        RedisSerializer<String> stringRedisSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringRedisSerializer);
        //value序列化
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //value hashmap序列化
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        return template;
    }

    /*缓存*/
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        //解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        // 配置序列化(解决乱码的问题),过期时间600秒
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                .disableCachingNullValues();
        return RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
    }

    /**
     * redis 监听配置
     *
     * @param redisConnectionFactory redis 配置
     * @return
     */
    @Bean
    public RedisMessageListenerContainer redisContainer(RedisConnectionFactory redisConnectionFactory, MessageListenerAdapter commonListenerAdapter) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisConnectionFactory);
        container.addMessageListener(commonListenerAdapter, new ChannelTopic(RedisConstant.MSG_CHANNEL));
        return container;
    }

    @Bean
    MessageListenerAdapter commonListenerAdapter(RedisReceiver redisReceiver) {
        MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(redisReceiver, "onMessage");
        messageListenerAdapter.setSerializer(jacksonSerializer());
        return messageListenerAdapter;
    }

    private Jackson2JsonRedisSerializer jacksonSerializer() {
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        return jackson2JsonRedisSerializer;
    }
}

发送消息:redisTemplate.convertAndSend(RedisConstant.MSG_CHANNEL,new JSONObject());

	
	@Component
	public class RedisReceiver {
	
	    @Autowired
	    private WebSocket webSocket;
	
	    /**
	     * 接受消息并调用业务逻辑处理器
	     */
	    public void onMessage(JSONObject map) {
	        System.out.println("收到数据",map);
	    }
	}

Redis 主从复制

  • 概念:主从复制,是指将一台redis服务器数据复制到其它的redis服务器上,前者称为主节点(master/leader),后者称为从结点(slave/follower);数据的复制是单向的,只能由主节点到从节点,master以写为主,slave以读为主

  • 主从复制的作用主要包括:

    1. 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式
    2. 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余
    3. 负载均衡:当主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个结点分担读负载,可以大大提高redis服务器的并发量
    4. 高可用(集群)基石:除了上述作用意外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是redis高可用的基础
  • 一般来说,要将redis运用于工程项目中,只使用一台redis是万万不能的(宕机,一主二从),原因如下:

    1. 从结构上,单个redis服务器会发生单点故障,并且一台服务器需要处理所有的请求负载,压力较大

    2. 从容量上,单个redis服务器内存容量有限,就算一台redis服务器内存容量为256G,也不能将所有内存作redis存储内存,一般来说,单个redis最大使用内存不应该超过 20G

    3. 电商网站的商品,属于 读多写少,推荐使用以下架构

      在这里插入图片描述
      主从复制,读写分离!80%的情况下都是在进行读操作!架构中经常使用!一主二从

环境配置

  • 查看当前库的信息
  • copy三份配置文件,修改端口,rdb文件名,启动
    	127.0.0.1:6379> info replication 		#  info查看信息
    	# Replication
    	role:master								# 角色master
    	connected_slaves:0						# 0个从机
    	master_replid:34da02abad8667ca3861112dbebf94d98a524bc0
    	master_replid2:0000000000000000000000000000000000000000
    	master_repl_offset:0
    	second_repl_offset:-1
    	repl_backlog_active:0
    	repl_backlog_size:1048576
    	repl_backlog_first_byte_offset:0
    	repl_backlog_histlen:0
    
  • 默认情况下每台redis服务都是主节点;一般情况下只用配置从机

    slaveof ip 端口

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值