Redis基础知识

Posted 喜六六

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis基础知识相关的知识,希望对你有一定的参考价值。

1 初识Redis

Redis(Remote Dictionary Server,远程词典服务器)是一个基于内存的健值型数据库,特征如下:

1、健值型,value支持多种不同数据类型

2、单线程,每个命令具备原子性

3、低延迟、速度快(基于内存、IO多路复用、良好的编码),基于C语言实现

4、支持数据持久化

5、支持主从集群、分片集群

6、支持多语言客户端

redis-server 启动Redis

ps -ef | grep redis 查看Redis进程

redis-cli -h 127.0.0.1 -p 6379 连接redis服务

Redis中数据类型,Key一般是String类型,Value包含以下类型:

GEO:地理坐标

2 Redis命令

2.1 Redis通用命令

KEYS:查看所有符合指定模版的key。搜索效率低,生产环境不要用该命令。

查询所有的key keys *

查询所有以a开头的key keys a*

DEL:删除指定的key,可以一个或者多个key。返回值是删除了多少个key。

Exists:判断key是否存在

expire:设置key的有效期,单位是秒,有效期过后自动删除。不设置有效时间的话,默认永久有效(返回-1)

ttl:查看一个key的剩余有效期

2.2 string类型常用命令

set:添加或者修改已经存在的一个string类型的键值对

get:根据key获取string类型的value

mset:批量添加多个string类型的键值对

mget:批量获取多个key的value

Incr:让一个整型key自增1

Incrby:让一个整型的key自增并指定步长,例如incrby num 2 让num值自增2

Incrbyfloat:让一个浮点型数字自增并指定步长

setnx:添加一个string类型的键值对,前提是这个key不存在,否则不执行

setex:添加一个string类型的键值对,并指定有效期。

setex name2 10 jack等同于set name2 jack ex 10

实际项目中key要用多个单词形成层级结构,多个单词之间用:隔开,格式如下:

项目名:业务名:类型:id。如果Value是一个对象,可以将对象序列化为JSON字符串后存储

2.3 hash类型常用命令

hset key field value:添加或者修改hash类型key的field的值

hget key field:获取一个hash类型key的field的值

hmset:批量添加多个hash类型key的field的值

hmget:批量获取多个hash类型key的field的值

HgetAll:获取一个hash类型的key中的所有的field和value

Hkeys:获取一个hash类型的key中的所有的field

hvals:获取一个hash类型的key中所有的value

Hincrby:让一个hash类型key的字段值自增并指定步长

hsetnx:添加一个hash类型的key的filed值,前提是这个field不存在,否则不执行。

2.4 list类型常用命令

Redis中的List类型可以看做是一个双向链表结构,既可以支持正向检索也可以支持反向检索。List中的元素有序排列、元素可以重复,插入和删除速度快、查询速度一般。

2.5 set类型常用命令

Redis中的Set结构可以看做是一个value为null的HashMap,底层也是Hash表结构,特点如下:

1、元素无序

2、元素不可重复

3、查找速度快

4、支持交集、并集、差集等功能

单个set操作:

多个set间互相操作:

2.6 SortedSet类型常用命令

Redis中的SortedSet是一个可排序的set集合,SortedSet中每一个元素都带有

一个score属性,可以基于score属性对元素排序,底层实现是一个跳表(SkipList)加Hash表,常用来实现排行榜功能。特征如下:

1、可排序,每个元素都带score属性,根据score属性排序

2、元素不可重复

3、查询速度快

3 Redis的Java客户端

3.1 Jedis

官网地址:https://github.com/redis/jedis

引入依赖:

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>4.3.0</version>
</dependency>

基本用法:

//Jedis中的方法名和Redis命令行命令名相同   
 Jedis jedis = new Jedis("127.0.0.1",6379);//建立连接
    @Test
    public void testJedis() 
        jedis.select(0);//选择数据库
        System.out.println( jedis.get("age"));//取数据
        jedis.setnx("school","bupt");//存数据
        if (jedis!=null) 
            jedis.close();//释放资源
        
    

