Redis

概念:Redis是用C语言开发的一个开源的高性能键值对(Key-value)数据库

特征:

  1. 数据间没有必然的关联关系
  2. 内部采用单线程机制进行工作
  3. 高性能,官方提供测试数据,50个并发执行100000个请求,读的速度是110000次/s,写的速度是81000次/s。
  4. 多数据类型支持

       字符串类型   string

        列表类型        list

        散列类型        hash

        集合类型         set

         有序集合类型    sorted_set

5.持久化支持。可以进行数据灾难恢复。

二、Redis的下载与安装
2.1Redis的下载

Linux版(适用于企业级开发)

  • Redis高级开始使用
  • 以4.0版本作为主板本

Windows版本(适合零基础学习)

  • Redis入门使用
  • 以 3.2 版本作为主版本
  • 下载地址:https://github.com/MSOpenTech/redis/tags
2.2安装Redis

 核心文件:

redis-server.exe 服务器启动命令

redis-cli.exe 命令行客户端

redis.windows.conf redis核心配置文件

redis-benchmark.exe 性能测试工具

redis-check-aof.exe AOF文件修复工具

redis-check-dump.exe RDB文件检查工具(快照持久化文件)

2.3启动Redis

服务器启动

方式1:双击redis-server.exe

方式2:指令redis-server.exe redis.windows.conf

客户端连接

 三、Redis数据类型(5种常用)

5.1String
  • 存储的数据:单个数据,最简单的数据存储类型,也是最常用的数据存储类型
  • 存储数据的格式:一个存储空间保存一个数据
  • 存储内容:通常使用字符串,如果字符串以整数的形式展示,可以作为数字操作使用

 业务场景一:========================================================== 大型       大型企业级应用中,随着数据量的递增,分表操作是基本操作,使用多张表存储同类型数据,但是对应的主键 id 必须保证统一性,不能重复。Oracle 数据库具有 sequence 设定,可以解决该问题,但是 MySQL数 据库并不具有类似的机制,那么如何解决?

设置数值数据增加指定范围的值

incr key

incrby key increment

incrbyfloat key increment

设置数值数据减少指定范围的值

decr key

decrby key increment

业务场景二:==========================================================

“中国有嘻哈”启动海选投票,只能通过微信投票,每个微信号每 4 小时只能投1票。

 电商商家开启热门商品推荐热门商品不能一直处于热门,每种商品热门期维持3天,3天后自动取消热门。 新闻网站会出现热点新闻,热点新闻最大的特征是时效性,如何自动控制热点新闻的时效性。

设置数据具有指定的生命周期

setex key seconds value psetex key milliseconds value

设置key的过期时间

EXPIRE key seconds

查看key的剩余时间

ttl key

Tips 2:

redis 控制数据的生命周期,通过数据是否失效控制业务行为,适用于所有具有时效性限定控制的操作

业务场景三:==========================================================         主页高频访问信息显示控制,例如新浪微博大V主页显示粉丝数与微博数量 

关注数focuss               粉丝数fans                  微博数blogs                                                             解决方案

在redis中为大V用户设定用户信息,以用户主键和属性值作为key,后台设定定时刷新策略即可

eg: user:id:3506728370:fans → 12210947

eg: user:id:3506728370:blogs → 6164

eg: user:id:3506728370:focuss → 83

在redis中以json格式存储大V用户信息,定时刷新(也可以使用hash类型)

eg: user:id:3506728370 → {"id":3506728370,"name":"春晚","fans":12210862,"blogs":6164, "focus":83}

Tips 3:redis应用于各种结构型和非结构型高热度数据访问加速 key 的设置约定===数据库中的热点数据key命名惯例 表名:主键名:主键值:字段名

eg: order:id:9527:name : 王瑞豪

注意事项:========================================================== 数据操作不成功的反馈与数据正常操作之间的差异

① 表示运行结果是否成功       (integer) 0 → false 失败       (integer) 1 → true 成功

② 表示运行结果值      

(integer) 3 → 3 3个      

(integer) 1 → 1 1个

数据未获取到

         (nil)等同于null

数据最大存储量

512MB

数值计算最大范围(java中的long的最大值)

9223372036854775807

5.2hash

存储的困惑

对象类数据的存储如果具有较频繁的更新需求操作会显得笨重

hash哈希特点

  • 新的存储需求:对一系列存储的数据进行编组,方便管理,典型应用存储对象信息
  • 需要的存储结构:一个存储空间保存多个键值对数据
  • hash类型:底层使用哈希表结构实现数据存储

hash存储结构优化

  • 如果filed数量较少,存储结构优化为类数组结构
  • 如果field数量较多,存储结构使用HashMap结构

