Redis学习
Redis学习

Redis学习

一、NoSQL概述

1、NoSQL数据库特点

  • 方便扩展
  • 大数据量高性能
  • 数据类型多样性

传统关系型数据库(RDBMS)和非关系型数据库(NoSQL)的区别

传统关系型数据库(RDBMS)

  • 结构化组织
  • 固定sql语言
  • 数据和关系都存在表中
  • 严格的一致性
  • .......

非关系型数据库(NoSQL)

  • 不仅仅是数据
  • 没有固定的查询语言
  • 存储方式多样:键值对、列、文档、图形数据库
  • 最终一致性
  • 高性能、高可用、高可扩展
  • ......

3、关系型数据库分类

4、非关系型数据库分类

二、安装与使用Redis

1、Redis启动

  • 启动Redis服务:

    redis-server usr/local/bin/kconfig/redis.conf(redis根路径)

  • 使用Redis客户端连接:

    redis-cli -p 6379

  • 查看redis进程:

    ps -ef|grep redis

  • 关闭redis服务:

    shutdown、exit

  • 重启redis:

    systemctl restart redis.service

2、Redis性能测试

redis-benchmark [option] [option value]

3、Redis基础知识

  • 默认16个数据库

  • Redis是单线程的

  • Redis是单线程速度却很快的原因:

    • 多线程CPU上下文会切换,而redis将数据存储在内存中。对于内存系统来说,单线程效率最高。
  • 端口号6379 - MERZ

4、Redis基本命令

  • 127.0.0.1:6379> SELECT [index]

    切换数据库

  • 127.0.0.1:6379> DBSIZE

    查看当前数据库键值对长度

  • 127.0.0.1:6379> keys *

    查看所有key

  • 127.0.0.1:6379> FLUSHDB

    清除当前数据库内容

  • 127.0.0.1:6379> FLUSHALL

    清除所有数据库内容

  • 127.0.0.1:6379> EXISTS [key]

    查看key是否存在(存在显示(integer) 1)

  • 127.0.0.1:6379> MOVE [key] [databaseIndex]

    移除指定数据库的key

  • 127.0.0.1:6379> EXPIRE [key] [second]

    设置过期时间

  • 127.0.0.1:6379> TTL [key]

    查看剩余过期时间

  • 127.0.0.1:6379> TYPE [key]

    查看key的类型

三、Redis数据类型

1、五大基本数据类型

String字符串

以key-value方式存储

  • 127.0.0.1:6379>set [key] [value]

    创建键值对,若存在key则覆盖

  • 127.0.0.1:6379>get [key]

    根据key取出value

  • 127.0.0.1:6379> APPEND [key] [String]

    字符串后添加字符串

  • 127.0.0.1:6379> STRLEN [key]

    获取字符串长度

  • 127.0.0.1:6379> INCR [key]

    +1操作(需要为Integer类型,下同)

  • 127.0.0.1:6379> DECR [key]

    -1操作

  • 127.0.0.1:6379> INCRBY [key] [num]

    增加某值

  • 127.0.0.1:6379> DECRBY [key] [num]

    减少某值

  • 127.0.0.1:6379> GETRANGE [key] [begin] [end]

    获取字符串区间值

  • 127.0.0.1:6379> GETRANGE [key] 0 -1

    获取字符串全部值

  • 127.0.0.1:6379> SETRANGE [key] [begin] [value]

    将从begin开始的位置,替换成value

  • 127.0.0.1:6379> SETEX [key] [second] [value]

    定义key时设置过期时间

  • 127.0.0.1:6379> SETNX [key] [value]

    如果key不存在,则设置key(不会覆盖)

  • 127.0.0.1:6379> MSET k1 v1 k2 v2 k3 v3

    一次性设置多个key value

  • 127.0.0.1:6379> MGET k1 k2 k3

    一次性取出多个值

  • 127.0.0.1:6379> MSETNX k1 v1 k4 v4

    如果k1,k4都不存在,设置key value。原子性操作,一起成功或一起失败

  • 127.0.0.1:6379> mset user:1:name odinpeng user:1:age 21

    创建user对象

  • 127.0.0.1:6379> getset [key] [value]

    先获取原来的值再设置新值

List列表