3.1.1 Jedis连接池

public class JedisConnectionFactory 
    private static final JedisPool jedisPool;

    static 
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        //最大连接数
        jedisPoolConfig.setMaxTotal(10);
        //最大空闲连接,超过一段时间后空闲连接会被撤销
        jedisPoolConfig.setMaxIdle(10);
        //最小空闲连接
        jedisPoolConfig.setMinIdle(2);
        //设置最长等待时间,毫秒
        jedisPoolConfig.setMaxWaitMillis(200);
        jedisPool = new JedisPool(jedisPoolConfig, "127.0.0.1", 6379, 1000);
    

    /**
     * 获取jedis对象
     * @return
     */
    public static Jedis getJedis() 
        return jedisPool.getResource();
    

3.2 SpringDataRedis

SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块叫做SpringDataRedis,官网地址:https://spring.io/projects/spring-data-redis

引入依赖:

        <!-- Redis依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- 连接池依赖 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

yaml配置文件:

spring:
  data:
    redis:
      host: 127.0.0.1
      jedis:
        pool:
          max-active: 8
          max-idle: 8
          min-idle: 0
          max-wait: 100

注入RedisTemplate:

@SpringBootTest
public class RedisTest 
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void testString() 
        redisTemplate.opsForValue().set("salary",500000);//存储数据
        System.out.println( redisTemplate.opsForValue().get("salary"));//查询数据

    

3.2.1 RedisTemplate

SpringDataRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作。并且将不同数据类型的操作API封装到了不同类型中:

4 Redis实战案例

4.1 短信登录

4.2 商户查询缓存

4.3 博客

4.4 优惠券秒杀

4.5 好友关注

4.6 附近的商户

4.7 用户签到

4.8 UV统计

Redis:Redis基础知识 01

Redis基础知识 01

一、NoSQL与RDBMS

1.RDBMS

  • RDBMS:关系型数据库管理系统
  • 工具:MYSQL、Oracle、SQL Server…
  • 应用:业务型数据存储系统:事务和稳定性
  • 特点:体现数据之间的关系,保证业务完整性和稳定性,小数据量的性能也比较好
  • 需求:能实现高并发的数据库,接受高并发需求

2.NoSQL

  • NoSQL:非关系型数据库
  • 工具:Redis、HBASE、MongoDB…
  • 应用:一般用于高并发性能场景下的数据缓存或者数据库存储
  • 特点:读写速度特别快、相对而言不如RDBMS稳定,对事物的支持不太友好
  • 开发:每中NoSQL都有自己的命令语法
  • 解决:RDBMS的问题:实现读写分离
    • 读需求:读请求不读MySQL、读取Redis
    • 写需求:直接写入MySQL

二、Redis的功能与应用场景

  • 定义:基于内存的分布式的NoSQL数据库
  • 功能:提高高性能并发的数据存储
  • 特点
    • 基于C语言开发的系统,与硬件交互性能更好
    • 基于内存实现数据读写,读写性能更快
    • 分布式的、扩展性和稳定性更好
    • 支持事务、拥有各种各样丰富的数据结构
  • 应用场景
    • 缓存:用于实现高并发的数据缓存
    • 数据库:用于实现高性能的数据读写
    • 场景
      • 数据库:永久性存储
      • 缓存:临时存储
      • 消息中间件:消息队列MQ

三、Redis的安装、部署

  • Redis版本
    • 3.x:支持分片集群功能
    • 5.x:分片集群的功能更加稳定

1.Windows上的部署

GitHub:下载地址
版本:Redis-x64-3.2.100.zip
在这里插入图片描述解压完毕就可以使用

  • 测试
    • 打开客户端和服务端

有的系统存在兼容性问题,服务端不能直接打开,需要编写一个脚本文件打开服务端,脚本文件内容如下

redis-server.exe redis.windows.conf

