Redis入门


一、Redis环境准备?

Redis是一个基于内存的key-value结构数据库。Redis 是互联网技术领域使用最为广泛的存储中间件
官网: link

中文网:link

主要特点:基于内存存储,读写性能高

  • 适合存储热点数据(热点商品、资讯、新闻)
  • 企业应用广泛

Redis是用C语言开发的一个开源的高性能键值对(key-value)数据库,官方提供的数据是可以达到100000+的QPS(每秒内查询次数)。它存储的value类型比较丰富,也被称为结构化的NoSql数据库。

NoSql(Not Only SQL),不仅仅是SQL,泛指非关系型数据库。NoSql数据库并不是要取代关系型数据库,而是关系型数据库的补充。

下载与安装

下载:
Redis安装包分为windows版和Linux版:

  • Windows版下载地址:https://github.com/microsoftarchive/redis/releases
  • Linux版下载地址:
    https://download.redis.io/releases/

安装:
在Windows中安装Redis
目录结构如下:
在这里插入图片描述

服务启动与停止

以window版Redis进行演示:
服务启动命令:redis-server.exe redis.windows.conf
在这里插入图片描述
Redis服务默认端口号为 6379 ,通过快捷键Ctrl + C 即可停止Redis服务

当Redis服务启动成功后,可通过客户端进行连接。

客户端连接命令

在redis安装目录中,执行命令为:redis-cli.exe,如下图
在这里插入图片描述
通过redis-cli.exe命令默认连接的是本地的redis服务,并且使用默认6379端口。也可以通过指定如下参数连接:

  • -h ip地址
  • -p 端口号
  • -a 密码(如果需要)

Redis配置文件

在根目录中的redis.windows.conf文件为redis的核心配置文件,可根据项目情况设置不同的参数 在第443行

  • 设置Redis服务密码,添加内容为:requirepass 123456 设置密码为123456
    注意:

  • 修改密码后需要重启Redis服务才能生效

  • Redis配置文件中 # 表示注释

重启Redis后,再次连接Redis时,需加上密码,否则连接失败。

在这里插入图片描述

加上秘密后的命令如下:
redis-cli.exe -a 123456
在这里插入图片描述

如果是远程的redis服务,也可以使用以下命令指定ip和端口
redis-cli.exe -h localhost -p 6379 -a 123456

客户端图形工具

默认提供的客户端连接工具界面不太友好,同时操作也较为麻烦,接下来,引入一个Redis客户端图形工具。
在这里插入图片描述
在这里插入图片描述

成功之后,可以直接查看redis中存储的数据
在这里插入图片描述

二、Redis数据类型及命令

Redis存储的是key-value结构的数据,其中key是字符串类型,value有5种常用的数据类型:
在这里插入图片描述

字符串操作命令

Redis 中字符串类型常用命令:

SET key value设置指定key的值
GET key获取指定key的值
SETEX key seconds value设置指定key的值,并将 key 的过期时间设为 seconds 秒
SETNX key value只有在 key 不存在时设置 key 的值
  • set key(同一个key),后执行的会覆盖之前的数据
  • del key 删除key的数据,这个是通用的命令,不仅仅只是在字符串中适用
  • setnx与set在存储数据的时候,set可以覆盖之前的数据,sexnx则不行
127.0.0.1:6379> set name lisi
OK
127.0.0.1:6379> get name
"lisi"
127.0.0.1:6379> setex age 10 20   # key为20,10为过期时间(秒),20为值
OK
127.0.0.1:6379> get age
"20"
127.0.0.1:6379> setnx age 40
(integer) 0   #设置失败,age存在则保存不成功
127.0.0.1:6379> setnx city beijing
(integer) 1   #设置成功

哈希操作命令

Hash类型,也叫散列,其value是一个无序字典,类似于Java中的HashMap结构。

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

HSET key field value将哈希表 key 中的字段 field 的值设为 value
HGET key field获取存储在哈希表中指定字段的值
HDEL key field删除存储在哈希表中的指定字段
HKEYS key获取哈希表中所有字段
HVALS key获取哈希表中所有值

数据特点:
在这里插入图片描述

