Spring Boot整合

使用SpringData连接Redis

创建一个我们的springboot项目,选中我们的NOSQL里面的Redis

然后我们就会发现我们的Reids依赖关系

<!--        操作Redis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
他的底层依赖是<dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-redis</artifactId><version>2.4.1</version><scope>compile</scope></dependency>

在SpringBoot2.x之后,我们的jedis被替换成了lettuce

<dependency><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId><version>6.0.1.RELEASE</version><scope>compile</scope>
</dependency>
底层<dependency><groupId>io.netty</groupId><artifactId>netty-common</artifactId><version>4.1.53.Final</version><scope>compile</scope></dependency>

jedis:采用的直连,多个线程操作的话 是不安全的,如果想要避免不安全的问题,要使用我们的jedis poll连接池!类似BIO

lettuce:采用netty,实例可以在多个线程中进行共享,不存在线程不安全的情况!可以减少线程数量,更新NIO模式

@Configuration(proxyBeanMethods = false
)
@ConditionalOnClass({RedisOperations.class})
@EnableConfigurationProperties({RedisProperties.class})
//默认是{Lettuce生效后面我们详细讲解
@Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})
public class RedisAutoConfiguration {public RedisAutoConfiguration() {}@Bean@ConditionalOnMissingBean(name = {"redisTemplate"})//我们可以自己定义一个redisTemplate来替换@ConditionalOnSingleCandidate(RedisConnectionFactory.class)public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {   //默认的RedisTemplate没有过多的设置,redis对象都是需要序列化的//两个泛型都是Object类型,我们需要强制类型转换<String,Object>RedisTemplate<Object, Object> template = new RedisTemplate();template.setConnectionFactory(redisConnectionFactory);return template;}@Bean@ConditionalOnMissingBean@ConditionalOnSingleCandidate(RedisConnectionFactory.class)//为乐方便String类型生出了这个Beanpublic StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {StringRedisTemplate template = new StringRedisTemplate();template.setConnectionFactory(redisConnectionFactory);return template;}
}
spring.redis.host=192.168.1.99
server.redis.port=6379

测试

@SpringBootTest
class RedisSpringbootApplicationTests {@Autowiredprivate RedisTemplate redisTemplate;@Testvoid contextLoads() {//opsForValue   操作字符串类似String//opsForList 操作List//opsForSet 操作Set等等等等//除了基本的操作,我们常用的方法都可以直接用redisTemplate调API
//获取reids的链接对象
//        RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
//        connection.flushAll();
//        connection.flushDb();redisTemplate.opsForValue().set("mykey","王花花");System.out.println(redisTemplate.opsForValue().get("mykey"));}}
java测试结果王花花

但是我们的redis显示的是

127.0.0.1:6379> keys *
1) "\xac\xed\x00\x05t\x00\x05mykey"

我们后面可以用序列化来解决这个问题

//RedisTemplate里面的源码
//这就是我们的默认序列化配置
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer keySerializer = null;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer valueSerializer = null;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer hashKeySerializer = null;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer hashValueSerializer = null;//默认的序列化方式是JDK序列化,我们希望要用JSON来序列化
if (defaultSerializer == null) {defaultSerializer = new JdkSerializationRedisSerializer(classLoader != null ? classLoader : this.getClass().getClassLoader());}
//我们就需要自己配置我们的类

自定义RedisTemplate

简单测试(对象不序列化)

