Redis 入门笔记

目录

一、五种数据类型

1. select 

2. 字符串(String)

1)添加String

2)获取String

3)批量设置

4)批量获取

2. 散列(hashes)

1)hash设置

2)hash获取(一样的)

3)hash多条设置

4)hash多条获取

5)获取key下的所有值

6)hash删除

 3. 列表(list)

1)从两边加

2)显示值

3)显示list length

4)删除(remove)

4. 集合(Set) 

1)添加

2)获取set

3)查询Set大小

 4)删除set数据

 5. 有序集合sorted set

1)添加

 2)查看条数

3)查看set成员

 4)删除

 6. 通用指令

1)通用删除

2)查询所有的keys

二、层级目录

1.层级目录设置

2.层级目录获取

 三、失效时间

1.设置值时设置失效时间

2. 给已有的值设置时间。

3. NX/XX

四、事务操作

1. 创建/执行事务

 2. 删除/放弃事务 (discard)

 3. 异常处理

五、IDEA中的Redis

1.Jedis连接Redis

2. 操作五大变量

1)String

 2)hashed

3)List

4)Set

5)Sorted Set 

六、磁盘持久化方案

1.快照(rdb)

2.aof

七、主从关系


Redis 特点:

由于访问量上升,使用SQL架构的网站在数据库上都出现了性能问题,而redis属于NoSql,它可以作为数据库,缓存和消息中间件。缓存的作用可以提高速度,例如有的数据经常的被访问但是不用频繁的被修改就可以放到缓存里,就可以直接读取而不需要再进行计算。一般来说都是固定不变的数据。缓存不适合持久储存海量数据。

Redis支持多种数据结构(只有这五种),如字符串String, 散列(hashes), 列表(list),集合(set),  有序集合(sorted set)。

一、五种数据类型

1. select 

选择储存的数据库

select 1

选择第几个数据库,这里是第二个

2. 字符串(String)

1)添加String

set [key] [value]

ex: 

set name longwang

2)获取String

get  [key] [value]

3)批量设置

m (multi)

mset [key] [value]  [key] [value]...

ex:

mset age 20 addr shanghai

4)批量获取

mget  [key]...

ex:

mget age addr

2. 散列(hashes)

因为哈希也是key value所以格式是

1)hash设置

hset [key] [field(也就是哈西的value)] [value]

ex:

hset user name chuangw

2)hash获取(一样的)

hget user name

3)hash多条设置

hmset [key] [field] [value] [field] [value]

ex:

hmset user age 20 addr shanghai

4)hash多条获取

hmget user age addr

5)获取key下的所有值

hgetall [key]

ex:

hgetall user

6)hash删除

  hdel key field field...  

 ex:

hdel user age addr

 

 3. 列表(list)

1)从两边加

lpush/rpush key value value

ex:

lpush students longwang chuanwang haoge

rpush students bingsong haoyong

2)显示值

lrange key start stop

stop 写-1话就是显示全部, 如果大于上限也是显示全部.(-2会显示少一个,以此类推)

ex:

lrange student 0 4

 添加步骤逻辑:

左添加最后一个永远在最左边,右添加永远在最右边

a.

 b.

 c.

d-e.

 

3)显示list length

llen key

4)删除(remove)

lrem key count value 

count:删除几个这个值,因为可以有重复值。删除顺序是从左到右。如果超过数量则全删,不会报错

lrem students 1 haoyong

4. 集合(Set) 

特点:无序(其实有内部排序),不可重复(重复的会被删掉不会报错)

1)添加

sadd key member member

ex:

sadd letters aaa bbb ccc ddd aaa

 发现只加了4条,因为aaa重复了而set不能重复

2)获取set

smembers key

发现顺序是乱的(其实是内部排序了)

3)查询Set大小

scard key 

 4)删除set数据

srem key member member

 5. 有序集合sorted set

1)添加

zadd key score member [score memeber]

score: 按照分数给member 排序, 分数从小到大排序

 2)查看条数

zcard key

3)查看set成员

zrange key start stop

 4)删除

zrem key member member

 6. 通用指令

1)通用删除

del key key

之前的String 是没有删除的可以“del”来删除。del可以删除不同类型的数据

 这是是删了String 的name 和 sorted set

2)查询所有的keys

keys pattern

 * 星号就是所有

二、层级目录

可以更方便的查看不同用户购物车里的物品

1.层级目录设置

 可以在RMD中看到

2.层级目录获取

 三、失效时间

例子:手机验证码10分钟有效时间,超出时间需要重新申请。

设置失效时间有三种方式。1.在设置值的时候直接设置时间。2,给已有的值设置时间。

1.设置值时设置失效时间

在key value后+ ex设置秒/px设置毫秒