127.0.0.1:6379> hset heima name zhangsan
(integer) 1
127.0.0.1:6379> hget heima name
"zhangsan"
127.0.0.1:6379> hdel heima name
(integer) 1
127.0.0.1:6379> hget heima name
(nil)
127.0.0.1:6379> hset heima name zhangsan
(integer) 1
127.0.0.1:6379> hkeys heima
1) "name"
127.0.0.1:6379> hset heima age 30
(integer) 1
127.0.0.1:6379> hvals heima
1) "zhangsan"
2) "30"

列表操作命令

Redis中的List类型与Java中的LinkedList类似,可以看做是一个双向链表结构。既可以支持正向检索和也可以支持反向检索。

特征也与LinkedList类似:

  • 有序
  • 元素可以重复
  • 插入和删除快
  • 查询速度一般

常用命令:

LPUSH key value1 [value2]将一个或多个值插入到列表头部
LRANGE key start stop获取列表指定范围内的元素
RPOP key移除并获取列表最后一个元素
LLEN key获取列表长度
BRPOP key1 [key2 ] timeout移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超 时或发现可弹出元素为止
127.0.0.1:6379> lpush list a b c
(integer) 3
127.0.0.1:6379> llen list
(integer) 3
127.0.0.1:6379> lrange list 0 1
1) "c"
2) "b"
127.0.0.1:6379> lrange list 0 -1
1) "c"
2) "b"
3) "a"
127.0.0.1:6379> rpop list
"a"
127.0.0.1:6379> lrange list 0 -1
1) "c"
2) "b"
127.0.0.1:6379> lpop list
"c"
127.0.0.1:6379> lrange list 0 -1
1) "b"
127.0.0.1:6379> brpop list 10
1) "list"
2) "b"
127.0.0.1:6379> lrange list 0 -1
(empty list or set)

集合操作命令

Redis的Set结构与Java中的HashSet类似,可以看做是一个value为null的HashMap。因为也是一个hash表,因此具备与HashSet类似的特征:

  • 无序
  • 元素不可重复
  • 查找快
  • 支持交集、并集、差集等功能

常见命令:

SADD key member1 [member2]向集合添加一个或多个成员
SMEMBERS key返回集合中的所有成员
SCARD key获取集合的成员数
SINTER key1 [key2]返回给定所有集合的交集
SUNION key1 [key2]返回所有给定集合的并集
SREM key member1 [member2]移除集合中一个或多个成员
127.0.0.1:6379> sadd set a b c d a
(integer) 4
127.0.0.1:6379> smembers set
1) "c"
2) "a"
3) "d"
4) "b"
127.0.0.1:6379> scard set
(integer) 4
127.0.0.1:6379> sadd set2 a e f
(integer) 3
127.0.0.1:6379> sinter set set2
1) "a"
127.0.0.1:6379> sunion set set2
1) "b"
2) "c"
3) "f"
4) "e"
5) "a"
6) "d"
127.0.0.1:6379> srem set a
(integer) 1
127.0.0.1:6379> smembers set
1) "c"
2) "b"
3) "d"
127.0.0.1:6379>

有序集合操作命令

Redis的SortedSet是一个可排序的set集合,与Java中的TreeSet有些类似,但底层数据结构却差别很大。SortedSet中的每一个元素都带有一个score属性,可以基于score属性对元素排序,底层的实现是一个跳表(SkipList)加 hash表。

SortedSet具备下列特性:

  • 可排序
  • 元素不重复
  • 查询速度快

因为SortedSet的可排序特性,经常被用来实现排行榜这样的功能。

常用命令:

ZADD key score1 member1 [score2 member2]向有序集合添加一个或多个成员
ZRANGE key start stop [WITHSCORES]通过索引区间返回有序集合中指定区间内的成员
ZINCRBY key increment member有序集合中对指定成员的分数加上增量 increment
ZREM key member [member …]移除有序集合中的一个或多个成员
127.0.0.1:6379> zadd zset 10 heima
(integer) 1
127.0.0.1:6379> zadd zset 10 heima 20 itcast
(integer) 1
127.0.0.1:6379> zrange zset 0 20
1) "heima"
2) "itcast"
127.0.0.1:6379> zincrby zset 30 heima
"40"
127.0.0.1:6379> zincrby zset 50 heima
"90"
127.0.0.1:6379> zrange zset 0 -1 withscores
1) "itcast"
2) "20"
3) "heima"
4) "90"

通用命令

Redis的通用命令是不分数据类型的,都可以使用的命令:

