前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >小白轻松入门Redis

小白轻松入门Redis

作者头像
AI码真香
发布2022-09-13 17:46:06
5110
发布2022-09-13 17:46:06
举报
文章被收录于专栏:AI码真香
一、了解Redis
1.1、关于NoSQL

NoSQL的全称是Not only SQL,在过去的几年中,NoSQL数据库一度成为高并发、海量数据存储解决方案的代名词,与之相应的产品也呈现出雨后春笋般的生机。然而在众多产品中能够脱颖而出的却屈指可数,如Redis、MongoDB、BerkeleyDB和memcached等内存数据库。

1.2、关于Redis

Redis,中文网站 。典型的NoSQL数据库服务器,它可以作为服务程序独立运行于自己的服务器主机。在很多时候,人们只是将Redis视为Key/Value数据库服务器,然而事实并非如此,在目前的版本中,Redis除了Key/Value之外还支持List、Set、Hash和Ordered Set等数据结构,因此它的用途也更为宽泛。

Redis的特性:速度快、支持很多语言、持久化、多种数据结构、主从复制以及高可用与分布式

二、Redis的安装
2.1、Redis 在CentOS7下的安装

下载、解压以及编译Redis

代码语言:javascript
复制
#安装流程
wget http://download.redis.io/releases/redis-5.0.4.tar.gz
tar xzf redis-5.0.4.tar.gz
cd redis-5.0.4
make
#遇到[adlist.o]Error 127
yum install gcc
#运行Redis
src/redis-server redis.conf
2.2、Redis 在Windows下的安装

很不幸的是,Redis项目不正式支持Windows。 但是,Microsoft开放技术小组开发和维护这个Windows端口针对Win64,目前从网上找到win环境的最新版本是3.2.100,虽然不是最新版本,但本地开发学习足够用啦。下面就来聊下,Win下如何安装Redis。下载地址

下载完成,解压后的文件结构:

双击redis-server.exe,启动redis-server服务:

redis默认启动6379端口,需要保证本地6379端口没被占用!出现此界面表示redis服务已经正常启动了,这时候就可启动redis客户端进行相关操作了。

双击redis-cli.exe,启动redis-cli客户端:

当然,你也可以将redis安装成win系统服务,这样每次就不需要去双击打开客户端服务端啦(推荐)

代码语言:javascript
复制
#提示successful的字样表示成功,服务不能重复安装
#需要进入你安装包解压的路径中,win10注意cmd要以管理员打开
redis-server --service-install redis.windows-service.conf --loglevel verbose
#安装成功后,可以将解压路径配置到环境变量path中去:
C:\Program Files\MZJ\Redis-x64-3.2.100(这是我本地解压的路径,将这个路径配置到环境变量中,下次执行redis-cli就不需要到指定路径了,全局使用方便)

#常用的命令

卸载服务:redis-server --service-uninstall
开启服务:redis-server --service-start
停止服务:redis-server --service-stop

#注意:如果需要修改配置文件信息,可在redis.windows-service.conf文件(非redis.windows.conf)自定义配置信息,因为Redis安装的服务默认加载的是该文件。当然你启动redis-server的时候也可以指定配置文件
2.3、Redis常用的配置选项

常用配置选项:

  • daemonize yes 配置为守护进程,后台启动,默认为no
  • port 6379 修改默认监听端口
  • bind 127.0.0.1 默认只支持本地访问,改行注释掉则允许所有主机访问redis,正式环境不推荐
  • protected-mode no 关闭保护模式
  • requirepass xxxx 配置redis密码,使用时候需要输入:auth xxxx 进行认证,认证成功后才能操作redis
  • logfile 设置日志文件
  • databases 255 设置redis数据库总量,推荐不超过255
  • dir 设置数据文件储存目录
三、Redis命令
3.1、Redis通用命令
代码语言:javascript
复制
查看客户端连接信息:
	info replication
	info memory
ping
   	PONG 表示数据库正常运行