    @Testpublic void test() throws JsonProcessingException {//真是开发一般使用JSON来传递对象User user = new User("涛涛", 3);
//        String jsonUser = new ObjectMapper().writeValueAsString(user);使用这种方式就直接传递进去了redisTemplate.opsForValue().set("user",user);System.out.println(redisTemplate.opsForValue().get("user"));}
org.springframework.data.redis.serializer.SerializationException: Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer;
意思就是我们没有序列化,不能进行传输,直接传递对象会报错误
@Component
@AllArgsConstructor
@NoArgsConstructor
@Data
public class User implements Serializable {private String name;private Integer age;
}
当我们的pojo类进行了序列化,在运行就会成功User(name=涛涛, age=3)
127.0.0.1:6379> keys *
1) "\xac\xed\x00\x05t\x00\x04user"
也存进来了

序列化方式

我们自己的RedisTeplate模板

package com.wang.redis.config;import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnection;
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;/*** @author 王....华* @version 1.0* @date 2020/11/29 17:47* @Description TODO* @pojectname wang-redis*/
@Configuration
public class ReidsConfig {//编写我们的redisTemplate@Bean@SuppressWarnings("all")public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){//为了方便,泛型规定为String,Object类型RedisTemplate<String,Object> template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory);//序列化 json解析任意对象Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);//使用ObjectMapper转义ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);//String的序列化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;}
}

注意我们的注入redisTeplate一定要跳到我们的配置中

运行我们的测试类

User(name=涛涛, age=3)

我们的redis显示

127.0.0.1:6379> keys *

  1. “user”

不使用原生命令,使用自定义RedisUtils

package com.wang.redis.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.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;@Component
public final class RedisUtil {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;// =============================common============================/*** 指定缓存失效时间* @param key  键* @param time 时间(秒)*/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 可以传一个值 或多个*/@SuppressWarnings("unchecked")public void del(String... key) {if (key != null && key.length > 0) {if (key.length == 1) {redisTemplate.delete(key[0]);} else {redisTemplate.delete((Collection<String>) 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)*/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)*/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*/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 对应多个键值*/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)*/public double hincr(String key, String item, double by) {return redisTemplate.opsForHash().increment(key, item, by);}/*** hash递减** @param key  键* @param item 项* @param by   要减少记(小于0)*/public double hdecr(String key, String item, double by) {return redisTemplate.opsForHash().increment(key, item, -by);}// ============================set=============================/*** 根据key获取Set中的所有值* @param key 键*/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 键*/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代表所有值*/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 键*/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倒数第二个元素,依次类推*/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 值*/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  时间(秒)*/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 值* @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;}}}

测试我们疯转的工具类

@Autowired
private RedisUtil redisUtil;
@Test
public void test1(){redisUtil.set("name","kuangshen");System.out.println(redisUtil.get("name"));
}
kuangshen127.0.0.1:6379> keys *
1) "user"
2) "name"
127.0.0.1:6379> get name
"\"kuangshen\""

Redis.cong详解

启动的时候就是通过配置文件来启动的

单位

配置文件对unit单位不区分大小写

包含

多个配置文件可以在这配置进来

网络

bind 127.0.0.1   #绑定ip   不注释掉代表只能在本机访问
protected-mode yes      #保护模式
prot 6379       #端口号

通用配置GENERAL

daemonize yes        #默认是no    yes代表以守护进程的方式运行
pidfile /var/run/redis_6379.pid     #如果以后台方式运行,我们就需要指定一个pid进程文件#日志级别
# Specify the server verbosity level.
# This can be one of:
# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)生产环境使用
# warning (only very important / critical messages are logged)
loglevel notice
logfile ""        #文件名  后面我们会改
databases 16    #数据库数量,默认是16个
always-show-logo yes        #是否显示logo图标 默认开启

快照SNAPSHOTTING

持久化,在规定的时间内,执行了多少操作则会持久到文件 .rdb .aof

Reids是内存数据库,没有持久化秘书局断电即失去

#   save ""
#如果900s内,如果至少有 1 个key进行修改,我们就进行持久化操作
save 900 1
#如果300s内,如果至少有 10 个key进行修改,我们就进行持久化操作
save 300 10、
#如果60s内,如果至少有 10000 个key进行修改,我们就进行持久化操作
save 60 10000
#我们之后可以设置自己的持久化规则!#持久化出错后是否还会继续工作        默认是继续工作的
stop-writes-on-bgsave-error yes#是否压缩我们的 rdb 文件,需要消耗我们的cpu资源
rdbcompression yes#保存 rdb 文件的时候,是否开启进行错误的检查校验
rdbchecksum yes# rdb 文件保存的目录
dir ./

复制REPLICATION

后面我们主从复制会详细讲到

安全SECURITY