a. 查看剩余时间

ttl key        //秒

pttl key         //毫秒

 还剩14秒 
----------------------------------------------------------------------------------------------------------------

-2 代表已经完全失效

DRM里也可以查看TTL, 时间到了就会消失 

----------------------------------------------------------------------------------------------------------------

 设置一个不带时间的,显示-1。代表永远有效。

2. 给已有的值设置时间。

expire key seconds       //秒

pexpire key ms      //毫秒

3. NX/XX

NX:表示这个key不存在,才能设置成功

XX:表示这个key存在,才能设置成功

 这个可以用来做锁,来占位置。

 scenario analysis:

去取钱,第一个先取,然后锁住花(22秒)取完了才能到下一个人。

 但是这么写不完善,(例如万一花了30秒才完成的话,就会把后一个人的锁取消掉)具体需要学习 "redlock" 和 "lua脚本"。

监控(watch):

悲观锁:认为什么都会出问题,无论什么都会加上锁。(效率很低)

乐观锁:认为什么都不会出问题,所以不会上锁。只有更新数据的时候回去判断一下,在此期间数据是否被修改了。

1.获取version

2.更新的时候比较version

例:模拟多线程,开两个客户端

客户端1:

 这里监视money,但是注意这里不执行。

客户端2:
       

直接进行修改Money.

回到客户端1,执行:

 返回nil说明执行失败。

只要执行了修改,不管值是否一样,都会触发Watch.

四、事务操作

事务就是一组命令的集合,一个事务中所有命令都会被集合化,执行中所有命令都会按顺序执行。会一次性,顺序性,排他性地执行这些命令。

Redis事务没有隔离级别地概念,命令在事务中不会被执行。只有在命令发起是在会被执行。

1. 创建/执行事务

步骤:

1.开启事务

multi

2.命令入列

3.执行事务。

exec

ex:

 2. 删除/放弃事务 (discard)

放弃事务之后,所有命令都不会被执行。

 3. 异常处理

编译异常: 命令错误,代码语法不对。那么事务中所有命令都不会被执行。

注:getset key  value。这里没有value。就算剩下的命令没有问题也不会执行。

运行时异常: 计算时的异常(例如:1除0),那么这条会抛异常,剩下的命令正常执行。

Incr 命令将 key 中储存的数字值增一。

如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。

如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。

五、IDEA中的Redis

1.Jedis连接Redis

先创建新的project

勾选这两个。

由于2.0版本后redis默认配置lettuce客户端,所以先要移除依赖

在这里修改 

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <exclusions>
        <exclusion>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>

操作:

        Jedis jedis = new Jedis("127.0.0.1",6379);
        System.out.println(jedis.ping());
        jedis.set("name","yao");
        
        String name = jedis.get("name");
        System.out.println("here is "+name);
        if (null != jedis){
            jedis.close();

        }

输出:

2. 操作五大变量

1)String

        Jedis jedis = new Jedis("127.0.0.1",6379);
        System.out.println(jedis.ping());
        //设值,单条
        jedis.set("name","yaoshuige");
        //取值,单条
        String name = jedis.get("name");
        System.out.println("here is "+name);
        //设值,多条
        jedis.mset("age","30","addr","shamghai1");
        //取值,多条
        List<String> list = jedis.mget("age", "addr");
        list.forEach(System.out::println);
         //删除
        jedis.del("addr");
        // String addr = jedis.get("addr");
        list = jedis.mget("age", "addr");
        System.out.println("删除后");
        list.forEach(System.out::println);



        if (null != jedis){
            jedis.close();

        }

输出:

 2)hashed

        //设值,单条
        jedis.hset("rapper","name","agiao");
        取值,单条
        String name = jedis.hget("rapper", "name");
        System.out.println(name);
        //设值,多条
        Map<String,String> map = new HashMap<>();
        map.put("say","Hi!");
        map.put("words","Hello!");
        jedis.hmset("rapper",map);
        List<String> list = jedis.hmget("rapper", "words","say");
        //取值,多条
        list.forEach(System.out::println);
        //删除
        jedis.hdel("rapper","words");
        System.out.println("删除后:");
        list.forEach(System.out::println);

输出:

3)List

        //list
        //push
        jedis.lpush("students","s1","s2","s3");
        jedis.rpush("students","s4","s5");
        //取值
        List<String> students = jedis.lrange("students", 0, -1);
        students.forEach(System.out::println);
        //获取长度
        Long size = jedis.llen("students");
        System.out.println("the size is: "+size);
        //删除
        jedis.lrem("students",1,"s2");
        students = jedis.lrange("students", 0, -1);
        students.forEach(System.out::println);