选择数据库:
    select + number (0-15) ,默认提供16个数据库,可以扩展到256(推荐,尽量不要再大)select 0 			表示选择0号数据库,一次类推
   	keys *   查看数据库中所有的key的值;不推荐在生产环境中使用,keys 命令是阻塞的
            keys he*  keys ph? ....
    dbsize  返回是key 的数量
	exists + key 返回 1 表示key 存在
    del +key 表示删除 key 对应的数据
	expire key +时间(单位秒) 设置key 的有效时间
    ttl + key 查看key是否有效 ,返回-2 表示过期
	flushdb 表示清空当前数据库中所有的数据
	flushall 表示删除所有数据库中的所有数据
	redis-cli shutdown 关闭redis服务器(推荐)
	netstat -tulpn | grep redis 与 kill -9 pid
四、Redis数据结构

Redis中支持五种数据结构

  • String 字符串类型(较多)
  • Hash hash类型(Map)
  • List 列表类型
  • Set 集合类型
  • ZSet 有序集合类型
4.1、Redis字符串类型

特点:

  1. String 类型最大存储不超过512mb,单个key - value 不超过100kb,可以是数字、字符串以及json字符串(javaBean)
  2. String类型结构的应用场景:缓存、秒杀、分布式锁(分布式事务的一致性,分布式事务)、配置中心(统一分布式各系统的配置,统一设置读取)、对象序列化(jackson,gson序列化工具)、计数器(用于统计一些数据,保存为字符串数据类型)

常用的指令:

代码语言:javascript
复制
get  key  获取key的值
set  key  value 设置key 的值为value (重复set ,新的值会把旧的值覆盖掉)                      mset hello world java best  一次性设置多个key的值,这里hello 和java作为key
mget hello java 一次性获取多个key的值
del key 删除key的值
incr/decr key 表示key的值自增/自减1 (有点类似mysql 数据库中的主键)
incrby/decrby key num  增或减少指定的num
4.2、Redis Hash类型

特点:

  1. Hash用于存储结构化数据,可以看做是Map
  2. 典型的应用场景:对象的存储(可实现部分字段更新操作)

常用的指令:

代码语言:javascript
复制
redis 中 hash key 的命名规则:对象类型:id:属性
	hget user:1:info age  表示获取hash中key=age的值
    hset user:1:info age 23 设置hash 中age=23 (多次hset同一个值表示覆盖,成功会返回 0)
	hmset user:1:info height 178 birthday 1992-06-26  设置多个key()height birthday
    hmget user:1:info name age height birthday   获取多个值
    hgetall user:1:info 表示一次性获取所有的值
	hdel user:1:info birthday  删除 birthday  的 value值
	hlen  user:1:info   查看有多少个值
	hexists user:1:info name  查看key是否存在 存在返回 1
4.3、Redis List类型

特点:

  1. List列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾(右边)
  2. 一个列表最多可以包含 2的32次方 - 1 个元素(4294967295, 每个列表超过40亿个元素)。

典型的应用场景:时间轴的展示

常用的指令:

代码语言:javascript
复制
List 相关指令
rpush listkey c b a 右侧插入(每一次从右侧插入,就是从列表的尾部添加)
lpush listkey f e d 左侧插入,就是从列表的头部添加
rpop listkey 右侧元素弹出
lpop listkey 左侧元素弹出
llen listkey 获取从航都
lrange listkey 0 2 (表示从左边第一个元素取到第2个元素)
lrange listkey 1 -1 获取子集 从第二个元素开始 都末端所有元素
4.3、Redis Set类型

特点:

  1. Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
  2. Redis 中集合是通过哈希表实现的,所以添加,删除,查找的速度极快。
  3. 集合中最大的成员数为 2的32次方 - 1 (4294967295,每个集合可存储40多亿个成员)。

典型的应用场景:微关系中,共同关注的人sinter ;如随机弹出srandmember(可以设计奖池),抽奖活动(spop)

常用的指令:

代码语言:javascript
复制
sadd key element 添加集合元素
srem key 移除集合中的指定元素
scard user:1:follow 计算集合数量
smembers user:1:follow 获取所有集合元素 不推荐使用
srandmember user:1:follow 3 随机挑选3个参数
spop user:1:follow 随机弹出元素
sdiff set1 set2  差集
	sdiff user:1:follow user:2:follow
sinter set1 set2  交集
    sinter user:1:follow user:2:follow
sunion set1 set2 并集
    sunion user:1:follow user:2:follow
4.3、Redis Zset类型

特点:是String类型的有序集合,集合成员是唯一的,不能出现重复的数据。