KEYS pattern查找所有符合给定模式( pattern)的 key
EXISTS key检查给定 key 是否存在
TYPE key返回 key 所储存的值的类型
DEL key该命令用于在 key 存在是删除 key
127.0.0.1:6379> keys *
 1) "RECORD:355"
 2) "city"
 3) "RECORD:351"
 4) "name"
 5) "RECORD:340"
 6) "RECORD:348"
 7) "RECORD:346"
 8) "zset"
 9) "RECORD:345"
10) "RECORD:343"
11) "set2"
12) "heima"
13) "set"
14) "RECORD:350"
15) "age"
16) "zset2"
127.0.0.1:6379> exists heima
(integer) 1
127.0.0.1:6379> exists heima2
(integer) 0
127.0.0.1:6379> type heima
hash
127.0.0.1:6379> del heima
(integer) 1
127.0.0.1:6379> exeits heima
(error) ERR unknown command 'exeits'

三、Redis持久化

Redis有两种持久化方案:

  • RDB持久化
  • AOF持久化

RDB持久化(默认)

RDB全称Redis Database Backup file(Redis数据备份文件),也被叫做Redis数据快照。简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据。快照文件称为RDB文件,默认是保存在当前运行目录。

执行时机:
RDB持久化在四种情况下会执行:

  • 执行save命令
  • 执行bgsave命令 background
  • Redis停机时(shutdown命令关机)
  • 触发RDB条件时

AOF持久化

AOF全称为Append Only File(追加文件)。Redis处理的每一个写命令都会记录在AOF文件,可以看做是命令日志文件。

AOF默认是关闭的,需要修改redis.conf配置文件来开启AOF:

# 是否开启AOF功能,默认是no 581行
appendonly yes

AOF的命令记录的频率也可以通过redis.conf文件来配:

# 表示每执行一次写命令,立即记录到AOF文件 609行
appendfsync always 
# 写命令执行完先放入AOF缓冲区,然后表示每隔1秒将缓冲区数据写到AOF文件,是默认方案
appendfsync everysec
# 写命令执行完先放入AOF缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
appendfsync no

RDB和AOF各有自己的优缺点,如果对数据安全性要求较高,在实际开发中往往会结合两者来使用。

四、Java中操作Redis

Spring Data Redis

Spring Data Redis 是 Spring 的一部分,提供了在 Spring 应用中通过简单的配置就可以访问 Redis 服务,对 Redis 底层开发包进行了高度封装。在 Spring 项目中,可以使用Spring Data Redis来简化 Redis 操作。

网址:https://spring.io/projects/spring-data-redis
Spring Boot提供了对应的Starter,maven坐标:

<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>

Spring Data Redis中提供了一个高度封装的类:RedisTemplate,对相关api进行了归类封装,将同一类型操作封装为operation接口,具体分类如下:

  • ValueOperations:string数据操作
  • SetOperations:set类型数据操作
  • ZSetOperations:zset类型数据操作
  • HashOperations:hash类型的数据操作
  • ListOperations:list类型的数据操作

环境搭建

在application.yml文件,配置redis连接,如下:
spring:
redis:
host: localhost
port: 6379
password: 123456

操作常见类型数据

@SpringBootTest(classes = CacheDemoApplication.class)
@RunWith(SpringRunner.class)
public class RedisTest {

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Test
    public void test(){
        System.out.println(redisTemplate);
    }
    
}

上述代码中直接注入了RedisTemplate,并且指定了泛型为String

  • 如果不指定泛型也可以进行操作,但是存储对象的时候需要进行序列化
  • 一般项目中存储对象都会先转换为json字符串,再进行存储,所以一般会选择使用泛型为String,避免大量的序列化操作

操作字符串数据类型

/**
 * 操作字符串类型的数据
 */
@Test
public void testString(){
    // 普通的放入数据
    // redisTemplate.boundValueOps("name").set("zhangsan");
    // 设置超时时间
    // redisTemplate.boundValueOps("name1").set("lisi",10, TimeUnit.SECONDS);

    // 分布式锁的原理
    // Boolean aBoolean1 = redisTemplate.boundValueOps("name2").setIfAbsent("wangwu");
    // System.out.println(aBoolean1);
    // Boolean aBoolean2 = redisTemplate.boundValueOps("name2").setIfAbsent("wangwu");
    // System.out.println(aBoolean2);

    // 获取数据
    String name = redisTemplate.boundValueOps("name").get();
    System.out.println(name);


}