在这里插入图片描述

  • 服务端
    在这里插入图片描述
  • 客户端
    在这里插入图片描述- 测试命令

在这里插入图片描述

2.Redis的桌面管理工具的部署

百度网盘:下载地址
提取码:zfin

  • 解压安装即可
  • 启动连接
    在这里插入图片描述在这里插入图片描述

3.Linux上的部署

百度网盘:下载地址
提取码:tfp9
版本:redis-3.2.8.tar.gz

  • 将下载的redis安装包上传安装包到Linux上
#1.切换到指定目录
cd /export/software/
#2.上传
rz

在这里插入图片描述

解压

tar -zxvf redis-3.2.8.tar.gz -C /export/server/

安装依赖

yum -y install gcc-c++ tcl

编译安装

#1.进入源码目录
cd /export/server/redis-3.2.8/
#2.编译
make
#3.安装,并指定安装目录
make PREFIX=/export/server/redis-3.2.8-bin install

修改配置

1.复制配置文件

cp /export/server/redis-3.2.8/redis.conf /export/server/redis-3.2.8-bin/

2.创建目录

#1.创建redis日志目录
mkdir -p /export/server/redis-3.2.8-bin/logs
#2.创建redis数据目录
mkdir -p /export/server/redis-3.2.8-bin/datas

3.修改配置

#1.切换到redis-3.2.8-bin目录
cd  /export/server/redis-3.2.8-bin/
#2.编辑配置文件
vim redis.conf
  • 修改内容如下:
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

4.创建软连接

#1.切换到server目录
cd /export/server
#2.创建软连接
ln -s redis-3.2.8-bin redis

在这里插入图片描述
5.配置环境变量

#1.编辑profile文件
vim /etc/profile
#2.添加以下内容
# REDIS HOME
export REDIS_HOME=/export/server/redis
export PATH=:$PATH:$REDIS_HOME/bin
#3.刷新环境变量
source /etc/profile

在这里插入图片描述

启动

1.启动服务端

命令

/export/server/redis/bin/redis-server /export/server/redis/redis.conf

查看是否启动

ps -ef | grep redis

在这里插入图片描述2.编辑服务端启动脚本

vim /export/server/redis/bin/redis-start.sh

添加脚本内容如下:

#!/bin/bash 

REDIS_HOME=/export/server/redis
${REDIS_HOME}/bin/redis-server ${REDIS_HOME}/redis.conf

在这里插入图片描述
修改权限

chmod u+x /export/server/redis/bin/redis-start.sh 

3.启动客户端

/export/server/redis/bin/redis-cli -h node1 -p 6379

4.关闭客户端和服务端

关闭客户端

exit

关闭服务端

  • 客户端中
shutdown
  • Linux命令行下
kill -9 pid
  • 通过客户端命令
bin/redis-cli -h node1 -p 6379  shutdown

测试
在这里插入图片描述

四、Redis数据结构和类型

Redis数据结构

  • 整个Reids中所有数据以KV结构形式存在
  • K:作为唯一标识符,唯一标识一条数据,固定为String类型
  • V:真正存储的数据,可以有多种类型
    • String、Hash、List、Set、Zset、BitMap、HypeLogLog

Redis:类似于Java中的一个Map集合

Map<String,T> = Redis存储
  • 写:指定K和V
  • 读:指定K

Redis数据类型

Key:StringValue类型Value值应用场景
s1String10000一般用于存储单个数据指标的结果
hs1Hashname:zhangsan age : 18 sex : male用于存储整个对象所有属性值
ls1List{100,200,300}有序允许重复的集合,每天获取最后一个值
ss1Set{userid1,userid2,userid3…}无序且不重复的集合,直接通过长度得到UV
zs1ZSet{1-衣服,2-文具,3-电脑…}有序不可重复的集合,统计TopN
bs1BitMap{0101010101010000000011010}将一个字符串构建位,通过0和1来标记每一位
ps1HypeLogLog{id1,id2,id3…}类似于Set集合,底层实现原理不一样,数据量大的情况下,性能会更好
  • String类型
    • KV:【String,String】,类似于Java中Map集合的一条KV
  • Hash类型
    • KV:【String,Map集合】:Map集合的嵌套,Map集合中的元素是无序的
  • List类型
    • KV:【String,List】:有序且可重复
  • Set类型
    • KV:【String,Set】:无序且不重复
  • Zset类型
    • KV:【String,TreeMap集合】:Value也类似于Map集合,有序的Map集合
    • 类似于List和Set集合特点的合并:有序且不可重复