典型的应用场景:排行榜

常用的指令:

代码语言:javascript
复制
zadd key score elements 添加集合中的元素
zadd player:rank 1000 ronaldo 900 messi 800 cronaldo 600 kaka
zrem key element 移除
zscore key element 获取数据
zscore player:rank kaka  (元素排名下标是从0开始)
zcard key 元素总数
zrank key 元素总数
zrange key scope withscores 获得排序索引数据
zrange player:rank 0 -1 withscores
zcount key scope 获得排序数据总量
       zcount player:rank 700 901
zrangebyscore key 获得按分数排序元素
       zrangebyscore player:rank 700 901 withscores
五、Redis客户端和使用
5.1、Redis 客户端

windows 环境下 有 RDM 0.9.3版本是最新免费版本,类似数据库(navicate)可视化管理工具文末会提供下载!

java 下客户端 Jedis:

  • Jedis是Java语言开发的Redis客户端工具包,用于Java语言与Redis数据进行交互.
  • Jedis只是对Redis命令的封装,掌握Redis命令便可轻易上手Jedis
  • Jedis遵循RESP协议规范开发,具有良好的通用性与可读性
  • jedis 直连: 简单粗暴,适用于少量连接的场景
  • jedis线程不安全,存在连接泄露的可能

Jedis连接池(JedisPool): 对象预先生成,降低开销,便于连接资源进行监管和控制;使用麻烦,参数较多,规划不合理容易出现问题

5.2、Redis的使用

Jedis直连的使用:

  1. pom.xml文件中添加依赖:
代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.xmlvhy</groupId>
    <artifactId>jedis</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.0.1</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>
  1. 单元测试类编写:
代码语言:javascript
复制
package com.xmlvhy;

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

import java.util.List;
import java.util.Map;

/**
 * @ClassName JedisTest
 * @Description TODO
 * @Author 小莫
 * @Date 2019/04/17 21:57
 * @Version 1.0
 **/
public class JedisTest {

    @Test
    public void testJedis() throws Exception{
        //创建一个redis 通道
        Jedis jedis = new Jedis("127.0.0.1",6379, 1000);

        try {
            //设置登录密码密码
            //jedis.auth("123456");
            //选择第4个数据库,数据库下标从 0  开始
            jedis.select(3);
            jedis.flushDB();//清空第四个数据库
            //jedis.xxx方法名就是命令
            jedis.set("hello","world");
            System.out.println(jedis.get("hello"));
            jedis.mset(new String[]{"a","1","b","2","c","3"});
            List<String> strs = jedis.mget(new String[]{"a", "b", "c"});
            System.out.println(strs);
            System.out.println(jedis.incr("c"));
            Long b = jedis.del("b");
            System.out.println(b);
        } catch (Exception e) {
            throw e;
        }finally {
            //释放连接
            jedis.close();
        }
    }

    @Test
    public void testHash(){
        //创建一个redis 通道
        Jedis jedis = new Jedis("127.0.0.1",6379, 1000);

        try {
            //设置登录密码密码
            //jedis.auth("123456");
            //选择第4个数据库,数据库下标从 0  开始
            jedis.select(3);
            jedis.flushDB();//清空第四个数据库
            //jedis.xxx方法名就是命令
            jedis.hset("user:1:info","name","xiaomo");
            jedis.hset("user:1:info","age","27");
            jedis.hset("user:1:info","sex","男");
            Map<String, String> all = jedis.hgetAll("user:1:info");
            System.out.println(all);
            System.out.println(jedis.hget("user:1:info","name"));
        } catch (Exception e) {
            throw e;
        }finally {
            //释放连接
            jedis.close();
        }
    }
}

Jedis使用连接池jedisPool:

代码语言:javascript
复制
package com.xmlvhy;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * @ClassName JedisTestPool
 * @Description TODO
 * @Author 小莫
 * @Date 2019/04/18 9:30
 * @Version 1.0
 **/
public class JedisTestPool {