操作哈希类型数据

/**
 * 操作哈希类型的数据
 */
@Test
public void testHash(){
    // BoundHashOperations<String, String, String> boundHashOps = redisTemplate.boundHashOps("math");
    //
    // boundHashOps.put("zhangsan","100");
    // boundHashOps.put("lisi","99");
    // boundHashOps.put("wangwu","90");
    // boundHashOps.put("zhaoliu","95");
    //
    // BoundHashOperations<String, String, String> boundHashOps1 = redisTemplate.boundHashOps("chinese");
    //
    // boundHashOps1.put("zhangsan","89");
    // boundHashOps1.put("lisi","76");
    // boundHashOps1.put("wangwu","78");
    // boundHashOps1.put("zhaoliu","99");
    BoundHashOperations<String, String, String> boundHashOps = redisTemplate.boundHashOps("math");
    //删除某一对数据
    Long zhangsan1 = boundHashOps.delete("zhangsan");

    //获取大key中的所有数据
    Map<String, String> map = boundHashOps.entries();
    for (Map.Entry<String, String> entry : map.entrySet()) {
        System.out.println(entry.getKey()+"--->"+entry.getValue());
    }
    //获取指定小key的数据
    String zhangsan = boundHashOps.get("zhangsan");
    System.out.println(zhangsan);
}

操作列表类型数据

/**
 * 操作列表类型的数据
 */
@Test
public void testList(){
    // 有顺序
    BoundListOperations<String, String> listOperations = redisTemplate.boundListOps("listKey");
    // listOperations.leftPush("A");  //A
    // listOperations.leftPush("B");  //BA
    // listOperations.leftPush("C"); //CBA
    // listOperations.leftPush("D"); //DCBA
    // // 普通的取数据
    // List<String> range = listOperations.range(0, 3);
    // System.out.println(range);
    // 弹出式的获取    秒杀商品数量的记录
    // String s = listOperations.rightPop();
    // System.out.println(s);

    BoundListOperations<String, String> goodsOperations = redisTemplate.boundListOps("iphone16");
    // for (int i = 0; i < 10; i++) {
    //     goodsOperations.leftPush("iphone16Id");
    // }

    for (int i = 0; i < 10; i++) {
        goodsOperations.rightPop();
    }

    String s = goodsOperations.rightPop();
    System.out.println( s);

}

操作集合类型数据

/**
 * 操作集合类型的数据
 */
@Test
public void testSet(){
    BoundSetOperations<String, String> setOps = redisTemplate.boundSetOps("setKey");
    setOps.add("A");
    setOps.add("B");
    setOps.add("C");
    setOps.add("D");
    setOps.add("B");
    setOps.add("A");

    Set<String> members = setOps.members();
    System.out.println(members);

}

操作有序集合类型数据

/**
 * 操作有序集合类型的数据
 */
@Test
public void testZset(){
    BoundZSetOperations<String, String> zSetOps = redisTemplate.boundZSetOps("zsetKey");

    // zSetOps.add("zhangsan",100);
    // zSetOps.add("lisi",88);
    // zSetOps.add("wangwu",99);
    // zSetOps.add("zhaoliu",109);

    // Set<String> range = zSetOps.range(0, 3); //默认升序 lisi  wangwu  zhangsan zhaoliu
    // System.out.println(range);

    //  排名 rank  反向排名 reverseRank
    Long zhangsanRank = zSetOps.reverseRank("zhangsan");
    System.out.println(zhangsanRank);

    // Set<String> range1 = zSetOps.reverseRange(0, 3);   //默认升序      zhaoliu  zhangsan  wangwu lisi
    // System.out.println(range1);
}

通用命令操作

/**
 * 通用命令操作
 */
@Test
public void testCommon(){
    //keys exists type del
    Set keys = redisTemplate.keys("*");
    System.out.println(keys);

    Boolean name = redisTemplate.hasKey("name");
    Boolean set1 = redisTemplate.hasKey("set1");

    for (Object key : keys) {
        DataType type = redisTemplate.type((String) key);
        System.out.println(type.name());
    }

    redisTemplate.delete("mylist");
}
  • 17
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值