==========================hash哈希类型==========================                        添加/修改数据

hset key field value

获取数据

hget key field hgetall key

删除数据

hdel key field1 [field2]

获取哈希表中字段的数量

hlen key

获取哈希表中所有的字段名或字段值

hkeys key hvals key

hash 类型数据操作的注意事项

1.hash类型下的value只能存储字符串,不允许存储其他数据类型,不存在嵌套现象。如果数据未获取 到,对应的值为(nil)

2.每个 hash 可以存储 2^32^-1个键值对

3.hash类型十分贴近对象的数据存储形式,并且可以灵活添加删除对象属性。但hash设计初衷不是为了 存储大量对象而设计的,切记不可滥用,更不可以将hash作为对象列表使用

 4.hgetall 操作可以获取全部属性,如果内部field过多,遍历整体数据效率就很会低,有可能成为数   据访问瓶颈

业务场景一:==========================================================   string存储对象(json)与hash存储对象 Stirng存对象强调整体性一般用于读 hash存对象强调灵活性一般用于写

业务场景二:==========================================================

电商网站购物车设计与实现 购物车的redis存储模型 添加、浏览、更改数量、删除、清空

解决方案

  • 以客户id作为key,每位客户创建一个hash存储结构存储对应的购物车信息
  • 将商品编号作为field,购买数量作为value进行存储
  • 添加商品:追加全新的field与value
  • 浏览:遍历hash
  • 更改数量:自增/自减,设置value值
  • 删除商品:删除field
  • 清空:删除key
5.3List
  • 数据存储需求:存储多个数据,并对数据进入存储空间的顺序进行区分
  • 需要的存储结构:一个存储空间保存多个数据,且通过数据可以体现进入顺序
  • list类型:保存多个数据,底层使用双向链表存储结构实现

==========================list==========================                                      添加/修改数据

lpush key value1 [value2] ……

rpush key value1 [value2] ……

获取数据

lrange key start stop

lindex key index

llen key

获取并移除数据

lpop key rpop key

通过下标截取指定的长度,这个list已经被改变了,只剩下截取的元素

ltrim key start end

lset将列表中指定下标的值替换为另外一个值,更新操作

lset key 下标 新数据 # 如果不存在列表我们去更新就会报错

list 类型数据操作注意事项

1.list中保存的数据都是string类型的,数据总容量是有限的,最多2^32^-1个元素 (4294967295)

2.list具有索引的概念,但是操作数据时通常以队列的形式进行入队出队操作,或以栈的形式进行入栈出 栈操作

3.获取全部数据操作结束索引设置为-1

4.list可以对数据进行分页操作,通常第一页的信息来自于list,第2页及更多的信息通过数据库的形式加 载

5.4Set
  • 新的存储需求:存储大量的数据,在查询方面提供更高的效率
  • 需要的存储结构:能够保存大量的数据,高效的内部存储机制,便于查询
  • set类型:与hash存储结构完全相同,仅存储键(nil),并且值是不允许重复的

==========================Set==========================                                 添加数据

sadd key member1 [member2]

获取全部数据

smembers key

删除数据

srem key member1 [member2]

获取集合数据总量

scard key

判断集合中是否包含指定数据

sismember key member

业务场景一:==========================================================         每位用户首次使用今日头条时会设置3项爱好的内容,但是后期为了增加用户的活跃度、兴趣点,必须让用户 对其他信息类别逐渐产生兴趣,增加客户留存度,如何实现? 业务分析

1.系统分析出各个分类的最新或最热点信息条目并组织成set集合

2.随机挑选其中部分信息

3.配合用户关注信息分类中的热点信息组织成展示的全信息集合

解决方案

随机获取集合中指定数量的数据

srandmember key [count]

随机获取集合中的某个数据并将该数据移出集合

spop key [count]

Tips 1:

redis 应用于随机推荐类信息检索,例如热点歌单推荐,热点新闻推荐,热卖旅游线路,应用APP推荐, 大V推荐等

 业务场景二:==========================================================        1.脉脉为了促进用户间的交流,保障业务成单率的提升,需要让每位用户拥有大量的好友,事实上职场新人不 具有更多的职场好友,如何快速为用户积累更多的好友?

2.新浪微博为了增加用户热度,提高用户留存性,需要微博用户在关注更多的人,以此获得更多的信息或热门 话题,如何提高用户关注他人的总量?

3.QQ新用户入网年龄越来越低,这些用户的朋友圈交际圈非常小,往往集中在一所学校甚至一个班级中,如何 帮助用户快速积累好友用户带来更多的活跃度?

4.美团外卖为了提升成单量,必须帮助用户挖掘美食需求,如何推荐给用户最适合自己的美食?