    @Test
    public void testJedisPool(){
        //创建一个jedis 池
        GenericObjectPoolConfig config = new JedisPoolConfig();
        //设置连接池中最多允许放100个jedis对象
        config.setMaxTotal(100);
        //设置连接池中允许的最大连接数
        //maxIdle 设置一般跟 maxTotal一致即可
        config.setMaxIdle(50);
        //设置连接池中允许的最小连接数
        config.setMinIdle(10);
        //设置借出连接的时候是否测试有效性 推荐false 提升效率
        config.setTestOnBorrow(false);
        //设置归还连接的时候是否测试有效性 推荐false 提升效率
        config.setTestOnReturn(false);
        //创建时候测试有效性,设置true(注意这个属性设置true的话,如果不是本地连接则会报错,是由于自我保护引起的问题)
        config.setTestOnCreate(true);
        //当连接池内jedis无可用资源的时候,是否等待资源
        config.setBlockWhenExhausted(true);
        //没有获取资源时最长等待时间设置 1 秒,1秒后还没有的话就报错
        config.setMaxWaitMillis(1000);

        JedisPool pool = new JedisPool(config,"127.0.0.1",6379);
        Jedis jedis = null;
        try {
            //从连接池中获取(borrow)一个jedis对象
            jedis = pool.getResource();
            //jedis.auth("123456");
            jedis.set("abc","bb");
            String abc = jedis.get("abc");
            System.out.println(abc);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (jedis != null) {
                //在使用连接池的时候,使用close方法不是关闭。而是归还到连接池中
                jedis.close();
            }
        }

    }
}

Spring 环境下使用JedisPool:

  1. pom.xml中添加相关依赖:
代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.xmlvhy</groupId>
    <artifactId>spring-jedis</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <!--引用 spring-data-redis-->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
            <version>2.1.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>
		<!--单元测试-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.1.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
		<!--日志框架-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-nop</artifactId>
            <version>1.7.2</version>
        </dependency>
		<!--jackson用于序列化和反序列化-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.8</version>
        </dependency>
		<!--封装了javaBean相关的操作-->
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.9.3</version>
        </dependency>
    </dependencies>
</project>
  1. applicationContext.xml配置
代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--连接池配置类-->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal" value="100"/>
        <property name="maxIdle" value="100"/>
        <property name="minIdle" value="10"/>
        <property name="maxWaitMillis" value="1000"/>
        <property name="blockWhenExhausted" value="true"/>
        <property name="testOnBorrow" value="false"/>
        <property name="testOnReturn" value="false"/>
        <property name="testOnCreate" value="false"/>
    </bean>

    <!--sentinel配置核心-->
    <bean id="sentinelConfiguration" class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
        <property name="master">
            <bean class="org.springframework.data.redis.connection.RedisNode">
                <property name="name" value="mymaster"/>
            </bean>
        </property>
        <property name="sentinels">
            <set>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="127.0.0.1"/>
                    <constructor-arg name="port" value="26379"/>
                </bean>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="127.0.0.1"/>
                    <constructor-arg name="port" value="26380"/>
                </bean>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="127.0.0.1"/>
                    <constructor-arg name="port" value="26381"/>
                </bean>
            </set>
        </property>
    </bean>

    <!--配置jedis
        usePool = false 表示jedis直连,true表示使用连接池
    -->
    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:usePool="true" p:hostName="127.0.0.1" p:port="6666" p:database="2" p:poolConfig-ref="poolConfig"/>

    <!--<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:usePool="true" p:database="2" p:poolConfig-ref="poolConfig">-->
        <!--TODO:windows环境下执行提示失败-->
        <!--&lt;!&ndash;整合sentinel配置,通知jedisconnectionFactory 使用sentinel创建jedis连接&ndash;&gt;-->
        <!--<constructor-arg index="0" ref="sentinelConfiguration"/>-->
    <!--</bean>-->

    <!--jedis 核心操作类 redisTemplate 本质上就是jedis封装,在jedis基础上进行了大幅度的简化,并且
    对连接池友好,允许自动回收连接
    在JedisPool 中如果没有调用 close方法可能会出现连接泄露的问题,但在spring-date-redis中则不会
    -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connectionFactory-ref="jedisConnectionFactory">
        <property name="keySerializer">
            <!--设置 StringRedisSerializer 字符串原本序列化进行保存-->
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
        </property>
        <!--设置 值序列化采用原文字符串的序列化方式-->
        <property name="valueSerializer">
            <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
        </property>
        <property name="hashKeySerializer">
            <!--设置 StringRedisSerializer 字符串原本序列化进行保存-->
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
        </property>
        <property name="hashValueSerializer">
            <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
        </property>
    </bean>