#查看密码
127.0.0.1:6379> config get requirepass
1) "requirepass"
2) ""     #默认为空的
#配置文件设置
# requirepass foobareds
requirepass 123456
# Command renaming (DEPRECATED).
#命令设置
127.0.0.1:6379> CONFIG SET requirepass "123456"#设置redis密码
OK
127.0.0.1:6379> CONFIG get requirepass   #获取密码
1) "requirepass"
2) "123456"
127.0.0.1:6379> auth 123456      #使用密码登录
OK
127.0.0.1:6379> ping
PONG

客户端限制CLIENTS

扩展了解

# maxclients 10000       #默认最大客户端连接数量
# maxmemory <bytes>       #设置Redis的最大内存容量
#内存满了处理的策略
# maxmemory-policy noeviction#移除一些过期的key。。。。。#报错#。。。。1、volatile-lru:只对设置了过期时间的key进行LRU(默认值) 2、allkeys-lru : 删除lru算法的key   3、volatile-random:随机删除即将过期key   4、allkeys-random:随机删除   5、volatile-ttl : 删除即将过期的   6、noeviction : 永不过期,返回错误

APPEND ONLY MODE模式 AOF配置

#默认不开启AOF模式,默认是开启RDB方式持久化的,在大部分情况下,rdb够用
appendonly no   #持久化文件的名字
appendfilename "appendonly.aof"# appendfsync always   #每次修改都会同步,速度比较慢
#每秒执行一次sync,可能会丢掉这一秒的数据
appendfsync everysec
#不同步,这个时候操作系统自己同步数据,速度最快
# appendfsync no

Redis持久化

为什么Redis要做持久化?

因为Reids是内存数据库,如果不将内存中的数据状态保存到磁盘中,一旦服务器退出,服务器的数据库状态也会消失,所以需要做持久化

RDB

(Redis DataBase)

什么是RDB

默认采用的RDB方式持久化,一般不需要修改

指定的时间间隔内内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里。
Redis会单独创建( fork ) 一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何I0操作的。这就确保了极高的性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后- -次持久化后的数据可能丢失。

rdb保存的文件是dump.rdb文件

# The filename where to dump the DB
dbfilename dump.rdb

测试

修改了配置文件
save 60 5
127.0.0.1:6379> save
OK
127.0.0.1:6379> clear
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k2 v2
OK
127.0.0.1:6379> set k3 v3
OK
127.0.0.1:6379> set k4 v4
OK
127.0.0.1:6379> set k5 v5
OK

触发机制

1.save的规则满足的情况下,会自动触发rdb规则

2.执行flushall命令,也会出发我们的rdb规则

3.退出redis,也会产生我们的rdb文件

被焚毁自动生成一个dump.rdb

如何恢复rdb文件

只需要将rdb文件放在我们的redis启动目录就可以,redis启动的时候会自动检查durm.rdb恢复其中的数据

127.0.0.1:6379> CONFIG GET dir
1) "dir"
2) "/data"[root@bogon data]# ls
appendonly.aof  dump.rdb

优缺点

优点:

适合大规模的数据恢复!!

如果对数据的完整性要求不高!

缺点:

需要一定的时间间隔进行操作!如果redis以外宕机,这个最后一次修改的数据就没有了

