导图社区 Redis
Redis是现在最受欢迎的NoSQL数据库之一,Redis是一个使用ANSI C编写的开源、包含多种数据结构、支持网络、基于内存、可选持久性的键值对存储数据库。Redis 的应用场景包括:缓存系统(“热点”数据:高频读、低频写)、计数器、消息队列系统、排行榜、社交网络和实时系统。综合来说,用缓存,主要有两个用途:高性能、高并发。
编辑于2022-05-07 10:48:24Linux是一套不用付费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。专业性强,主要用于服务器,嵌入式系统,移 动终端系统等
Thymeleaf提供了一个用于整合Spring MVC的可选模块,在应用开发中,你可以使用Thymeleaf来完全代替JSP或其他模板引擎,如Velocity、FreeMarker等。Thymeleaf的主要目标在于提供一种可被浏览器正确显示的、格式良好的模板创建方式,因此也可以用作静态建模。你可以使用它创建经过验证的XML与HTML模板。相对于编写逻辑或代码,开发者只需将标签属性添加到模板中即可。
这是一篇关于Nginx的思维导图,主要内容有1.目标、2.Nginx的安装与启动、3.Nginx静态网站部署、4.Nginx反向代理与负载均衡。
社区模板帮助中心,点此进入>>
Linux是一套不用付费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。专业性强,主要用于服务器,嵌入式系统,移 动终端系统等
Thymeleaf提供了一个用于整合Spring MVC的可选模块,在应用开发中,你可以使用Thymeleaf来完全代替JSP或其他模板引擎,如Velocity、FreeMarker等。Thymeleaf的主要目标在于提供一种可被浏览器正确显示的、格式良好的模板创建方式,因此也可以用作静态建模。你可以使用它创建经过验证的XML与HTML模板。相对于编写逻辑或代码,开发者只需将标签属性添加到模板中即可。
这是一篇关于Nginx的思维导图,主要内容有1.目标、2.Nginx的安装与启动、3.Nginx静态网站部署、4.Nginx反向代理与负载均衡。
redis
概述
非关系型数据库 1.数据之间没有联系 2.数据保存在内存
关系型数据库 1.数据间有关系 2.数据保存在硬盘
键值对的方式存储在内存中
下载安装官网:https://redis.io 中文网:http://www.redis.net.cn/
redis.windows.conf:配置文件
redis-cli.exe:redis的客户端
redis-server.exe:redis服务器端
redis数据结构和持久化
数据结构
字符串类型String
set key value
get key
del key
哈希类型 hash
hset key field value
hget key field
hgetall key
hdel key field
列表类型 list 有序有重复
lpush key value
rpush key value
lrange key start end
集合类型 set
sadd key value
获取set集合中所有元素 smembers myset
删除set集合中的某个元素 srem key value
有序集合类型 sortedset 不允许重复元素,且元素有顺序 每个元素都会关联一个double类型的分数,通过分数来排序
zadd key score value
zrange key start end [withscores]
zrem key value
通用命令
查询所有的键 keys *
获取键对应的value的类型 type key
删除指定的key value del key
持久化
概念:redis是一个内存数据库,一旦计算机重启,或者关闭,数据会丢失,所以我们需要持久化数据到硬盘上
RDB
默认方式.rdb
编辑redis.windwos.conf文件
save 900 1 表示900秒内至少有一次key发生了改变
重启服务器并指定配置文件名称。redis目录命令行 redis-2.8.9>redis-server.exe redis.windows.conf
AOF
默认关闭
编辑redis.windwos.conf文件
appendonly yes
# appendfsync always : 每一次操作都进行持久化 appendfsync everysec : 每隔一秒进行一次持久化 # appendfsync no : 不进行持久化
Jedis
概念: 一款java操作redis数据库的工具
使用步骤
导入jar包
Jedis jedis = new Jedis("localhost",6379); jedis.set("username","zhangsan"); jedis.close();
操作数据结构
操作字符串
jedis.set(键,值)
jedis.get(键)
jedis.setex(key,seconds,value); 设置保留时间,一般用于验证码的保存
操作hash
jedis.hset(key,field,value)
jedis.hget(key,field)
获取Map中所有的数据jedis.hgetAll(key) map集合 keySet遍历
列表类型List(有序有重复)
jedis.lpush(rpush)(key,value1,value2,value3)
jedis.lpop(rpop)(key) 弹出
jedis.lrange(key,0,-1) 范围获取
结果遍历
普通for,增强for,迭代器
set(无序无重复)
jedis.sadd(key,value1,value2)
Set<String> sets = jedis.smembers(key)
结果遍历
转数组,增强for,迭代器
有序集合类型 sortedset
jedis.zadd(key,3,value);
jedis.zrange(key,0,-1)
jedis连接池使用
直接使用
创建JedisPool连接池对象
getResource()方法获取Jedis连接
使用jedis并归还连接
连接池工具类
1. Redis缓存相关问题
1.1 缓存穿透
缓存穿透是指查询一个数据库一定不存在的数据。
我们以前正常的使用Redis缓存的流程大致是:
1、数据查询首先进行缓存查
2、如果数据存在则直接返回缓存数据
3、如果数据不存在,就对数据库进行查询,并把查询到的数据放进缓存
4、如果数据库查询数据为空,则不放进缓存
例如我们的数据表中主键是自增产生的,所有的主键值都大于0。此时如果用户传入的参数为-1,会是怎么样?这个-1,就是一定不存在的对象。程序就会每次都去查询数据库,而每次查询都是空,每次又都不会进行缓存。假如有人恶意攻击,就可以利用这个漏洞,对数据库造成压力,甚至压垮我们的数据库。
为了防止有人利用这个漏洞恶意攻击我们的数据库,我们可以采取如下措施:
如果从数据库查询的对象为空,也放入缓存,key为用户提交过来的主键值,value为null,只是设定的缓存过期时间较短,比如设置为60秒。这样下次用户再根据这个key查询redis缓存就可以查询到值了(当然值为null),从而保护我们的数据库免遭攻击
1.2 缓存雪崩
缓存雪崩,是指在某一个时间段,缓存集中过期失效。在缓存集中失效的这个时间段对数据的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰
为了避免缓存雪崩的发生,我们可以将缓存的数据设置不同的失效时间,这样就可以避免缓存数据在某个时间段集中失效。例如对于热门的数据(访问频率高的数据)可以缓存的时间长一些,对于冷门的数据可以缓存的时间段一些。甚至对于一些特别热门的数据可以设置永不过期。
1.3 缓存击穿
缓存击穿,是指一个key非常热点(例如双十一期间进行抢购的商品数据),在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求到数据库上,就像在一个屏障上凿开了一个洞
我们同样可以将这些热点数据设置永不过期就可以解决缓存击穿的问题了。
2. Redis集群方案
单台Redis服务性能不足的问题。这就需要使用到Redis的集群了。Redis集群有多种方案,下面分别进行讲解。
2.1 主从复制Replication
redis支持主从复制的模式。
在主从复制模式下Redis节点分为两种角色:主节点(也称为master)和从节点(也称为slave)。这种模式集群是由一个主节点和多个从节点构成。
原则:Master会将数据同步到slave,而slave不会将数据同步到master。Slave启动时会连接master来同步数据。
这是一个典型的分布式读写分离模型。我们可以利用master来处理写操作,slave提供读操作。这样可以有效减少单个机器的并发访问数量。
要实现主从复制这种模式非常简单,主节点不用做任何修改,直接启动服务即可。从节点需要修改redis.conf配置文件,加入配置:slaveof <主节点ip地址> <主节点端口号>,例如master的ip地址为192.168.200.129,端口号为6379,那么slave只需要在redis.conf文件中配置slaveof 192.168.200.129 6379即可。
分别连接主节点和从节点,测试发现主节点的写操作,从节点立刻就能看到相同的数据。但是在从节点进行写操作,提示 READONLY You can't write against a read only slave 不能写数据到从节点。
现在我们就可以通过这种方式配置多个从节点进行读操作,主节点进行写操作,实现读写分离。
2.2 哨兵sentinel
我们现在已经给Redis实现了主从复制,可将主节点数据同步给从节点,实现了读写分离,提高Redis的性能。但是现在还存在一个问题,就是在主从复制这种模式下只有一个主节点,一旦主节点宕机,就无法再进行写操作了。也就是说主从复制这种模式没有实现高可用。那么什么是高可用呢?如何实现高可用呢?
项目中用到的redis知识
Spirngboot整合Redis
项目
智慧商城
依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.4.RELEASE</version> </parent>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
配置
spring: redis: host: ip地址 port: 端口
例如
spring: redis: host: 192.168.211.132 port: 6379
操作数据结构
操作redis的所有类型
模板
@Autowired private RedisTemplate redisTemplate;
redisTemplate.方法;
删除
Delete given key.根据给的key删除
模板
@Autowired private RedisTemplate redisTemplate;
redisTemplate.delete(键);
例如
项目
智慧商城
类
方法
add
子主题
@Autowired private RedisTemplate redisTemplate;
redisTemplate.delete("Cart_"+username);
操作字符串
图示
模板
//tring-focused extension of RedisTemplate. @Autowired private StringRedisTemplate stringRedisTemplate;
stringRedisTemplate.boundValueOps(键).方法;
增加
添加redis字符串的键和值
模板
//tring-focused extension of RedisTemplate. @Autowired private StringRedisTemplate stringRedisTemplate;
stringRedisTemplate.boundValueOps(键).set(值);
例如
项目
智慧商城
类
方法
onEventCustomUpdate
子主题
//tring-focused extension of RedisTemplate. @Autowired private StringRedisTemplate stringRedisTemplate;
stringRedisTemplate.boundValueOps("content_" + categoryId).set(JSON.toJSONString(data));
删除
获得
获得redis字符串的值
模板
//tring-focused extension of RedisTemplate. @Autowired private StringRedisTemplate stringRedisTemplate;
stringRedisTemplate.boundValueOps(键).get();
例如
项目
智慧商城
类
方法
findByCategoryIdAndRedis
子主题
//tring-focused extension of RedisTemplate. @Autowired private StringRedisTemplate stringRedisTemplate;
String s = stringRedisTemplate.boundValueOps("content_" + categoryId).get();
操作hash
图示
模板
@Autowired private RedisTemplate redisTemplate;
redisTemplate.boundHashOps(键).方法;
添加
添加redishash的key,field和value
模板
@Autowired private RedisTemplate redisTemplate;
redisTemplate.boundHashOps(键).put(字段,值);
例如
项目
智慧商城
类
方法
add
子主题
@Autowired private RedisTemplate redisTemplate;
redisTemplate.boundHashOps("Cart_"+username).put(skuId,orderItem);
删除
Delete given hash keys at the bound key.(根据key和fields,删除redishash的key绑定的一个或者多个键值对)
模板
@Autowired private RedisTemplate redisTemplate;
redisTemplate.boundHashOps(键).delete(字段们);
例如
项目
智慧商城
类
方法
add
子主题
@Autowired private RedisTemplate redisTemplate;
redisTemplate.boundHashOps("Cart_"+username).delete(skuId);
获得
Get entry set (values) of hash at the bound key.获得绑定指定key的values
模板
@Autowired private RedisTemplate redisTemplate;
redisTemplate.boundHashOps(键).values();
例如
项目
智慧商城
类
方法
list
子主题
@Autowired private RedisTemplate redisTemplate;
redisTemplate.boundHashOps("Cart_"+username).values();
Get key set (fields) of hash at the bound key.获得绑定指定key的fields
模板
@Autowired private RedisTemplate redisTemplate;
redisTemplate.boundHashOps(键).keys();
例如
项目
类
方法
子主题
@Autowired private RedisTemplate redisTemplate;
redisTemplate.boundHashOps("Cart_"+username).keys();
Get size of hash at the bound key.获得绑定指定key的键值对的数量
模板
@Autowired private RedisTemplate redisTemplate;
redisTemplate.boundHashOps(键).size();
例如
项目
智慧商城
类
方法
add
子主题
@Autowired private RedisTemplate redisTemplate;
Long size = redisTemplate.boundHashOps("Cart_" + username).size();
Get value for given key from the hash at the bound key.获得绑定指定key和field的value
模板
@Autowired private RedisTemplate redisTemplate;
redisTemplate.boundHashOps(键).get(字段);
例如
项目
类
方法
子主题
@Autowired private RedisTemplate redisTemplate;
redisTemplate.boundHashOps("Cart_" + username).get(skuId);
列表类型List(有序有重复)
set(无序无重复)
有序集合类型 sortedset
jedis
项目
智慧医院
依赖
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>
配置
<?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" xmlns:context="http://www.springframework.org/schema/context" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--Jedis连接池的相关配置--> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxTotal"> <value>200</value> </property> <property name="maxIdle"> <value>50</value> </property> <property name="testOnBorrow" value="true"/> <property name="testOnReturn" value="true"/> </bean> <bean id="jedisPool" class="redis.clients.jedis.JedisPool"> <constructor-arg name="poolConfig" ref="jedisPoolConfig" /> <constructor-arg name="host" value="127.0.0.1" /> <constructor-arg name="port" value="6379" type="int" /> <constructor-arg name="timeout" value="30000" type="int" /> </bean> </beans>
操作数据结构
操作字符串
操作hash
列表类型List(有序有重复)
set(无序无重复)
图示
添加
Add the specified member to the set value stored at key. If member is already a member of the set no operation is performed. If key does not exist a new set with the specified member as sole member is created. If the key exists but does not hold a set value an error is returned. Time complexity O(1)
模板
// 使用JedisPool操作Redis服务 @Autowired private JedisPool jedisPool;
jedisPool.getResource().sadd(键,值);
例如
// 使用JedisPool操作Redis服务 @Autowired private JedisPool jedisPool;
// 用户上传图片后,将文件名存入Redis的set集合,集合名称为setmealPicResources jedisPool.getResource().sadd(RedisConstant.SETMEAL_PIC_RESOURCES,fileName);
删除
Remove the specified member from the set value stored at key. If member was not a member of the set no operation is performed. If key does not hold a set value an error is returned. Time complexity O(1)
删除1个值
模板
// 使用JedisPool操作Redis服务 @Autowired private JedisPool jedisPool;
// 从Redis的setmealPicResources集合,删除垃圾图片的名称 jedisPool.getResource().srem(键, 值);
例如
// 使用JedisPool操作Redis服务 @Autowired private JedisPool jedisPool;
// 从Redis的setmealPicResources集合,删除垃圾图片的名称 jedisPool.getResource().srem(RedisConstant.SETMEAL_PIC_RESOURCES, pictureName);
获得
返回存储在 key 的集合值的所有成员(元素)Return all the members (elements) of the set value stored at key.
public Set<String> smembers(final String key)
模板
// 使用JedisPool操作Redis服务 @Autowired private JedisPool jedisPool;
Set<String> set = jedisPool.getResource().smembers(键);
例如
// 使用JedisPool操作Redis服务 @Autowired private JedisPool jedisPool;
// 返回存储在 key 的集合值的所有成员(元素) Set<String> set = jedisPool.getResource().smembers(setName);
根据Redis中保存的两个set集合进行差值计算,获得集合
Return the difference between the Set stored at key1 and all the Sets key2, ..., keyN Example: key1 = [x, a, b, c] key2 = [c] key3 = [a, d] SDIFF key1,key2,key3 => [x, b]
模板
// 使用JedisPool操作Redis服务 @Autowired private JedisPool jedisPool;
// 根据Redis中保存的两个set集合进行差值计算,获得垃圾图片名称集合 Set<String> set = jedisPool .getResource() .sdiff(键1, 键2);
例如
// 使用JedisPool操作Redis服务 @Autowired private JedisPool jedisPool;
// 根据Redis中保存的两个set集合进行差值计算,获得垃圾图片名称集合 Set<String> set = jedisPool .getResource() .sdiff(RedisConstant.SETMEAL_PIC_RESOURCES, RedisConstant.SETMEAL_PIC_DB_RESOURCES);
有序集合类型 sortedset