</beans>
  1. 单元测试
代码语言:javascript
复制
package com.xmlvhy.springredis;

import com.xmlvhy.entity.User;
import org.apache.commons.beanutils.BeanUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;

/**
 * @ClassName SpringRedisTests
 * @Description TODO
 * @Author 小莫
 * @Date 2019/04/18 10:30
 * @Version 1.0
 **/
@RunWith(SpringJUnit4ClassRunner.class) //启动时候初始化spring ioc 容器
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpringRedisTests {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Test
    public void test() {
        //对string 字符串操作的类
        //默认情况下Spring-data-redis 会采用jdk序列化的方式将所有key value 进行二次序列化
        //这样会导致可读性差,通常我们需要字符串或json的方式来保存对象
        redisTemplate.opsForValue().set("a", "b1111");
        String a = (String) redisTemplate.opsForValue().get("a");
        System.out.println(a);
    }

    //string 序列化
    @Test
    public void testObjectSerializer() {
        User user = new User("u1", "test1");
        User user1 = new User("u2", "test2");

        redisTemplate.opsForValue().set("user:u1", user);
        redisTemplate.opsForValue().set("user:u2", user1);

        //spring data redis 底层提供jackson 进行序列化
    }

    //string 反序列化
    @Test
    public void testObjectDeserializer() {
        //这里注意需要实体类中有一个空的默认构造方法
        User u1 = (User) redisTemplate.opsForValue().get("user:u1");
        System.out.println(u1);
    }

    //hash 序列化
    @Test
    public void testHashSerializer() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        User user = new User("u3", "test3");
        Map<String, String> map = BeanUtils.describe(user);
        //将javaBean 转化为 map
        redisTemplate.opsForHash().putAll("user:m1", map);
    }

    //hash 反序列化
    @Test
    public void testHashDeserializer() throws InvocationTargetException, IllegalAccessException {
        //拿到所有值
        Map map = redisTemplate.opsForHash().entries("user:m1");
        User user = new User();
        BeanUtils.populate(user, map);
        System.out.println(user.getUsername());
    }

    @Test
    public void testList() {
        for (int i = 0; i < 10; i++) {
            User u = new User("u" + i, "p" + i);
            redisTemplate.opsForList().rightPush("VipUserRank", u);
        }
        //下标是从0开始的
        List<Object> list = redisTemplate.opsForList().range("VipUserRank", 1l, 5l);
        System.out.println(list);
    }

    @Test
    //数据库层面的命令要使用 execute 接口回调实现
    public void testFlashdb() {
        redisTemplate.execute(new RedisCallback() {
            @Override
            public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
                redisConnection.flushDb();
                return null;
            }
        });
    }
}
5.3、SpringBoot和Spring Cache

Redis在我们程序中最重要的应用便是缓存,利用内存的高吞吐解决数据查询慢的问题; Spring Cache是Spring生态的一员,用于对主流缓存组件进行一致性集成.通过暴露统一的接口,让我们轻松的使用并进行组件之间的切换。

声明式缓存

  • 声明式缓存通俗来说是采用注解的形式对当前应用的”非侵入式”扩展
  • 声明式缓存是Spring Cache的默认支持. 底层采用Spring AOP技术实现

直接上代码:

  1. pom.xml中添加相关依赖
代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.xmllvhy</groupId>
    <artifactId>spring-cache</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-cache</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.8</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
  1. 主程序入口,SpringCacheApplication 添加 @EnableCaching 注解,表示启用spring cache缓存
  2. application.properties 中配置jedisPool
代码语言:javascript
复制
spring.redis.database=2
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.jedis.pool.max-active=100
spring.redis.jedis.pool.max-idle=100
spring.redis.jedis.pool.min-idle=10
spring.redis.jedis.pool.max-wait=1000ms
  1. RedisCacheConfig 序列化相关配置
代码语言:javascript
复制
package com.xmllvhy.spring.cache.config;

import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.stereotype.Component;

/**
 * @ClassName RedisCacheConfig
 * @Description TODO
 * @Author 小莫
 * @Date 2019/04/18 14:15
 * @Version 1.0
 **/
