Mac下Redis的安装和SpringBoot整合Redis实现常规操作

前言

本片博客是本人在网上看文学习Redis所产出的学习笔记,内容均为本人实操所得希望对正在学习Redis的各位有所帮助!

Redis的安装(MAC)

1.官网下载

https://redis.io

2.安装

以下是Redis安装的命令,对自己下载的版本进行修改

# 解压(我下载的版本是5.0.7)
tar -zxvf redis-5.0.7.tar.gz
# 拷贝的local目录下
sudo cp -rf redis-5.0.7 /usr/local/
# 进入相应目录下
cd /usr/local/redis-*
# 编译
sudo make test
# 安装
sudo make install
# 建立相应目录
sudo mkdir bin etc db
# 拷贝启动文件
sudo cp src/mkreleasehdr.sh src/redis-benchmark src/redis-check-rdb src/redis-cli src/redis-server bin/

###############################################
# 如果在编译时报错了,清理了再编译一下:
sudo make distclean && sudo make && sudo make test
3.配置

看注释(没有硬性要求可以不做修改)

# 拷贝配置文件(在redis目录下)
sudo cp redis.conf etc/
sudo vi etc/redis.conf

####内容参照如下:(选择性修改就好了,不用全都照着改)

#修改为守护模式(后台启动)
daemonize yes
#设置进程锁文件
pidfile /usr/local/redis-5.0.7/redis.pid
#端口
port 6379
#客户端超时时间
timeout 300
#日志级别
loglevel debug
#日志文件位置
logfile /usr/local/redis-5.0.7/log-redis.log
#设置数据库的数量,默认数据库为0,可以使用SELECT <dbid>命令在连接上指定数据库id
databases 16
##指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合
#save <seconds> <changes>
#Redis默认配置文件中提供了三个条件:
save 900 1
save 300 10
save 60 10000
#指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,
#可以关闭该#选项,但会导致数据库文件变的巨大
rdbcompression yes
#指定本地数据库文件名
dbfilename dump.rdb
#指定本地数据库路径
dir /usr/local/redis-5.0.7/db/
#指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能
#会在断电时导致一段时间内的数据丢失。因为 redis本身同步数据文件是按上面save条件来同步的,所以有
#的数据会在一段时间内只存在于内存中
appendonly no
#指定更新日志条件,共有3个可选值:
#no:表示等操作系统进行数据缓存同步到磁盘(快)
#always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)
#everysec:表示每秒同步一次(折衷,默认值)
appendfsync everysec
# 设置连接密码
requirepass yourpassword
4.服务启动
sudo /usr/local/redis-5.0.7/src/redis-server /usr/local/redis-5.0.7/etc/redis.conf
5.服务关闭

结束redis服务

  • 1.可以直接结束进程
  • 2.在客户端执行 SHUTDOWNSHUTDOWN NOSAVE 可关闭 redis 服务
6.客户端

redis自带客户端工具,可以直接使用

# 进入相应目录
cd /usr/local/redis-4.0.10/src/
# 启动客户端连接
./redis-cli 

# 注意:如果后续操作的时候存储数据时出现中文乱码,可在启动客户端时加上 --raw
# ./redis-cli --raw


# 如果有密码
sudo ./redis-cli auth yourpassword

客户端常用命令:

命令用途
keys *查看所有的 key
exists key查看此 key 是否存在
get key获取 key 的值
set key value设置 key 的值
flushall清空所有
7.可视化工具

Redis桌面管理工具Mac版:http://www.pc6.com/mac/486661.html

8.其他常用的命令
# 查找redis-server的PID
ps -ef |grep redis

# 根据PID暂用服务
kill -9 PID

# 查看6379是否被暂用
netstat -lntp | grep 6379

Redis介绍:

1.概述

Redis是一种速度非常快的非关系数据库(NO-Relational Database),可以将存储在内存中的键值对数据持久化到硬盘,可以使用复制特性来扩展性能,还可以使用客户端来分片来扩展写性能

为了满足高性能,Redis采用内存(in-memory)数据集(Dataset),根据使用场景,可以通过每隔一段时间转储数据集到磁盘,或者最佳每条命令到日志来持久化。持久化也可以被禁用,如果你只是需要一个功能丰富,网络化的内存缓存。

2.数据模型

Redis数据模型不仅与关系数据库管理系统(RDBMS)不同,也不同于任何简单的NoSQL键值数据存储。Redis数据类型类似于变成语言的基础数据类型,因此开发人员感觉很自然,每个数据类型都支持适用于其类型的操作,受支持的数据类型包括:

  • String(字符串)
  • Hash(哈希)
  • List(列表)
  • Set(集合)
  • Zset(Sorted Set:有序集合)
