目录

一、五种数据类型

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

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

redis 客户端指令提示_redis

2. 字符串(String)

1)添加String

set [key] [value]

ex: 

set name longwang

2)获取String

get  [key] [value]

redis 客户端指令提示_redis 客户端指令提示_02

3)批量设置

m (multi)

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

ex:

mset age 20 addr shanghai

4)批量获取

mget  [key]...

ex:

mget age addr

redis 客户端指令提示_redis 客户端指令提示_03

2. 散列(hashes)

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

redis 客户端指令提示_redis 客户端指令提示_04

1)hash设置

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

ex:

hset user name chuangw

2)hash获取(一样的)

hget user name

redis 客户端指令提示_System_05

3)hash多条设置

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

ex:

hmset user age 20 addr shanghai

4)hash多条获取

hmget user age addr

redis 客户端指令提示_System_06

5)获取key下的所有值

hgetall [key]

ex:

hgetall user

redis 客户端指令提示_数据_07

6)hash删除

field...  

 ex:

hdel user age addr

 

redis 客户端指令提示_System_08

 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

redis 客户端指令提示_redis 客户端指令提示_09

 添加步骤逻辑:

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

a.

redis 客户端指令提示_redis 客户端指令提示_10

 b.

redis 客户端指令提示_数据_11

 c.

redis 客户端指令提示_redis_12

d-e.

 

redis 客户端指令提示_数据_13

3)显示list length

llen key

4)删除(remove)

lrem key count value 

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

lrem students 1 haoyong

redis 客户端指令提示_数据_14

4. 集合(Set) 

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

1)添加

sadd key member member

ex:

sadd letters aaa bbb ccc ddd aaa

redis 客户端指令提示_redis_15

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

2)获取set

smembers key

redis 客户端指令提示_数据_16

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

3)查询Set大小

scard key 

redis 客户端指令提示_数据_17

 4)删除set数据

srem key member member

redis 客户端指令提示_System_18

 5. 有序集合sorted set

1)添加

zadd key score member [score memeber]

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

redis 客户端指令提示_redis 客户端指令提示_19

 2)查看条数

zcard key

redis 客户端指令提示_redis_20

3)查看set成员

zrange key start stop

redis 客户端指令提示_System_21

 4)删除

zrem key member member

redis 客户端指令提示_System_22

 6. 通用指令

1)通用删除

del key key

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

redis 客户端指令提示_System_23

 这是是删了String 的name 和 sorted set

2)查询所有的keys

keys pattern

redis 客户端指令提示_数据_24

 * 星号就是所有

二、层级目录

redis 客户端指令提示_redis_25

redis 客户端指令提示_redis 客户端指令提示_26

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

1.层级目录设置

redis 客户端指令提示_System_27

 可以在RMD中看到

redis 客户端指令提示_System_28

2.层级目录获取

redis 客户端指令提示_数据_29

 三、失效时间

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

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

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

redis 客户端指令提示_redis_30

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

redis 客户端指令提示_redis 客户端指令提示_31

a. 查看剩余时间

ttl key        //秒

pttl key         //毫秒

redis 客户端指令提示_System_32

 还剩14秒 

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

redis 客户端指令提示_redis 客户端指令提示_33

-2 代表已经完全失效

redis 客户端指令提示_System_34

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

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

redis 客户端指令提示_redis 客户端指令提示_35

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

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

expire key seconds       //秒

pexpire key ms      //毫秒

redis 客户端指令提示_redis_36

3. NX/XX

redis 客户端指令提示_redis_37

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

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

redis 客户端指令提示_redis_38

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

 scenario analysis:

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

redis 客户端指令提示_数据_39

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

监控(watch):

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

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

1.获取version

2.更新的时候比较version

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

客户端1:

redis 客户端指令提示_redis 客户端指令提示_40

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

客户端2:

       

redis 客户端指令提示_redis_41

直接进行修改Money.

回到客户端1,执行:

redis 客户端指令提示_redis_42

 返回nil说明执行失败。

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

四、事务操作

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

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

1. 创建/执行事务

步骤:

1.开启事务

multi

2.命令入列

3.执行事务。

exec

ex:

redis 客户端指令提示_redis 客户端指令提示_43

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

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

redis 客户端指令提示_redis 客户端指令提示_44

 3. 异常处理

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

redis 客户端指令提示_数据_45

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

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

redis 客户端指令提示_redis 客户端指令提示_46

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

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

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

五、IDEA中的Redis

1.Jedis连接Redis

先创建新的project

redis 客户端指令提示_System_47

勾选这两个。

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

redis 客户端指令提示_redis_48

在这里修改 

<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();

        }

输出:

redis 客户端指令提示_System_49

redis 客户端指令提示_数据_50

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();

        }

输出:

redis 客户端指令提示_redis 客户端指令提示_51

 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);

输出:

redis 客户端指令提示_redis 客户端指令提示_52

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);

输出:

redis 客户端指令提示_System_53

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);

输出:

redis 客户端指令提示_数据_54

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());

输出:

redis 客户端指令提示_redis_55

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 客户端指令提示_数据_56

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

1.快照(rdb)

1)使用“bgsave”命令

redis 客户端指令提示_redis_57

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

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

2)设置自动储存

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

redis 客户端指令提示_redis 客户端指令提示_58

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

这里有3条分别是:

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

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

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

这个条件可以自行编辑。

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

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

redis 客户端指令提示_System_59

打开rdb文件

redis 客户端指令提示_System_60

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

优点:不需要一直bgsave

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

2.aof

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

redis 客户端指令提示_System_61

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

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

打开appendonly.aof

redis 客户端指令提示_redis_62

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

优点:实时保存。

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

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

七、主从关系

概念:

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

redis 客户端指令提示_System_63

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

哨兵(sentinel)

redis 客户端指令提示_redis 客户端指令提示_64

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

redis 客户端指令提示_redis 客户端指令提示_65

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

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

redis 客户端指令提示_System_66

默认超时时间为3分钟。