@Component
public class RedisCacheConfig {
    //@Bean
    //public RedisCacheConfiguration redisCacheConfiguration() {
    //    //加载redis缓存的默认配置
    //    RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
    //    //使用jackson 进行json 序列化,jdk默认序列化是二进制的方式,那样出现乱码不易查看
    //    configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
    //    return configuration;
    //}

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {

        //初始化一个RedisCacheWriter
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);

        //以下这种方式可以序列化,但是如果对集合或者javabean反序列化时候会出错
        //Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);

        RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer());

        RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);
        return new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
    }
}
  1. service类,集成cache相关业务逻辑
代码语言:javascript
复制
package com.xmllvhy.spring.cache.service;

import com.xmllvhy.spring.cache.entity.Emp;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @ClassName EmpService
 * @Description TODO
 * @Author 小莫
 * @Date 2019/04/18 13:58
 * @Version 1.0
 **/
@Service
public class EmpService {
    //对于默认情况下,redis对象的序列化使用的是 jdk序列化,必须要求实体类实现seriliziable 接口
    //cacheable 会将方法的返回值序列化后存储到redis,key就是参数执行的字符串
    //cacheable 的用途就是在执行方法前检查对应的key是否存在,存在则直接从redis中取出来不执行方法中的代码
    //没有对应的key则执行方法代码,并将返回的值序列化保存在缓存中
    //condition 代表条件成立的时候才执行缓存的数据
    @Cacheable(value = "emp",key = "#empno"/*,condition = "#empno == 1000"*/)
    public Emp findByEmpNo(Integer empno){
        System.out.println("执行了findByEmpNo方法:empno" + empno);
        return new Emp(empno,"xiaomo",new Date(),1000f,"研发部");
    }


    //冒号分割
    @Cacheable(value = "emp:rank:salary")
    public List<Emp> getEmpRank(){
        System.out.println("第一次获取数据");
        List list = new ArrayList();
        for(int i =0; i<10;i++){
            list.add(new Emp(i,"emp"+i,new Date(),500+i*100f,"SALES"));
        }
        return list;
    }

    //CachePut 中的代码都会被执行
    //CachePut 作用是不管redis是否存在key,都把返回的数据进行保存(强制更新)
    @CachePut(value = "emp",key = "#emp.empno")
    public Emp create(Emp emp){
        System.out.println("正在创建"+emp.getEmpno()+ " 的员工信息");
        return emp;
    }
    //CachePut 作用是不管redis是否存在key,都把返回的数据进行保存(强制更新)
    //update 也是 cache put 有则更新无则创建
    @CachePut(value = "emp",key = "#emp.empno")
    public Emp update(Emp emp){
        System.out.println("正在更新"+emp.getEmpno()+ " 的员工信息");
        return emp;
    }

    //CacheEvict 从缓存中删除指定key的数据
    @CacheEvict(value = "emp",key = "#empno")
    public void delete(Integer empno){
        System.out.println("正在删除"+ empno + " 的员工信息");
    }
}
  1. 单元测试类
代码语言:javascript
复制
package com.xmllvhy.spring.cache;

import com.xmllvhy.spring.cache.entity.Emp;
import com.xmllvhy.spring.cache.service.EmpService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Date;
import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest //spring boot 中,springboot test 的作用就是在junit启动的时候自动初始化springboot 的ioc容器
public class SpringCacheApplicationTests {

    @Autowired
    private EmpService empService;
    @Test
    public void contextLoads() {

    }
    @Test
    public void findByEmpno(){
        empService.findByEmpNo(1000);
        empService.findByEmpNo(1000);
        empService.findByEmpNo(1000);
        empService.findByEmpNo(1000);
        Emp emp = empService.findByEmpNo(1000);
        System.out.println(emp.getName());
        System.out.println(emp.getBirthday());
    }
    @Test
    public void testEmpRank(){
        List<Emp> list = empService.getEmpRank();
        String name = list.get(list.size() - 1).getName();
        System.out.println(name);
    }
    @Test
    public void testCreate(){
        empService.create(new Emp(1001,"xiaomo",new Date(),1111f,"sales"));
    }
    @Test
    public void testUpdate(){
        empService.create(new Emp(1001,"xiaomo-update",new Date(),1111f,"sales"));
    }
    @Test
    public void testDelete(){
        empService.delete(1000);
    }
}
六、提供Redis一个工具类(jedisPool)
  1. 初始化配置 redisTemplate 和 cacheManager