3.关键优势

Redis的优势包括它的速度,对富数据的·支持,操作的原子性,以及通用性:

  • 性能极高,它每秒可执行约100000个Set以及约100000个Get操作
  • 丰富的数据类型,Redis对大多数的开发人员已知的大多数数据类型提供了原生支持,这使得各种问题得以轻松解决
  • 原子性,因为所有的Redis操作都是原子性的,所以多个客户端会并发地访问一个Redis访问器,获取相同的更新值
  • 丰富的特性,Redis是一个多效用的工具,有非常多的应用场景,包括缓存,消息队列(Redis原生支持发布/订阅),短期应用程序数据(比如web会话,web页面命中技术)等
4. spring-boot-starter-data-redis

Spring Boot 提供了对 Redis 集成的组件包:spring-boot-starter-data-redis,它依赖于 spring-data-redis 和 lettuce。Spring Boot 1.0 默认使用的是 Jedis 客户端,2.0 替换成了 Lettuce,但如果你从 Spring Boot 1.5.X 切换过来,几乎感受不大差异,这是因为 spring-boot-starter-data-redis 为我们隔离了其中的差异性。

  • Lettuce:是一个可伸缩线程安全的 Redis 客户端,多个线程可以共享同一个

  • Spring Data:是 Spring 框架中的一个主要项目,目的是为了简化构建基于 Spring 框架应用的数据访问,包括非关系数据库、Map-Reduce 框架、云数据服务等,另外也包含对关系数据库的访问支持。

  • Spring Data Redis:是 Spring Data 项目中的一个主要模块,实现了对 Redis 客户端 API 的高度封装,使对 Redis 的操作更加便捷

  • 可以用以下方式来表达它们之间的关系:

    • Lettuce  Spring Data Redis  Spring Data  spring-boot-starter-data-redis
      

    因此 Spring Data Redis 和 Lettuce 具备的功能,spring-boot-starter-data-redis 几乎都会有。

快速上手

项目目录结构
1.导入相关依赖
        <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>

引入 commons-pool 2 是因为 Lettuce 需要使用 commons-pool 2 创建 Redis 连接池。

2.application 配置
# Redis 数据库索引(默认为 0)
spring.redis.database=0
# Redis 服务器地址
spring.redis.host=localhost
# Redis 服务器连接端口
spring.redis.port=6379
# Redis 服务器连接密码(默认为空)
spring.redis.password=123
# 连接池最大连接数(使用负值表示没有限制) 默认 8
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
spring.redis.lettuce.pool.max-wait=
# 连接池中的最大空闲连接 默认 8
spring.redis.lettuce.pool.max-idle=8
# 连接池中的最小空闲连接 默认 0
spring.redis.lettuce.pool.min-idle=0

从配置可以看出来,SpringBoot是默认支持 Lettuce 连接池的

3.缓存配置

在这里可以为 Redis 设置一些全局配置,比如配置主键的生产策略 KeyGenerator,如不配置会默认使用参数名作为主键。

package com.jn.config;

import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Method;

/**
 * @Author ScholarTang
 * @Date 2020/2/3 5:43 PM
 * @Desc redis缓存配置
 */

@Configuration
@EnableCaching  //开启缓存
public class RedisConfig extends CachingConfigurerSupport {

    @Bean
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }
}
4.测试使用

在SpringBoot测试类中注入RedisTemplate

 		//TODO 注入RedisTemplate
    @Autowired
    private RedisTemplate redisTemplate;
1.String

String是最常见的一种数据类型,普通的key/value存储都可以归为此类,value其实不仅是String也可以是数字

 		@Test
    void testString() {
      	//向缓存中存储一对键值
        redisTemplate.opsForValue().set("jn","Jimmy");
        //根据key获取value进行,期望值比较
        Assert.assertEquals("Jimmy",redisTemplate.opsForValue().get("jn"));
    }
2.Redis对pojo的支持,新建一个User对象,放到缓存中,再取出来

创建实体类User.java

package com.jn.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.io.Serializable;

/**
 * @Author ScholarTang
 * @Date 2020/2/3 6:12 PM
 * @Desc 用户对象
 */

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User implements Serializable {
    private String username;
    private Integer age;
    private String sex;
    private String email;
}

测试:

 @Test
    public void testObj() {
        User user = new User("jimmy", 23, "1", "zs123@163.com");
        ValueOperations<String, User> operations = redisTemplate.opsForValue();
        operations.set("com.zs", user);
        User zs = operations.get("com.zs");
        System.out.println(zs);
    }
3.超时失效