狂神说Redis笔记三相关推荐

  1. 狂神说Redis笔记

    以下是狂神Redis笔记,个人觉得总结的很好,故收藏一下,日后再总结一下自己的笔记 ⭐学习时间2022.1.4-2022.1.6 一.Nosql概述 为什么使用Nosql 1.单机Mysql时代 90 ...

  2. 狂神redis笔记_狂神说redis笔记(三)

    八.Redis.conf 容量单位不区分大小写,G和GB有区别 可以使用 include 组合多个配置问题 网络配置 日志 # 日志 # Specify the server verbosity le ...

  3. 狂神说 redis 笔记

    Nosql概述 为什么要学Nosql 我们先在处于大数据时代,大数据一般的数据库无法进行分析处理了!2006 Hadoop 压力一定会越来越大,适者生存!一定要逼着自己学习,这是在这个社会生存的唯一法 ...

  4. 狂神redis笔记_狂神说redis笔记(一)

    一.Nosql概述 1.单机Mysql时代 90年代,一个网站的访问量一般不会太大,单个数据库完全够用.随着用户增多,网站出现以下问题: 数据量增加到一定程度,单机数据库就放不下了 数据的索引(B+ ...

  5. Redis笔记(狂神说)

    搭配狂神说 Redis视频一起学习 狂神视频 一.Nosql概述 为什么使用Nosql 1.单机Mysql时代 90年代,一个网站的访问量一般不会太大,单个数据库完全够用.随着用户增多,网站出现以下问 ...

  6. 两万字的Redis笔记!

    声明:所有内容均来自B站<狂神说Java系列课程>一个宝藏男孩,强烈推荐! 视频地址:https://www.bilibili.com/video/BV1S54y1R7SB 笔者也是基于视 ...

  7. 【Redis笔记】缓存穿透与缓存击穿以及应对方法

    [Redis笔记]缓存穿透与缓存击穿以及应对方法 一.缓存穿透 1. 缓存穿透概念 2. 缓存穿透解决方法 示例代码 二.缓存击穿 1. 缓存击穿概念 2. 缓存击穿解决方法 方法一:互斥锁 示例代码 ...

  8. 【大厂面试】面试官看了赞不绝口的Redis笔记

    文章目录 一.Redis简介 二.Redis API的使用和理解 (一)通用命令 (二)单线程架构 (三)数据结构和内部编码 (四)字符串 (五)hash (字典) (六)列表 (七)Set集合 (八 ...

  9. 兄弟连NoSQL视频教程 redis笔记

    兄弟连NoSQL视频教程 redis笔记 ================================课程目录====================================== 01.N ...

  10. 黑马Redis笔记高级篇 | 多级缓存

    黑马Redis笔记高级篇 | 多级缓存(黑马教程云服务器踩坑记录) 1.JVM进程缓存(tomcat服务内部) 1.1 导入商品案例 1.2 初识Caffeine 1.3 实现进程缓存 2.Lua语法 ...

最新文章

  1. 六步使用ICallbackEventHandler实现无刷新回调
  2. 讲你肯定能懂的机器学习多维极值求解
  3. 2021年最后几天,使用SSM实现网上购物商城系统
  4. 鸿蒙系统手机还会出吗,华为最强手机即将到来,可能还有华为鸿蒙系统加入!你期待吗?...
  5. IntelliJ IDEA 2017 注册方法
  6. 银行加速“去房地产化”
  7. Segmentation fault到底是何方妖孽
  8. win10+tensorflow faster-RCNN 训练自己的数据集
  9. h2 mysql 兼容_H2内存数据库对sql语句的支持问题 sql放到mysql数据库中能跑
  10. 大理石在哪儿 (Where is the Marble?,UVa 10474)
  11. [vue] 说说你对keep-alive的理解是什么?
  12. 大象喝水(信息学奥赛一本通-T1032)
  13. MySQL(25)---- ALTER命令
  14. 深挖前端 JavaScript 知识点 —— 史上最全面、最详细的 Cookie 总结
  15. Jquery跨域调用(JSONP)遇到error问题的解决
  16. 多模态语义分析_学术竞赛 | 冠军方案分享2020科大讯飞AI开发者大赛多模态情感分析赛道...
  17. java 四舍六入五成双
  18. wex5 发布apk以及更新
  19. mysql 无法启动 0xc000007b_「应用程序无法正常启动0xc000007b」正确解决 应用程序无法正常启动(0xc000007b)的问题 - seo实验室...
  20. 基于STM32F1的6位QS-30辉光钟

热门文章

  1. 四川大专计算机专业排行,四川排名前三中等职业技术学院专业排行
  2. SQL:postgresql中,将geometry转换为geojson数据
  3. TimeSpan asp.net中时间的运算
  4. 基于图像的相机定位/SLAM分类
  5. 前端复习笔记(三)——JavaScript和JQuery
  6. “鬼才”论文致谢刷屏!感谢我导“似导非导”的指导...
  7. 洛谷 P1725 简单DP单调队列优化
  8. 两个辅助指针变量挖字符串
  9. react 属性与状态 学习笔记
  10. 数据持久化基础知识——属性列表