代码语言:javascript
复制
package com.zhly.sso.auth.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @ClassName RedisCacheConfig
 * @Description TODO
 * @Author 小莫
 * @Date 2019/04/18 14:15
 * @Version 1.0
 **/
@Configuration
@EnableCaching
public class CacheRedisConfig {

    /**
     *功能描述: 配置 redis 缓存管理
     * @Author 小莫
     * @Date 17:44 2019/04/20
     * @Param [connectionFactory]
     * @return org.springframework.cache.CacheManager
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        //初始化一个RedisCacheWriter
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
        //以下这种方式可以序列化,但是如果对集合或者javabean反序列化时候会出错
        //Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);

        RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer());

        RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);
        return new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
    }

    /**
     *功能描述: 配置 redis 操作类 redisTemplate
     * @Author 小莫
     * @Date 17:45 2019/04/20
     * @Param [factory]
     * @return org.springframework.data.redis.core.RedisTemplate<java.lang.String,java.lang.Object>
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        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;
    }
}
  1. 封装 redisTemplate 对五种数据类型的操作(RedisUtil.java)
代码语言:javascript
复制
package com.zhly.sso.auth.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName RedisUtil
 * @Description TODO redis 工具类
 * 这里直接通过注入 redisTemplate 来封装redis的相关操作
 * @Author 小莫
 * @Date 2019/04/20 17:46
 * @Version 1.0
 **/
@Component
public class RedisUtil {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 指定缓存失效时间
     *
     * @param key  键
     * @param time 时间(秒)
     * @return
     */
    public boolean expire(String key, long time) {
        try {
            if (time > 0) {
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据key 获取过期时间
     *
     * @param key 键 不能为null
     * @return 时间(秒) 返回0代表为永久有效
     */
    public long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * 判断key是否存在
     *
     * @param key 键
     * @return true 存在 false不存在
     */
    public boolean hasKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除缓存
     *
     * @param key 可以传一个值 或多个
     */
    public void del(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete(CollectionUtils.arrayToList(key));
            }
        }
    }
    // ============================String=============================

    /**
     * 普通缓存获取
     *
     * @param key 键
     * @return 值
     */
    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    /**
     * 普通缓存放入
     *
     * @param key   键
     * @param value 值
     * @return true成功 false失败
     */
    public boolean set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 普通缓存放入并设置时间
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期
     * @return true成功 false 失败
     */
    public boolean set(String key, Object value, long time) {
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            } else {
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 递增
     *
     * @param key   键
     * @param delta 要增加几(大于0)
     * @return
     */
    public long incr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递增因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 递减
     *
     * @param key   键
     * @param delta 要减少几(小于0)
     * @return
     */
    public long decr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递减因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, -delta);
    }
    // ================================Map=================================

    /**
     * HashGet
     *
     * @param key  键 不能为null
     * @param item 项 不能为null
     * @return 值
     */
    public Object hget(String key, String item) {
        return redisTemplate.opsForHash().get(key, item);
    }

    /**
     * 获取hashKey对应的所有键值
     *
     * @param key 键
     * @return 对应的多个键值
     */
    public Map<Object, Object> hmget(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * HashSet
     *
     * @param key 键
     * @param map 对应多个键值
     * @return true 成功 false 失败
     */
    public boolean hmset(String key, Map<String, Object> map) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * HashSet 并设置时间
     *
     * @param key  键
     * @param map  对应多个键值
     * @param time 时间(秒)
     * @return true成功 false失败
     */
    public boolean hmset(String key, Map<String, Object> map, long time) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @return true 成功 false失败
     */
    public boolean hset(String key, String item, Object value) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @param time  时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
     * @return true 成功 false失败
     */
    public boolean hset(String key, String item, Object value, long time) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除hash表中的值
     *
     * @param key  键 不能为null
     * @param item 项 可以使多个 不能为null
     */
    public void hdel(String key, Object... item) {
        redisTemplate.opsForHash().delete(key, item);
    }

    /**
     * 判断hash表中是否有该项的值
     *
     * @param key  键 不能为null
     * @param item 项 不能为null
     * @return true 存在 false不存在
     */
    public boolean hHasKey(String key, String item) {
        return redisTemplate.opsForHash().hasKey(key, item);
    }

    /**
     * hash递增 如果不存在,就会创建一个 并把新增后的值返回
     *
     * @param key  键
     * @param item 项
     * @param by   要增加几(大于0)
     * @return
     */
    public double hincr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, by);
    }