Reids在存入每一个数据的时候都可以设置一个超时时间,过来这个时间就会自动删除数据,这种特性非常适合我们对阶段数据的存储

   /**   
     * 新建一个User对象,存入Redis的同时设置100毫秒后失效,
     * 设置一个线程暂停,1000毫秒之后,判断数据是否操作并打印结果
     */
    @Test
    public void testExpire() throws InterruptedException {

        User user = new User("Lucy", 20, "0", "luck@163.com");
        ValueOperations<String, User> operations = redisTemplate.opsForValue();
        operations.set("lucy",user,100,TimeUnit.MILLISECONDS);
        Thread.sleep(1000);
        Boolean lucy = redisTemplate.hasKey("lucy");
        if (lucy) {
            System.out.println("lucy is true");
        } else {
            System.out.println("lucy is false");
        }

    }
4.删除数据

对过期的缓存进行删除

@Test
    public void testDelete() {
        redisTemplate.opsForValue().set("deleteKey", "thisData");
        redisTemplate.delete("deleteKey");
        Boolean deleteKey = redisTemplate.hasKey("deleteKey");
        if (deleteKey) {
            System.out.println("thisData is true");
        } else {
            System.out.println("thisData is false");
        }
    }
5. Hash(哈希)

一般我们存储一个键,很自然的就会使用get/set去存储,实际上这并不是最好的做法,Redis存储一个key会有一个最小内存,不管你存储的这个键多小,都不会低于这个内存,因此合理的使用Hash可以帮我们节省很多内存

Hash Set 就是在哈希表 Key中的域(Field)的值设为value。如果key不存在,一个行的哈希表被创建并进行Hast操作;如果域(Field)已经存在于哈希表中,旧值将被覆盖

 @Test
    public void testHash () {
        /**
         * Hash set需要传入三个值,
         * 第一个为key,
         * 第二个为Field,
         * 第三个为存储的值,
         * 一般情况下key代表一组数据,
         * Field为key相关的属性二Value就是属性对应的值
         */
        HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
        //值1
        hash.put("hash", "you", "data one");
        //值2
        hash.put("hash", "you", "data two");
        //得到的是值2,值2将值1覆盖了
        String value = (String) hash.get("hash", "you");
        System.out.println("hash value:" + value);
    }
6.List

Redis List的应用场景非常多,也是Redis最重要的数据结构之一。使用List可以轻松实现一个队列,可以利用List的Push操作,将任务存在List中,然后工作线程再用POP操作将任务进行执行

Redis List的实现为一个双向链表,即可以支持反向查找和遍历,更方便的操作,不过带来的部分的内存开销。Redis内部有很多实现,包括发送缓冲队列等也都是用的这个数据结构

 @Test
    public void testList() {
        ListOperations<String,String> list = redisTemplate.opsForList();
        list.leftPush("list", "data one");
        list.leftPush("list", "data two");
        list.leftPush("list", "data there");

        String value = list.leftPop("list");
        System.out.println("list value:"+value);

        /**
         * 在如上代码中我们从左侧插入了一个key为list的队列,然后取出左侧最近的一条数据。
         * 其实List有很多API可以操作,比如由此坚信插入队列从右侧进行读取,或者通过方法range读取队列的一部分。
         * 演示使用range读取队列的一部分数据:
         * range后面的两个参数就是插入数据的位置,输入不同的参数就可以取出队列中对应的数据
         */
        List<String> values = list.range("list", 0, 2);
        for (String s : values) {
            System.out.println("list range:" + s);
        }
    }
7.Set

Redis Set对外提供的功能于List类似是一个列表功能,特殊之处在于Set是可以自动排抽的,当你需要存储一个列表数据,又不希望出现重复数据时,Set是一个很好的选择,并且Set提供了判断某个成员是否在一个Set集合内的重要接口这个也是List所不能提供的

   /**
     * 测试结果:
     * set value :banana
     * set value :apple
     * 通过这个案例我们可以发现,输入了两个相同的值banana,全部读取的时候只剩下了一条,
     * 说明Set对队列进行了自动排重操作
     */
    @Test
    public void testSet() {
        String key = "set";
        SetOperations<String, String> set = redisTemplate.opsForSet();
        set.add(key,"apple");
        set.add(key,"banana");
        set.add(key,"banana");

        Set<String> values = set.members(key);
        for (String value : values) {
            System.out.println("set value :" + value);
        }

    }

Redis为集合提供了求交集,并集,差集等操作,可以非常方便的使用。