以 key-v1 v2 v3方式存储,可重复

  • 127.0.0.1:6379> LPUSH [key] [value1]

    在key列表中,从前往后插入

  • 127.0.0.1:6379> LRANGE [key] [begin] [end]

    取出key集合从begin到end索引的值(0 -1取全部)

  • 127.0.0.1:6379> RPUSH [key] [value1]

    在key列表中,从后往前插入

  • 127.0.0.1:6379> LPOP [key]

    从左边移除key列表的第一个元素

  • 127.0.0.1:6379> RPOP [key]

    从右边移除key列表的第一个元素

  • 127.0.0.1:6379> LINDEX [key] [index]

    获取index索引值

  • 127.0.0.1:6379> LLEN [key]

    查看key列表长度

  • 127.0.0.1:6379> LREM [key] [count] [value]

    移除key列表指定个数的value

  • 127.0.0.1:6379> LTRIM [list] [begin] [end]

    截取指定范围的值,列表已经被修改

  • 127.0.0.1:6379> RPOPLPUSH [key] [key1]

    移除key最后一个元素到key1中

  • 127.0.0.1:6379> LSET [key] [index] [new value]

    更新列表index索引的值,不存在此下标会报错

  • 127.0.0.1:6379> LINSERT [key] before|after [value] [new value]

    在列表指定值前|后插入新值(若有重复value,取第一个value)

Set集合

以key -v1 v2 v3方式存储,不可重复

  • 127.0.0.1:6379> SADD [key] [v1] [v2] [v3]

    在set集合中添加元素,不可重复,重复覆盖原来元素

  • 127.0.0.1:6379> SMEMBERS [key]

    查看集合所有元素

  • 127.0.0.1:6379> SISMEMBER [key] [value]

    查看value是否在key中存在,存在返回1不存在返回0

  • 127.0.0.1:6379> SCARD [key]

    查看key中有几个元素

  • 127.0.0.1:6379> SREM [key] [value]

    移除key中的某值

  • 127.0.0.1:6379> SRANDMEMBER [key] [count]

    随机抽出count个元素

  • 127.0.0.1:6379> SPOP [key] [count]

    随机移除count个元素

  • 127.0.0.1:6379> SMOVE [key1] [key2] [value]

    将key1中的值移动到key2中

  • 127.0.0.1:6379> SDIFF [key] [key2]

    找出key和key2的不同值

  • 127.0.0.1:6379> SUNION [key] [key2]

    求key和key2的并集

Hash哈希

以 key-<k1,v1>,<k2,v2>,<k3,v3> 方式存储

  • 127.0.0.1:6379> HSET [key] [k1] [v1] [k2] [v2]

    向key中添加k1 v1和k2 v2键值对

  • 127.0.0.1:6379> HGET [key] [k1]

    取出key中的k1的值

  • 127.0.0.1:6379> HGETALL [key]

    显示所有key中的键值对

  • 127.0.0.1:6379> HMGET [key] [k1] [k2]

    同时取出key中k1和k2的值

  • 127.0.0.1:6379> HDEL [key] [k1] [k2]

    同时删除key中k1和k2的值

  • 127.0.0.1:6379> HLEN [key]

    查看当前key中的键值对个数

  • 127.0.0.1:6379> HEXISTS [key] [k1]

    判断key中的k1是否存在

  • 127.0.0.1:6379> HKEYS [key]

    获取当前key中的所有键

  • 127.0.0.1:6379> HVALS [key]

    获取当前key中的所有值

  • 127.0.0.1:6379> HINCRBY [key] [k1] [count]

    将key中k1对应的值+count,count为负数则为-

  • 127.0.0.1:6379> HSETNX [key] [k1] [v1]

    若k1存在则创建,k1不存在则不创建

Zset有序集合

以key- <num1,v1>,<num2,v2>,<num3,v3>存储,有序集合

  • 127.0.0.1:6379> ZADD [key] [num1] [v1] [num2] [v2] [num3] [v3]

    在key中存储带序号的值,保存顺序按照序号从小到大

  • 127.0.0.1:6379> ZRANGE [key] [begin] [end]

    查看key中从begin到value索引的部分,0 -1查看所有

  • 127.0.0.1:6379> ZRANGEBYSCORE [key] [min] [max]

    从min到max排列显示value,负无穷-正无穷:-inf +inf

  • 127.0.0.1:6379> ZRANGEBYSCORE [key] [min] [max] withscores

    从min到max排列显示value、num,负无穷-正无穷:-inf +inf