    /**
     * hash递减
     *
     * @param key  键
     * @param item 项
     * @param by   要减少记(小于0)
     * @return
     */
    public double hdecr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, -by);
    }
    // ============================set=============================

    /**
     * 根据key获取Set中的所有值
     *
     * @param key 键
     * @return
     */
    public Set<Object> sGet(String key) {
        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据value从一个set中查询,是否存在
     *
     * @param key   键
     * @param value 值
     * @return true 存在 false不存在
     */
    public boolean sHasKey(String key, Object value) {
        try {
            return redisTemplate.opsForSet().isMember(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将数据放入set缓存
     *
     * @param key    键
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long sSet(String key, Object... values) {
        try {
            return redisTemplate.opsForSet().add(key, values);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 将set数据放入缓存
     *
     * @param key    键
     * @param time   时间(秒)
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long sSetAndTime(String key, long time, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().add(key, values);
            if (time > 0)
                expire(key, time);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 获取set缓存的长度
     *
     * @param key 键
     * @return
     */
    public long sGetSetSize(String key) {
        try {
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 移除值为value的
     *
     * @param key    键
     * @param values 值 可以是多个
     * @return 移除的个数
     */
    public long setRemove(String key, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
    // ===============================list=================================

    /**
     * 获取list缓存的内容
     *
     * @param key   键
     * @param start 开始
     * @param end   结束 0 到 -1代表所有值
     * @return
     */
    public List<Object> lGet(String key, long start, long end) {
        try {
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取list缓存的长度
     *
     * @param key 键
     * @return
     */
    public long lGetListSize(String key) {
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 通过索引 获取list中的值
     *
     * @param key   键
     * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
     * @return
     */
    public Object lGetIndex(String key, long index) {
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @return
     */
    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒)
     * @return
     */
    public boolean lSet(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒)
     * @return
     */
    public boolean lSet(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒)
     * @return
     */
    public boolean lSet(String key, List<Object> value, long time) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据索引修改list中的某条数据
     *
     * @param key   键
     * @param index 索引
     * @param value 值
     * @return
     */
    public boolean lUpdateIndex(String key, long index, Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 移除N个值为value
     *
     * @param key   键
     * @param count 移除多少个
     * @param value 值
     * @return 移除的个数
     */
    public long lRemove(String key, long count, Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove(key, count, value);
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
}

以上就是我学习 Redis 的一些总结!

参考学习

代码语言:javascript
复制
来自老齐的IT加油站课程学习
	官网:http://www.itlaoqi.com/
https://www.cnblogs.com/zeng1994/p/03303c805731afc9aa9c60dbbd32a323.html

本篇文章涉及的 源码下载

本文作者: AI码真香

本文标题: 小白轻松入门Redis

本文网址: https://www.xmlvhy.com/article/65.html

版权说明: 自由转载-非商用-非衍生-保持署名 署名-非商业性使用4.0 国际 (CC BY-NC 4.0)

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、了解Redis
    • 1.1、关于NoSQL
      • 1.2、关于Redis
      • 二、Redis的安装
        • 2.1、Redis 在CentOS7下的安装
          • 2.2、Redis 在Windows下的安装
            • 2.3、Redis常用的配置选项
            • 三、Redis命令
              • 3.1、Redis通用命令
              • 四、Redis数据结构
                • 4.1、Redis字符串类型
                  • 4.2、Redis Hash类型
                    • 4.3、Redis List类型
                      • 4.3、Redis Set类型
                        • 4.3、Redis Zset类型
                        • 五、Redis客户端和使用
                          • 5.1、Redis 客户端
                            • 5.2、Redis的使用
                              • 5.3、SpringBoot和Spring Cache
                              • 六、提供Redis一个工具类(jedisPool)
                              相关产品与服务
                              云数据库 Redis
                              腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
                              领券
                              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档