五、Redis命令

1.通用命令

  • keys:列举当前数据库中所有Key
#1.列举所有key
keys *
#2.列举s开头的所有key
keys s*
#3.列举1结尾的所有key
keys *1

在这里插入图片描述

  • del key:删除某个KV
#删除key值为s1的kv
del s1

在这里插入图片描述

  • exists key :判断某个Key是否存在 ,存在为1,不存在为0
#判断k值为s2的是否存在
exists s2

在这里插入图片描述

  • type key:判断这个K对应的V的类型的
#判断s2的v的类型
type s2

在这里插入图片描述- expire K 过期时间:设置某个K的过期时间,一旦到达过期时间,这个K会被自动删除

#为k值为s2的设置过期时间20秒
expire s2 20
  • ttl K:查看某个K剩余的存活时间
#查看k值为s2的剩余存活时间
ttl s2

在这里插入图片描述

  • select N:切换数据库
    • 默认Redis有16个数据库,DB0 ~ DB15
    • 默认自动进入0数据库
#切换到数据库2
select 2

在这里插入图片描述

  • move key N:将某个Key移动到某个数据库中
#将s2移动到数据库2
move s2 2

在这里插入图片描述

  • flushdb:清空当前数据库的所有Key
#清楚当前数据库所有k
flushdb

在这里插入图片描述

  • flushall:清空所有数据库的所有Key
#清空所有数据库的所有k
flushall

在这里插入图片描述

2.String类型的常用命令

  • set:给String类型的Value的进行赋值或者更新

    • 语法:set K V
  • get:读取String类型的Value的值

    • 语法:get K
  • mset:用于批量写多个String类型的KV

    • 语法:mset K1 V1 K2 V2 ……
  • mget:用于批量读取String类型的Value

    • 语法:mget K1 K2 K3 ……
  • setnx:只能用于新增数据,当K不存在时可以进行新增

    • 语法:setnx K V
    • 应用:构建抢占锁,搭配expire来使用
  • incr:用于对数值类型的字符串进行递增,递增1

    • 语法:incr K
  • incrby:指定对数值类型的字符串增长固定的步长

    • 语法:incrby K N
  • decr:对数值类型的数据进行递减,递减1

    • 语法:decr K
  • decrby:按照指定步长进行递减

    • 语法:decrby K N
  • incrbyfloat:基于浮点数递增

    • 语法:incrbyfloat K N
  • strlen:统计字符串的长度

    • 语法:strlen K
  • getrange:用于截取字符串

    • 语法:getrange s2 start end

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

3.Hash类型的常用命令

  • hset:用于为某个K添加一个属性

    • 语法:hset K k v
  • hget:用于获取某个K的某个属性的值

    • 语法:hget K k
  • hmset:批量的为某个K赋予新的属性

    • 语法:hmset K k1 v1 k2 v2 ……
  • hmget:批量的获取某个K的多个属性的值

    • 语法:hmget K k1 k2 k3……
  • hgetall:获取所有属性的值

    • 语法:hgetall K
  • hdel:删除某个属性

    • 语法:hdel K k1 k2 ……
  • hlen:统计K对应的Value总的属性的个数

    • 语法:hlen K
  • hexist*:判断这个K的V中是否包含这个属性

    • 语法:hexists K k
  • hvals:获取所有属性的value的

    • 语法:hvals K

在这里插入图片描述