解决方案

求两个集合的交、并、差集

sinter key1 [key2]

sunion key1 [key2]

sdiff key1 [key2]

求两个集合的交、并、差集并存储到指定集合中

sinterstore destination key1 [key2]

sunionstore destination key1 [key2]

sdiffstore destination key1 [key2]

将指定数据从原始集合中移动到目标集合中

smove source destination member

 set 类型数据操作的注意事项

1.set 类型不允许数据重复,如果添加的数据在 set 中已经存在,将只保留一份

2.set 虽然与hash的存储结构相同,但是无法启用hash中存储值的空间

 具体实例

package com.ly.springboot_redis.pojo;

import java.io.Serializable;


public class Student implements Serializable {
    private Integer stuid;

    private String stuname;

    private String stuhobby;

    public Student(Integer stuid, String stuname, String stuhobby) {
        this.stuid = stuid;
        this.stuname = stuname;
        this.stuhobby = stuhobby;
    }

    public Student() {
    }

    @Override
    public String toString() {
        return "Student{" +
                "stuid=" + stuid +
                ", stuname='" + stuname + '\'' +
                ", stuhobby='" + stuhobby + '\'' +
                '}';
    }

    public Integer getStuid() {
        return stuid;
    }

    public void setStuid(Integer stuid) {
        this.stuid = stuid;
    }

    public String getStuname() {
        return stuname;
    }

    public void setStuname(String stuname) {
        this.stuname = stuname;
    }

    public String getStuhobby() {
        return stuhobby;
    }

    public void setStuhobby(String stuhobby) {
        this.stuhobby = stuhobby;
    }
}
package com.ly.springboot_redis.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.net.UnknownHostException;


@Configuration
public class JSonConfig {
    @Bean
    public RedisTemplate<Object,Object> jsonRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        //1.创建自定义模版类
        RedisTemplate<Object,Object> template=new RedisTemplate<>();
        //配置json类型的序列化工具
        template.setKeySerializer(new StringRedisSerializer());//这样key会用字符串方式保存
        template.setDefaultSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}

测试类

package com.ly.springboot_redis;

import com.alibaba.fastjson.JSONObject;
import com.ly.springboot_redis.pojo.Student;

import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Arrays;
import java.util.List;
import java.util.Set;


@RunWith(SpringRunner.class)
@SpringBootTest
class SpringbootRedisApplicationTests {

    //演示1(专用对象)
    @Autowired
    public RedisTemplate redisTemplate1;
    //专用对象
    @Autowired(required = false)
    public StringRedisTemplate redisTemplate;

    //演示3(自定义)
    @Autowired
    public RedisTemplate jsonRedisTemplate;
    /**
     * 测试stringRedisTemplate
     * */
    @Test
    public void stringRedisTemplate(){
        //1.key相关
        Set<String> keys=redisTemplate.keys("*");
        for (String key : keys) {
            System.out.println(key);
        }
        //2.各种类型支持
        redisTemplate.opsForValue();
        redisTemplate.opsForList();
        redisTemplate.opsForHash();
        redisTemplate.opsForSet();
        redisTemplate.opsForZSet();
        //3.举例字符串
        redisTemplate.opsForValue().set("name","蒋孝云");
        String name = redisTemplate.opsForValue().get("name");
        System.out.println(name);
        //4.操作list列表
        redisTemplate.opsForList().leftPush("mylist1","曹操");
        redisTemplate.opsForList().leftPush("mylist1","曹植");

    }

    /**
     * 测试自定义
     * 定义配置类javaconfig,自定义序列化策略
     * */
    @Test
    public void show3(){
        //保存对象
        Student stu=new Student(1,"小明","看书");
        jsonRedisTemplate.opsForValue().set("stu",stu);
        //获取对象
        Object o = jsonRedisTemplate.opsForValue().get("stu");
        String jsonString = JSONObject.toJSONString(o);
        Student student = JSONObject.parseObject(jsonString, Student.class);
        System.out.println(student);

        Student stu1=new Student(2,"小红","听音乐");
        Student stu2=new Student(2,"丹妮","听音乐");
        Student stu3=new Student(2,"詹妮","听音乐");
        List<Student> list= Arrays.asList(stu1,stu2,stu3);
        jsonRedisTemplate.opsForValue().set("stus",list);
        //必须接受Object,利用ObjectMapper对象转换,若强制转换会报错
        Object data = jsonRedisTemplate.opsForValue().get("stus");
        String datajson = JSONObject.toJSONString(data);
        //将JSON转为List
        List<Student> students=JSONObject.parseArray(datajson,Student.class);
        System.out.println(students);


    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值