默认为开区间,在num前添加(将其设置为闭区间。

  • 127.0.0.1:6379> ZREVRANGE [key] [begin] [end]

    倒序查看从begin到endkey中的value

  • 127.0.0.1:6379> ZRANGE [key] [value]

    移除key中的value

  • 127.0.0.1:6379> ZCARD [key]

    获取集合中的个数

  • 127.0.0.1:6379> zcount [key] [min] [max]

    获取指定区间的个数

2、三种特殊数据类型

Geospatial地理位置

有效纬度:-85.05112878到85.05112878

有效经度:-180到180


  • 127.0.0.1:6379> GEOADD [key] 纬度 经度 [place]

    在key中添加城市的纬度经度

  • 127.0.0.1:6379> GEOPOS [key] [place1] [place2]

    获取key中城市的纬度经度

  • 127.0.0.1:6379> GEODIST [key] [place1] [place2] [m,km,ft,mi]

    获取key中两个位置的距离,默认单位为m

  • 127.0.0.1:6379> GEORADIUS [key] [经度] [纬度] [半径] [m,km,ft,mi]

    找出key中所有与指定经度纬度位置距离小于半径的地方

  • 127.0.0.1:6379> GEORADIUSBYMEMBER [key] [place] [半径] [m,km,ft,mi]

    找出key中与place距离小于半径的城市,包括place

Hyperloglog基数统计

存储方式与set类似,但内存较小,用于大数量的数据统计

  • 127.0.0.1:6379> PFADD [key] [v1] [v2] [v3]

    向key中添加v1 v2 v3,不可重复

  • 127.0.0.1:6379> PFCOUNT [key]

    获取key中元素数量

  • 127.0.0.1:6379> PFMERGE [key] [key1] [key2]

    将key1和key2合并为key

Bitmap位图

统计用户信息,适用于只有两个状态(例如打卡为1,未打卡为0)

  • 127.0.0.1:6379> SETBIT [key] [num] [0/1]

    往key中存储某num和其状态(0或1)

  • 127.0.0.1:6379> GETBIT [key] [num]

    获取key中num的状态,为1则返回(integer) 1

  • 127.0.0.1:6379> BITCOUNT [key]

    统计状态为1的总数

四、事物

  • Redis单条命令保证原子性,但事物不保证原子性(同时成功或同时失败)

  • Redis事物没有隔离级别的概念

1、事物基本操作

  • 开启事物
  • 输入命令
  • 提交事务,一次性执行命令

2、基本命令

  • 127.0.0.1:6379> MULTI

    开启事物

  • 127.0.0.1:6379> EXEC

    提交事物

  • 127.0.0.1:6379> DISCARD

    放弃事物

3、出现异常

  • 编译时异常,输入命令错误,所有命令都不会执行

  • 运行时异常,命令语法正确,运行时报错。除报错命令,其他命令正常执行

4、锁

悲观锁

  • 很悲观,认为命令会出问题,无论什么时候都上锁。效率低

乐观锁

  • 很乐观,认为命令不会出问题,不会上锁。效率高。

  • 获取value

  • 更新的时候比较value

Redis监视测试

  • 事物正常结束,数据期间没有发生变动,则正常执行成功。

  • 事物提交前,另一个线程修改了值,则导致事物失败。

  • 127.0.0.1:6379> WATCH [key]

    监视某key

  • 127.0.0.1:6379> UNWATCH [key]

    接触对key的监控

五、Jedis

1、Jedis简介

Jedis是redis的java版本的客户端实现

2、Jedis使用

1、引入依赖

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

2、测试连接(使用本地连接)

import org.junit.Test;
import redis.clients.jedis.Jedis;

public class TestPing {
    @Test
    public void test1(){
        Jedis jedis = new Jedis("127.0.0.1",6379); //ip,端口号
        System.out.println(jedis.ping());
    }
}

输出结果:

六、SpringBoot整合

在SpringBoot 2.0之后,操作redis由原来的jedis替换成了lettuce

  • jedis:采用直连方式,多线程操作不安全

  • lettuce:采用netty,实例可以在多个线程中进行共享,不存在线程不安全情况

1、使用方式

  • 引入依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  • 配置properties文件
#配置redis
spring.redis.host=127.0.0.1
spring.redis.port=6379 
  • 连接测试
@SpringBootTest
class RedisSpringBootApplicationTests {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    void contextLoads() {
        redisTemplate.opsForValue().set("k1","你好!");
        Object k1 = redisTemplate.opsForValue().get("k1");
        System.out.println(k1);
        //获取redis连接对象
        RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
        connection.flushAll();
    }
}

操作数据类型

redisTemplate.opsForValue(); //String
redisTemplate.opsForList(); //List
redisTemplate.opsForHash(); //Hash
redisTemplate.opsForSet(); //Set
redisTemplate.opsForZSet(); //ZSet
redisTemplate.opsForGeo(); //Geospatial
redisTemplate.opsForHyperLogLog(); //Hyperloglog

2、具体使用

  • 编写Redis配置类,实现序列化
//Redis配置类
@Configuration
public class RedisConfig {

    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();

        return template;
    }

}
  • 在真实开发中,不会使用原生redisTemplate来写redis命令

  • 常常会写一个RedisUtils来封装set、get等方法,直接用RedisUtils.set()写Redis命令

3、Redis设置密码

  • 设置密码

127.0.0.1:6379> config set requirepass password

  • 查看密码

127.0.0.1:6379> config get requirepass

  • 登录

127.0.0.1:6379> AUTH password

七、Redis配置文件

  • 查看当前库的信息

127.0.0.1:6379> INFO replication

一条评论

发表回复

您的电子邮箱地址不会被公开。