redis基础

redis

特点

  • 可持久化

  • NoSQL

  • 应用于缓存

  • session分离

##应用场景

在Java web中,redis主要用于:

  1. 存储缓存用的数据;

  2. 需要高速读/写的场合使用它快速读/写。

应用要求:

  1. 业务数据常用吗?命中率如何?如果命中率很低,就没有必要写入缓存;

  2. 该业务数据是读操作多,还是写操作多?如果写操作多,频繁需要写入数据库,也没有必要使用缓存;

  3. 业务数据大小如何?如果要存储几百兆字节的文件,会给缓存带来很大的压力,这样也没有必要。

redis命令

  1. ping

  2. get/set

set name value

get name

  1. del

  2. keys*

  3. flushdb

清空所有数据

Jedis

单实例连接redis

  1. host,port

  2. select(0)//十六库选择

  3. set(“key”,“value”)

  4. expire(“key”,xx秒)//有效期

  5. get(“key”)

  6. hset(“库名”,“key”,“value”)

  7. hget(“库名”,“key”)

参考代码:

    import org.junit.Test; 

      import redis.clients.jedis.Jedis; 

      public class AppTest{  

        @Test  

        public void testJedisSingle() {  

            //创建Jedis对象,传递两个参数:第一个host为redis服务器的名称, 第二个为redis服务器的端口号   

            Jedis jedis = new Jedis("192.168.5.128", 6379);   

                //进行设值操作   

                jedis.set("username","zhangsan");  

                //从redis中取值   

                String username = jedis.get("username");  

                System.out.println("username:"+username);  

            } 

        }

连接池连接redis


    import org.junit.Test; 

    import redis.clients.jedis.Jedis; 

    import redis.clients.jedis.JedisPool; 

    import redis.clients.jedis.JedisPoolConfig; 

     

    public class AppTest{ 

     @Test 

     public void testJedisPool(){

        //创建JedisPool连接池配置   

        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();

        //设置连接池的最大连接数   

        jedisPoolConfig.setMaxTotal(20);  

        //设置连接池的最大连接空闲数       

        jedisPoolConfig.setMaxIdle(2);

          //设置redis服务器的主机   

           String host = "192.168.5.128";

        //设置redis服务器的端口

        int port = 6379;

       //创建JedisPool连接池对象   

        JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port);

       //获取Jedis对象

       Jedis jedis = jedisPool.getResource();

       //存入数据   jedis.set("info", "message");

      //获取数据

       String info = jedis.get("info");  

       System.out.println("info:"+info);

      //关闭资源

       jedisPool.close();

      } 

    } 

    

redis数据类型

String

格式: set key value

string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。

string类型是Redis最基本的数据类型,一个键最大能存储512MB。

##hash

格式: hmset name key1 value1 key2 value2

Redis hash 是一个键值(key=>value)对集合

Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。

list(双向链表)

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)

格式: lpush name value

在 key 对应 list 的头部添加字符串元素

格式: rpush name value

在 key 对应 list 的尾部添加字符串元素

格式: lrem name index

key 对应 list 中删除 count 个和 value 相同的元素

格式: llen name

返回 key 对应 list 的长度

set(散列存储)

格式: sadd name value

Redis的Set是string类型的无序集合不能重复

集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)

##sorted set(有序集合、每个元素带有分数)

格式: zadd name score value

Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。

不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。

zset的成员是唯一的,但分数(score)却可以重复

redis持久化

RDB

在 redis.conf 中以“sava 时长(秒) 更改键的个数”作为条件进行快照。可以拥有多个条件,不同的条件之间是或的关系。当满足条件时,将改变写入磁盘。

AOF(Append-only file)

需要手动开启的持久化方案,开启参数:“appendonly yes”。开启后每更改一个数据,变化都将写入磁盘,适用于数据太重要不能承担风险的情况。

RDB和AOF的对比

比较:

  1. aof文件比rdb更新频率高,优先使用aof还原数据。

  2. aof比rdb更安全也更大

  3. rdb性能比aof好

  4. 如果两个都配了,优先加载AOF

持久化的存储结构:

内容是redis通讯协议(RESP)格式的命令文本存储。

RESP

RESP 是redis客户端和服务端之前使用的一种通讯协议;

RESP 的特点:实现简单、快速解析、可读性好

For Simple Strings the first byte of the reply is “+” 回复

For Errors the first byte of the reply is “-” 错误

For Integers the first byte of the reply is “:” 整数

For Bulk Strings the first byte of the reply is “$” 字符串

For Arrays the first byte of the reply is “*” 数组

Redis 架构模式

单机版

问题:

  1. 内存容量有限

  2. 处理能力有限

  3. 无法高可用。

主从复制

主redis中的数据有两个副本(replication)即从redis1和从redis2,即使一台redis 服务器宕机其它两台redis服务也可以继续提供服务。是为了避免硬件损坏的机制。

特点:

  1. master/slave 角色

  2. master/slave 数据相同降低

  3. master 读压力在转交从库

问题:

  1. 无法保证高可用

  2. 没有解决 master 写的压力

哨兵

https://www.cnblogs.com/jasontec/p/9699242.html

集群(proxy 型)

https://www.cnblogs.com/jasontec/p/9699242.html

集群(直连型)

https://www.cnblogs.com/jasontec/p/9699242.html

缓存穿透、缓存雪崩与数据击穿

缓存穿透

一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就应该去后端系统查找(比如DB)。一些恶意的请求会故意查询不存在的key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。

如何避免?

1:对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据insert了之后清理缓存。

2:对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该bitmap过滤。

缓存雪崩

当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,会给后端系统带来很大压力。导致系统崩溃。

如何避免?

1:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

2:做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期

3:不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

数据击穿

数据击穿指的是一个高热度的键过期瞬间,由于大量访问,也导致sql负荷过高。可以将热门键设为永久

#遗留问题

暂时还看不太懂的问题。

使用过Redis分布式锁么,它是怎么实现的?

先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。

如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?

set指令有非常复杂的参数,这个应该是可以同时把setnx和expire合成一条指令来用的!

使用过Redis做异步队列么,你是怎么用的?有什么缺点?

一般使用list结构作为队列,rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。

缺点:

在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如rabbitmq等。

能不能生产一次消费多次呢?

使用pub/sub主题订阅者模式,可以实现1:N的消息队列。

拓展资料

https://www.cnblogs.com/php-no-2/p/9396965.html

https://www.cnblogs.com/lfs2640666960/p/9700706.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值