4)Set

    //set
    //赋值
    jedis.sadd("letters","a","b","c");
    //取值
     Set<String> letters = jedis.smembers("letters");
     letters.forEach(System.out::println);
    //查看大小
     Long size = jedis.scard("letters");
     System.out.println("size is "+ size);
    //删除
        jedis.srem("letters","a");
        letters = jedis.smembers("letters");
        letters.forEach(System.out::println);

输出:

5)Sorted Set 

        //sorted set
        //添加数据
        Map<String, Double> map = new HashMap<>();
        map.put("张三",5D);
        map.put("张二",7D);
        map.put("张一",4D);
        jedis.zadd("score",map);
        //获取数据
        Set<String> set = jedis.zrange("score", 0, -1);
        set.forEach(System.out::println);
        //获取长度
        Long size = jedis.zcard("score");
        System.out.println(size);
        //删除
        jedis.zrem("score","张三");
        set = jedis.zrange("score", 0, -1);
        set.forEach(System.out::println);

输出:

3.通用命令

1)层级目录

        //层级目录
        jedis.set("use:01:item","iphone");
        String iphone = jedis.get("use:01:item");
        System.out.println(iphone);
        //查询所有Key
        Set<String> set = jedis.keys("*");
        set.forEach(System.out::println);
        //获取数据库大小
        System.out.println(jedis.dbSize());

输出:

2)设置锁(NX/XX)

        //失效时间
        //设值失效时间
        jedis.setex("code",10,"test");
        //给已存在的key设置失效时间
        jedis.expire("score",20);
        //查询失效时间
        Long ttl = jedis.ttl("code");
        System.out.println(ttl);
        //NX:不存在时设置成功
        //XX:存在时设置成功
        SetParams params = new SetParams().xx().ex(30);
        jedis.set("code","test",params);

3)操作事务

一般很少用的,因为redis的事务能力非常弱。会用到redis的watch事件,类似于乐观锁

        //操作事务
        //开启事务
        Transaction tx = jedis.multi();
        tx.set("code","test");
        //执行事务
        tx.exec();
        //回滚事务
        tx.discard();

六、磁盘持久化方案

redis是在内存中操作数据,所以有数据丢失的风险,例如在redis宕机时。

为了应对这个问题,redis有两种解决方案:快照(rdb)和aof。

1.快照(rdb)

1)使用“bgsave”命令

有点:方便快捷,一行命令就可以做到。

缺点:因为不确定什么时候会宕机,所以为了以防万一每一行都要打,很麻烦。 

2)设置自动储存

打开redis.comf配置文件,可以看到

 当达到条件时,就会启动后台自动保存,存到dump.rdb里。

这里有3条分别是:

900秒内,如果有1个key发生变化时储存

300秒内,如果有10个key发生变化时储存

60秒内,如果有10,000个key发生变化时储存

这个条件可以自行编辑。

 快照原理:保存到了本地的rdb文件中了

打开redis.comf配置文件,可以看到快照的储存名和保存路径

打开rdb文件

发现里面保存的是key value。当redis出故障重启时,会将key value从rdb中读取,重新写入redis。

优点:不需要一直bgsave

缺点:如果达不到要求的数据还是会丢失,仍然有数据丢失的风险。

2.aof

开启方法,找到appendonly,把no改成yes

默认情况下,如果启动了appendonly,则rdb默认失效 

 appendonly是实时记录,所有数据都会被保留。

打开appendonly.aof

可以看到里面保存的是命令而不是key value。输入的每条命令都会被保存进来,当redis重启时,所有的命令会被重新输入进redis。

优点:实时保存。

缺点:数据量更大,rdb直接存key value,aof存完整的命令。所以aof文件占用大小会比rdb更大。当文件大到一定程度时,重启时的速度也会变慢。        

但是redis 4.0之后,rdb和aof可以混合开启。可以拥有两方面的优点,但是执行效率也会降低。

七、主从关系

概念:

当redis只有一个时(单节点),读取的压力会很大(因为redis一般作为缓存,里面数据不更改所以不考虑写入的压力)。当有多个时,能分流很多主节点的读取压力,提高可用性。

   在集群环境下,大于一半不可用、 整个集群不可用。

哨兵(sentinel)

当主节点下线(down)后,哨兵会开始选取新的从节点变成主节点,而且同级的从节点会被划分进新的主节点下。当主节点回复时,也会变成新的主节点的从节点。

哨兵判断主节点下线的方式为ping,当哨兵超过30秒没收到主节点返回的pong时,将会被判断为掉线。当超过一般的哨兵判断主节点掉线时,便会看是选取新的主节点。(为什么要多个哨兵?因为有可能是网络波动造成的)

当选举过程超时时,会重新开始选举,不会一直卡主。

默认超时时间为3分钟。 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值