4.List类型的常用命令

  • lpush:将每个元素放到集合的左边,左序放入

    • 语法:lpush K e1 e2 e3…
  • rpush:将每个元素放到集合的右边,右序放入

    • 语法:rpush K e1 e2 e3…
  • lrange:通过下标的范围来获取元素的数据

    • 语法:lrange K start end
    • 注意:从左往右的下标从0开始,从右往左的下标从-1开始,一定是从小的到大的下标
    • lrange K 0 -1:所有元素
  • llen:统计集合的长度

    • 语法:llen K
  • lpop:删除左边的一个元素

    • 语法:lpop K
  • rpop:删除右边的一个元素

    • 语法:rpop K

在这里插入图片描述

5.Set类型的常用命令

  • sadd:用于添加元素到Set集合中

    • 语法:sadd K e1 e2 e3 e4 e5…
  • smembers:用于查看Set集合的所有成员

    • 语法:smembers K
  • sismember:判断是否包含这个成员

    • 语法:sismember K e1
  • srem:删除其中某个元素

    • 语法:srem K e
  • scard:统计集合长度

    • 语法:scard K
  • sunion:取两个集合的并集

    • 语法:sunion K1 K2
  • sinter:取两个集合的交集

    • 语法:sinter K1 K2

在这里插入图片描述

6.Zset类型的常用命令

  • zadd:用于添加元素到Zset集合中

    • 语法:zadd K score1 k1 score2 k2 …
  • zrange:范围查询

    • 语法:zrange K start end [withscores]
  • zrevrange:倒序查询

    • 语法:zrevrange K start end [withscores]
  • zrem:移除一个元素

    • 语法:zrem K k1
  • zcard:统计集合长度

    • 语法:zcard K
  • zscore:获取评分

    • 语法:zscore K k

在这里插入图片描述

7.BitMap类型的常用命令

功能:通过一个String对象的存储空间,来构建位图,用每一位0和1来表示状态

在这里插入图片描述

  • Redis中一个String最大支持512M = 2^32次方,1字节 = 8位

  • 使用时,可以指定每一位对应的值,要么为0,要么为1,默认全部为0

  • 用下标来标记每一位,第一个位的下标为0

在这里插入图片描述

setbit:修改某一位的值

  • 语法:setbit bit1 位置 0/1

getbit:查看某一位的值

  • 语法:getbit K 位置

bitcount:用于统计位图中所有1的个数

  • 语法:bitcount K [start end]
  • 注:start end代表的是字节,0代表前8位,1代表9到16位

bitop:用于位图的运算:and/or/not/xor
- 语法:bitop and/or/xor/not bitrs bit1 bit2
- 注:除了 not 操作之外,其他操作都可以接受一个或多个 key 作为输入

在这里插入图片描述

8.HyperLogLog类型的常用命令

功能:类似于Set集合,用于实现数据数据的去重

  • 区别:底层实现原理不一样
  • 应用:适合于数据量比较庞大的情况下的使用,存在一定的误差率

pfadd:用于添加元素

  • 语法:pfadd K e1 e2 e3…

pfcount:用于统计个数

  • 语法:pfcount K

pfmerge:用于实现集合合并

  • 语法:pfmerge pfrs pf1 pf2…

在这里插入图片描述

六、Jedis

1.Jedis依赖

<properties>
        <jedis.version>3.2.0</jedis.version>
    </properties>

    <dependencies>
        <!-- Jedis 依赖 -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>${jedis.version}</version>
        </dependency>
        <!-- JUnit 4 依赖 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

2.构建连接