@Test
    public void test() {

        SetOperations<String, String> set = redisTemplate.opsForSet();
        String key1 = "setMore1";
        String key2 = "setMore2";

        set.add(key1, "apple");
        set.add(key1, "banana");
        set.add(key1, "orange");
        set.add(key2, "apple");
        set.add(key2, "orange");

        //TODO 测试difference(差集)
        /**
         * 根据这个例子可以看出,difference()函数会把key1中不同于key2的数据对比出来,
         * 这个特性很适合我们在金融场景中对账的时候使用
         */
        Set<String> diffs = set.difference(key1, key2);
        for (String diff : diffs) {
            System.out.println("diffs set value :" + diff); //diffs set value :banana
        }

        //TODO 测试unions(并集)
        /**
         * 根据这个例子可以看出来,unions会取两个集合中的合集
         * Set的内部实现是一个Value永远为null的HashMap,实际上是通过计算Hash的方式来快速排重的,
         * 这也是Set能提供判断一个成员是否在集合内的原因
         */
        Set<String> unions = set.union(key1, key2);
        for (String union : unions) {
            System.out.println("unions set value :" + union);
        }

        //TODO 测试intersect(交集)
        /**
         *根据这个例子可以看出来,intersect会取两个集合的相同的集(交集)
         */
        Set<String> intersects = set.intersect(key1, key2);
        for (String intersect : intersects) {
            System.out.println("intersects set value :" + intersect);
        }
    }
8.ZSet

Redis Sorted Set的使用场景与Set类似,区别是Set不是自动有序的,而SortedSet可以通过用户额外提供的优先级(Score)的参数来进行成员排序,并且是插入有序,集自动排序在使用ZSet的时候需要额外的输入一个参数Score,ZSet会自动根据Score的只对集合进行排序,我们可以利用这特性来做具有权重的队列,
比如普通消息的Score为1,重要消息的Score为2,然后工作线程可以选择Score的倒叙来获取工作任务

   /**
     * 测试结果:
     * zsetA value :apple
     * zsetA value :strawberry
     * zsetA value :banana
     * zsetA value :orange
     * zsetB value :apple
     * zsetB value :strawberry
     * zsetB value :banana
     *
     * 根据这个例子我们发现插入到ZSet的数据会自动根据Score进行排序,根据这个特性我们可以优先队列等各种常见的场景。
     * 另外Redis还提供了rangeByScore这样的一个方法,可以只获取Score范围内排序后的数据
     *
     * Redis Sorted Set 的内部使用HashMap和跳跃表(SkipList)来保证数据的存储有序,
     * HashMap里放的是所有的成员,排序依据是HashMap里存的Score,
     * 使用跳跃表的结构可以获得比较高的查找效率,并在实现上比较简单
     */
    @Test
    public void testZset() {
        String key = "zset";

        ZSetOperations<String, String> zset = redisTemplate.opsForZSet();
        zset.add(key, "apple", 1);
        zset.add(key, "banana", 3);
        zset.add(key, "orange", 4);
        zset.add(key, "strawberry", 2);

        Set<String> zsetsA = zset.range(key, 0, 3);
        for (String value : zsetsA) {
            System.out.println("zsetA value :" + value);
        }

        /**
         * 获取指定索引范围内的元素(含头不含尾)
         */
        Set<String> zsetsB = zset.rangeByScore(key, 0, 3);
        for (String value : zsetsB) {
            System.out.println("zsetB value :" + value);
        }
    }

9.封装

在我们实际的使用过程中,不会给每一个使用的类都注入RedisTemplate来直接使用,一般都会对业务进行简单的包装,最后提供出来对外使用

RedisService.java

package com.jn.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.Set;


/**
 * @Author ScholarTang
 * @Date 2020/2/3 9:31 PM
 * @Desc RedisService
 */


@Service
public class RedisService {
    @Autowired
    private RedisTemplate redisTemplate;


    /**
     * 封装简单插入操作
     * @param key
     * @param value
     * @return
     */
    public boolean set(String key,Object value) {
        boolean result = false;

        try {
            ValueOperations<String, Object> operations = redisTemplate.opsForValue();
            operations.set(key,value);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }


    /**
     * 封装简单的删除操作
     * @param pattern
     */
    public void removePattern(final String pattern) {
        //使用redis的pattern来匹配出一批符合条件的缓存,然后批量进行删除
        Set<Serializable> keys = redisTemplate.keys("pattern");
        if (keys.size() > 0) {
            redisTemplate.delete(keys);
        }
    }
}

测试:

	  @Autowired
    private RedisService service;
   /**
		 * 创建一个RedisService服务,将RedisTemplate注入到类中,
     * 在类中编写一个简单的插入方法,和一个删除方法。
     * 最后在测试方法中调用这个服务中的两个方法
     */
    @Test
    public void testModel() {
        boolean temp = service.set("jack", "jack@163.com");
        System.out.println(temp);
        service.removePattern("jack");
    }
码云地址

https://gitee.com/Tang1314521/redis-mytest.git

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值