import org.junit.After;
import org.junit.Before;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class RedisClientTest {
    //构建连接
    Jedis jedis = null;

    @Before
    public void getConnection(){
        //方式一:直接构建一个连接对象
        //实例化一个客户端连接对象,指定服务端地址
//        jedis = new Jedis("node1",6379);
        //方式二:通过连接池来构建连接
        //构建连接池,并且配置连接池属性
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(20);//最大连接数
        jedisPoolConfig.setMaxIdle(10);//最大空闲连接
        jedisPoolConfig.setMaxWaitMillis(1500);//最大等待时间
        //构建连接池:连接池配置对象,主机名,端口
        JedisPool jedisPool = new JedisPool(jedisPoolConfig,"node1",6379);
        //从连接池中获取连接对象
        jedis = jedisPool.getResource();
    }

    //释放连接
    @After
    public void close(){
        jedis.close();
    }
}

3.Jedis:String操作

@Test
public void stringTest() {
    jedis.set("s1", "hadoop");
    String s1 = jedis.get("s1");
    System.out.println(s1);
    jedis.set("s2", "2");
    jedis.incr("s2");
    String s2 = jedis.get("s2");
    System.out.println(s2);
    jedis.expire("s2", 20);
    // while(true){
    //     System.out.println(jedis.ttl("s2"));
    // }
    System.out.println(jedis.exists("s1"));
    System.out.println(jedis.exists("s2"));
    jedis.setex("s2", 10, "hive");
}

4.Jedis:Hash操作

@Test
public void hashTest(){
    jedis.hset("hs1","name","zhangsan");
    String name = jedis.hget("hs1", "name");
    System.out.println(name);
    System.out.println("-------------------------------------");
    Map<String,String> maps = new HashMap<>();
    maps.put("age","20");
    maps.put("sex","male");
    jedis.hmset("hs1",maps);
    List<String> hmget = jedis.hmget("hs1", "name", "age", "sex");
    System.out.println(hmget);
    Map<String, String> map = jedis.hgetAll("hs1");
    System.out.println(map);
    for(Map.Entry map1 : map.entrySet()){
        System.out.println(map1.getKey()+"\\t"+map1.getValue());
    }
    jedis.hdel("hs1","name");
    Long l1 = jedis.hlen("hs1");
    System.out.println(l1);
    System.out.println(jedis.hexists("hs1","name"));
    System.out.println(jedis.hexists("hs1","age"));
}

5.Jedis:List操作

 @Test
 public void listTest(){
     jedis.lpush("ls1","1","2","3","4");
     jedis.rpush("ls1","5","6","7","8");
     List<String> ls1 = jedis.lrange("ls1", 0, -1);
     System.out.println(ls1);
     System.out.println(jedis.llen("ls1"));
     jedis.lpop("ls1");
     jedis.rpop("ls1");
     System.out.println(jedis.lrange("ls1",0,-1));
 }

6.Jedis:Set操作

@Test
public void setTest(){
    jedis.sadd("ss1","1","4","5","4");
    jedis.sadd("ss1","1","1","6","6");
    Set<String> ss1 = jedis.smembers("ss1");
    System.out.println(ss1);
    System.out.println(jedis.sismember("ss1","2"));
    System.out.println(jedis.sismember("ss1","1"));
    System.out.println(jedis.scard("ss1"));
    jedis.srem("ss1","1");
    System.out.println(jedis.sismember("ss1","1"));
}

7.Jedis:Zset操作

@Test
public void zsetTest(){
   jedis.zadd("zs1",20,"chinese");
   jedis.zadd("zs1",99,"english");
   jedis.zadd("zs1",30,"science");
   Set<String> zs1 = jedis.zrange("zs1", 0, -1);
   Set<Tuple> zset2 = jedis.zrevrangeWithScores("zs1", 0, -1);
   System.out.println(zs1);
   System.out.println(jedis.zcard("zs1"));
   jedis.zrem("zs1","english");
   System.out.println(jedis.zrevrangeWithScores("zs1", 0, -1));
}

以上是关于Redis基础知识的主要内容,如果未能解决你的问题,请参考以下文章

Redis核心知识点

redis的几个重要知识点

Redis缓存知识问题

redis 常见的面试题,既是面试题也是知识点

使用Redis缓存必须要知道哪些知识点?

Redis基础入门