Set类型
在Redis中,我们可以将set类型看作为没有排序的字符集合。和List一样,我们也可以在该类型的数据上执行添加、删除或判断某一元素是否存在等操作。和List不同的是,Set集合中不允许出现重复的元素。
和List类型相比,Set类型在功能上还存在着一个非常重要的特性,即在服务器端完成多个sets之间的聚合计算操作,如union、intersections和differences。由于这些操作均在服务端完成,因此效率极高,而且也节省了大量的网络IO开销。
set可包含的最大元素数量是4294967295。
- sadd key member1 member2... 添加元素
- srem key member1 member2... 删除元素
- smembers key 获取元素
- scard key获取set长度
- srandmember key 随机返回set中的一个成员,可以在后面指定成员数量
- sismember key member 判断set中是否包含某个元素,返回1表示存在,返回0表示不存在
- spop set 弹出值
- smove set set2 5 把set中的指定元素,移动到set2中
以下命令是set运算命令
- sdiff key key2 差集运算,显示前面集合和后面集合的不同之处
- sinter key1 key2 key3 交集运算
- sunion key1 key2 key3 并集运算
- sdiffstore destination key key2 差集运算,把结果保存在destination 中
- sinterstore destination key key2 交集运算,把结果保存在destination 中
- sunionstore destination key key2 并集运算,把结果保存在destination 中
sinter set1 set2 set3 --> {c}sunion set1 set2 set3 --> {a,b,c,d,e}
sdiff set1 set2 set3 --> {a}
set应用场景:抽奖小程序
set应用场景:随机展示
通常,app首页的展示区域有限,但是又不能总是展示固定的内容,一种做法是先确定一批需要展示的内容,再从中随机获取。如图所示,酷狗音乐K歌擂台赛当日的打擂歌曲共29首,首页随机展示5首;昨日打擂金曲共200首,首页随机展示30首。
ZSet类型
zset是有序set集合, 是专门用来做数据的排序的
-
zadd key score value 注意是score在前,value在后,也可以用这个命令修改score
-
zscore key member 返回指定成员的分数
-
zrem key member 删除集合中指定的成员
-
zrange key start end [withscores] 范围查询
-
zrevrange key start stop 获取倒序结果, 添加WITHSCORES可以显示分数
-
zremrangebyscore key (min (max 按分数范围删除元素
-
zrangebyscore key min max [withscores] [limit start size] 在指定的分数范围之内进行排序
-
zremrangebyrank key start stop 按排名范围删除元素,就是顺序
-
zincrby key increment member 给指定的成员增加指定的分数,返回增加以后的分数
-
zcount key min max 获取分数在[min, max]之间的成员的个数
-
zrank key member 返回成员在集合中的排名,从0开始
-
zrevrank key member 反转排名
-
zcard key 获取集合数据总量 集合运算操作
-
zinterstore destination number key [key ...] 将所有的额分数累加
-
zunionstore destination number key [key ...] 将所有的分数累加
zset应用场景:排行榜
- 点击新闻zincrby hotNews:20200226 1 3003:全面复工
- 展示当日排行前十zrevrange hotNews:20200226 0 10 withscores
- 七日搜索榜单zunionstore hostNews:20200220-20200226 7 hotNews20200220 ... hotNews20200226
- 展示七日排行前十zrevrange hostNews:20200220-20200226 0 10 withscores
启动redis的客户端的时候在后面添加 --raw
Java客户端Jedis
Java连接redis
在官方网站里有一些Java的客户端,有Jedis、SpringData Redis、Lettuce等。下面我们就重点学习下jedis。
首先开放服务器6379端口,然后在redis.conf配置文件中,设置密码requirepass foobared,然后注释掉bind 127.0.0.1这行配置,重启redis服务。
创建maven项目,且在项目中导入jedis依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.2.0</version>
</dependency>
redis中有哪些命令,jedis中就有哪些方法
基本使用
@Test
public void testJedisConn(){
Jedis jedis = new Jedis("192.168.174.130",6379);
jedis.auth("foobared");
System.out.println(jedis.ping());
System.out.println(jedis.set("k1", "abcd"));
System.out.println(jedis.strlen("k1"));
jedis.close();
}
使用连接池
@Test
public void testJedisPool(){
//jedis连接池配置
JedisPoolConfig config = new JedisPoolConfig();
//进行配置
config.setMaxTotal(50);
config.setMaxIdle(10);
//数据库连接池
JedisPool jedisPool = new JedisPool("192.168.174.130",6379);
Jedis jedis = jedisPool.getResource();
jedis.auth("foobared");
System.out.println(jedis.ping());
}
编写util类
package com.woniu.util;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class JedisUtils {
private static JedisPool jedisPool;
static{
JedisPoolConfig config = new JedisPoolConfig();
//进行配置
config.setMaxTotal(50);
config.setMaxIdle(10);
//数据库连接池
jedisPool = new JedisPool("192.168.174.130",6379);
}
public static Jedis getJedisConn(){
Jedis jedis = jedisPool.getResource();
jedis.auth("foobared");
return jedis;
}
}
测试util类
@Test
public void testJedisUtils(){
System.out.println(JedisUtils.getJedisConn().ping());
}
redis持久化之RDB
所谓持久化,就是将数据保存到永久性存储介质上,在特定的时间将保存的数据进行恢复的机制。
*为什么要进行持久化*
防止数据的意外丢失,保证数据是安全的。
*证明redis持久化的存在*
redis为了追求高效的读写速度,默认情况下所有的增删改,都是在内存中进行的,断电以后redis的数据会丢失,丢失的数据是保存在内存中的数据。但是我们会发现,在关闭了redis服务器之后,再次启动redis服务,之前的key还在!也就是说,redis是有持久化功能的!
redis中持久化的方式,有两种
1. *RDB*(存快照)
2. *AOF*(存日志)
*RDB启动方式:save命令*
每当执行save命令的时候,都会立即进行一次快照保存!
save指令相关配置
dbfilename dump.rdb说明:设置本地数据库文件名,默认值为dump.rdb
经验:通常设置为dump-*端口号*.rdb
dir说明:
设置存储rdb文件的路径经验:通常设置为存储空间较大的目录中
rdbcompression yes说明:设置存储至rdb文件时会否压缩数据经验:通常默认为开启状态,如果设置为no,可以节省cpu运行时间,但存储文件会很大
rdbchecksum yes说明:设置是否进行rdb文件格式校验,该校验过程写文件和读文件的过程中都会进行经验:通常默认为开启状态,如果设置为no,可以节约读写的时间,但会有数据损坏风险
*rdb数据的恢复时机*
redis启动时。
*save持久化数据的缺点*
我们都知道redis是单线程模型,那么在数据量过大的情况下执行save指令,save指令的执行时间就会很长,这样排在save指令之后的其他指令只能长时间地阻塞,这样会拉低服务器的性能!
所以线上环境中,不建议使用save命令。
*RDB启动方式:bgsave命令*
针对于save命令的缺点,需要使用*bgsave*命令来在后台进行rdb数据快照备份。
注意:bgsave命令是针对save阻塞问题做的优化,redis内容所有涉及到rdb的操作都采用bgsave,save命令可以放弃使用了。
*RDB启动方式:自动执行*
配置save second changes作用在限定时间内(second),至少有指定个数(changes)的key发生变化时,就自动持久化 在redis.conf文件中有以下配置:save 900 1 表示每900秒(15分钟)至少有1个key发生变化,则dump内存快照 save 300 10表示每300秒(5分钟)至少有10个key发生变化,则dump内存快照 save 60 10000表示每60秒(1分钟)至少有1000个key发生变化,则dump内存快照
注意
-
save自动执行,执行的是bgsave命令。
-
在执行FLUSHALL命令的时候,无论是否满足条件,都会立即生成一个新的空的dump.rdb来覆盖以前的dump.rdb。另外多说一句:FLUSHALL很危险,工作中不要使用。
*RDB优点*
RDB是一个紧凑压缩的二进制文件,存储效率较高
RDB内部存储的是redis在某个时间点的数据快照,非常适合于数据备份,全量复制的场景
RDB恢复数据的速度要比AOF快很多
应用:将RDB文件单独拷贝到远程机器中,用于灾难恢复
*RDB缺点*
RDB方式无论是执行指令还是利用配置,都无法做到实时持久化,有丢失最新数据的风险
bgsave指令每次运行都要fork一个子进程,要牺牲掉一些性能
redis的众多版本中未进行RDB文件格式的统一,在各个版本的服务之间会有不兼容的现象
RDB是基于快照的思想,每次读写都是全部数据,当数据量巨大时,效率非常低
redis持久化之AOF
*AOF*
AOF(append only file)持久化:以独立日志的方式记录每次*写命令*(也就是记录数据产生的过程),重启时再重新执行AOF文件中的命令,达到数据恢复的目的。
*AOF写数据的三种策略*
always 每次写入操作均同步到AOF文件中,*数据零误差,性能较低*
everysec 每秒同步到AOF中,*数据准确性较高,性能较高*,最多丢失1秒的数据
no 由系统控制何时将命令同步到AOF文件,*整个过程不可控*。
*AOF功能开启*
appendonly yes|no 是否开启AOF功能
appendfsync always|everysec|no AOF写数据的策略
appendfilename filename 建议配置为appendonly-端口号.aof
*AOF写数据遇到的问题*
针对于右边的6个命令,如果aof都统统保存下来,是没有必要的! AOF提供了一个功能:AOF重写来解决这个问题!
*AOF重写*
随着命令不断写入AOF文件,AOF文件会越来越大,为了解决这个问题,redis引入了AOF重写机制来压缩AOF文件体积。AOF文件重写是将Redis进程内的数据转化为写命令同步更新到AOF文件的过程。简单地说就是将对同一个数据的若干条命令执合并为最终结果所对应的那一条命令!这样既降低了磁盘占用量,提高磁盘利用率,又减少了数据恢复时所用的时间!
*AOF重写规则*
-
进程内已超时的数据不再写入文件。
-
忽略无效指令,重写时使用进程内数据直接生成,这样新的AOF文件只保留最终数据的写入命令。
-
对同一数据的多条写命令合并为一条命令
如lpush list1 a、lpush list1 b可以合并为lpush list a b
*AOF重写启动方式*
- 手动重写:bgrewriteaof
- 自动重写触发条件设置auto-aof-rewrite-min-size size 自动触发AOF重写的文件最小大小auto-aof-rewrite-percentage percentage 自动触发AOF重写的百分比
- 自动重写触发比对参数,以下两个参数通过运行info persistence来获取具体信息aof_current_size (当前大小)aof_base_size (上次重写后的大小)
- 自动重写触发条件,以下两个条件一个成立就会触发aof的自动重写(可以只配置一种)aof_current_size > auto-aof-rewrite-min-size(aof_current_size - aof_base_size) / aof_base_size > auto-aof-rewrite-percentage percentage
*AOF重写流程*
*基于everysec开启重写*
*RDB与AOF的区别*
*RDB与AOF如何抉择?*
-
如果要求对整体数据特别敏感,建议使用AOF
AOF持久化策略采用everyseconds的话,每秒备份一次写命令。该策略使redis保持很好的性能,当出现问题时,最多丢失1秒内的数据。
-
如果对某时段内的数据特别敏感,建议使用RDB
由开发或者运维人员手工使用RDB维护,可以具有针对性的对于某时段内的数据进行灾难备份,且恢复速度较快。所以阶段数据持久化通常使用RDB。
如果同时开启RDB和AOF时,redis优先使用AOF来恢复数据。
redis事务
redis虽然是单线程,但是也会有事务的问题。
multi 开始事务
添加命令到队列
使用exec执行队列的命令
此时出现两个问题:
1、如果队列中有错误命令,则整个队列的命令都不执行。
2、如果队列没有错误命令,但是执行时出现异常,那么不影响其他命令的执行。(程序自行编码完成回滚处理。)
需要对数据进行监控,加watch,类似于乐观锁。
watch num
multi
set k1 v1
incr num
在exec之前,如果有其他客户对num进行了操作,则这个事务整体都不执行
exec
使用jedis操作事务
public void test(){
Jedis jedis = new Jedis("192.768.174.134", 7369);
Transaction transaction = jedis.multi();
transaction.set("k1", "asdf");
transaction.set("num", 1);
transaction.incr("num");
transaction.exec();
}
redis主从复制(集群)
当今互联网的“三高”架构:高并发、高性能、高可用。
*单机redis的问题*
单机redis的问题很明,如果当前的redis服务宕机了,则系统的整个缓存系统瘫痪,导致灾难性的后果。另外单机redis也有内存容量瓶颈。
*redis主从复制*
一个master可以有多个slave,一个slave只能有一个master
*redis的主从复制的作用*
-
读写分离,提高服务读写的负载能力。
-
提高了整个redis服务的可用性。
*搭建redis主从复制*
- 准备3台虚拟机,分别装好redis
-
开放每台服务器的6379端口
-
编辑redis master服务的配置文件redis.conf
daemonize yes requirepass foobared bind 0.0.0.0 logfile redis.log
-
编辑redis slave服务的配置文件redis.conf
daemonize yes masterauth foobared requirepass foobared bind 0.0.0.0 logfile redis.log
-
分别启动3个redis服务,且使用redis客户端连接redis服务,键入以下命令
info replication
会发现此时3个redis服务的role都是master
-
在从机中使用以下命令,完成主从复制
slaveof 192.168.1.51 6379
*redis主从复制流程*
- slave服务器配置master的连接信息(slaveof指令)
- slave连接上master,向master发送psync2指令
- master判断是否为全量复制(第一次连接),如果是全量复制,则进入下一步;否则进行增量复制(第8步)。
- master启动一个后台线程,执行bgsave生成一份RDB快照文件,同时将bgsave执行的过程中所接收到的写命令缓存到复制缓冲区中。
- RDB文件生成完毕之后,master会将RDB发送给slave。
- slave收到RDB文件之后,清空自己的旧数据,然后持久化到本地磁盘,再从本地磁盘加载到内存中。
- 当salve恢复了RDB文件中的数据到内存后,会发送命令告诉master RDB恢复已经完成。
- master会将内存中缓存的写命令发送给slave,slave也会执行这些命令。
- 如果slave node开启了AOF,那么会立即执行BGREWRITEAOF,重写AOF
我们已经知道了主从复制的流程了,而这些流程被划分为3个阶段。
*主从复制的三个阶段*
-
连接阶段,由slave去主动连接master,双方互相记住对方的套接字。
-
数据同步阶段,由master把目前的所有数据一次性同步给slave(使用RDB)
-
命令传播阶段,master把后期收到的写命令,发送给slave
步骤:
1、生成多个centos虚拟机(克隆)
2、开放6379端口
3、redis配置
master
reqirepass foobared
bind 0.0.0.0
logfile redis.log
slave
reqirepass foobared
bind 0.0.0.0
logfile redis.log
masterauth foobared #连接主机时的密码
4、启动服务
如果服务已经运行
pkill redis-server
如果没有启动服务
./redis-server redis.conf
5、查看当前redis服务的信息
info replication
所有的主机都是master
6、在要作为slave的服务器中运行命令连接master
slaveof master'ip port
7、再查看master服务的信息
8、查看slave服务的信息
9、测试
在master中添加数据
set k1 v1
在slave中读取该数据
get k1
测试:
-
当master宕机以后,slave会怎么样? --> 原地待命,等待master
-
当slave宕机以后,再次重启会怎么样? --> 脱离master,自立成为master
redis哨兵模式(解决主机宕机的问题)
问题描述:当master宕机以后,所有的slave是无法正常工作的,这时需要从所有的slave中选择一个作为新的master,并通知所有的其他slave连接该新的master,这个过程完全可以由人工完成。也可以使用哨兵模式!
*哨兵是什么*
哨兵也是一个redis服务,只是不提供数据服务
*哨兵模式搭建*
- 再准备1个虚拟机(192.168.1.54),安装好redis(安装过程以及安装目录和之前一样)
- 将redis解压目录下的哨兵配置文件sentinel.conf考到/usr/local/redis/目录下
- 查看sentinel.conf文件的内容
-
将sentinel.conf的内容写入sentinel-26379.conf文件中
cat sentinel.conf | grep -v "^#" | grep -v "^$" > sentinel-26379.conf
编辑sentinel-26379.conf的内容
哨兵监听的端口,记得开放端口port 26379
哨兵存放数据的位置dir .
下面标红的的数字1表示只要由1个哨兵认为master宕机了,就能确认maser确实宕机# 了,毕竟现在只有一个哨兵,还没有为哨兵做集群sentinel monitor mymaster 192.168.1.51 6379 1
设定master在多长时间(毫秒)没响应,就认为master宕机了sentinel down-after-milliseconds mymaster 30000
哨兵连接master也需要通过master的认证sentinel auth-pass mymaster foobared
-
在哨兵模式下,任何机器都有可能成为master,所以修改3个redis的配置为以下同一个配置
daemonize yes
masterauth foobared <-- 关键是为每个reids服务加上这一行,保证能够互相访问*
requirepass foobared
bind 0.0.0.0
logfile redis.log
-
先保证主从复制环境搭建好,最后再启动哨兵
- 此时关闭master,等待一段时间,会发先哨兵选出了一个新的master,并且通知其他slave归顺新主
至此哨兵环境已经搭建成功
*下面搭建哨兵集群的环境*
-
为了方便,我们就不再搞出更多的虚拟机了,而是在一个虚拟机上,做出3个哨兵分别监听26379、26380、26381端口,做一个哨兵的伪集群。
哨兵监听的端口,记得开放端口port 26379 | 26380 | 26381
哨兵存放数据的位置dir .# 下面标红的的数字2表示只要由1个哨兵认为master宕机了,就能确认maser确实宕机# 了,毕竟现在只有一个哨兵,还没有为哨兵做集群sentinel monitor mymaster 192.168.1.51 6379 *2*
设定master在多长时间(毫秒)没响应,就认为master宕机了sentinel down-after-milliseconds mymaster 30000
哨兵连接master也需要通过master的认证*sentinel auth-pass mymaster foobared*
-
重新搭建redis的主从复制环境:一主二从。
-
然后启动3个客户端分别在192.168.1.54上启动3个监听不同端口的哨兵。
./bin/redis-server sentinel-26379.conf --sentinel
./bin/redis-server sentinel-26380.conf --sentinel
./bin/redis-server sentinel-26381.conf --sentinel
*切记退出哨兵的时候,不要直接ctrl+c!! 应该由客户端发送shutdown命令来正常关闭哨兵,否则下次无法正常启动哨兵。*
- 关闭192.168.1.51的redis服务,过一会,哨兵集群会重新选出一个新主
- 使用客户端连接到一个哨兵服务
- 退出26379哨兵(shutdown),其他哨兵也能感知
23679哨兵的控制台
23680哨兵的控制台
23681哨兵的控制台
- 此时再关闭新主192.168.1.53
- 会发现,剩下的2个哨兵能继续重新选举一个新主
- 再让26379哨兵回来,可以看出26379回来后,获得到了最新的信息
*哨兵工作原理*
-
监控:同步信息
-
通知:保持数据互通
-
故障转移:
(1) 发现问题
(2) 从哨兵中选出负责人
(3) 负责人选出master
(4) 新master上位,其他slave切换master,原master也臣服于新master
缓存雪崩
-
在一个*较短*的时间内,缓存中*较多*的key过期
-
恰恰就是在较短的时间内,有很多请求访问过期key而未命中,让请求到达数据库
-
数据库同时接收大量的请求,而无法及时处理,导致数据库崩溃
-
redis得不到数据库的响应,无法释放链接,导致redis集群崩溃
-
应用服务器无法及时得到redis的响应,同时新的请求不断到来,应用服务器崩溃
-
同时重启应用服务、redis服务、数据库服务,重启以后,海量请求呼啸而至,缓存中是空的,继续崩溃。
*缓存雪崩解决方案*
-
对key的过期时间进行分类错峰:均匀分布key的过期时间,避免大量key在较短时间内集中过期。
-
超热key永不过期
-
使用mq削峰,让呼啸而至的请求排队。(用户体验不好)
-
构建多级缓存架构:nginx缓存 + redis缓存 + ehcahe缓存
-
优化mysql查询,增加查询速度
-
灾难预警机制:监控redis服务性能指标
-
限流、降级:短时间内牺牲一些客户体验,限制一部分请求访问,降低应用服务器压力,待服务恢复时再逐步恢复正常功能
缓存击穿
*缓存击穿*
-
redis中*某一个**高热*key过期
-
同时海量请求都在访问这同一个*高**热*key,均未命中
-
海量请求呼啸而至,奔向数据库,数据库崩溃
*缓存击穿解决方案*
-
在特殊节日前,预先设定阶段性高热key的过期时间
-
现场调整,对自然流量所推出来的新的高热key,延长其过期时间或者设置其为永久key
设置二级缓存,在二级缓存中设置相同的高热key,但是过期时间不同。
缓存穿透
*缓存穿透*
-
redis中出现大量未命中的请求
-
出现非正常URL的访问,这些访问由于没有走正常的应用,所以可以故意访问一类不可能存在的key,这些key不在缓存中,数据库中也没有。
-
后续出现大量以上请求,很可能是懂技术的人在对服务器进行攻击!
*缓存穿透解决方案*
-
缓存null:对查询结果为null的数据也进行缓存,设定较短的过期时间
-
白名单策略
(1) 提前预热各种分类数据id对应的bitmaps,id作为bitmaps的offset,当加载正常数据时就放行,加载异常数据时直接拦截(效率偏低)
(2) 使用布隆过滤器(不是100%命中非法key)
*对比缓存击穿和缓存穿透*
缓存击穿,访问的是一个存在的高热key,突然过期,导致数据库服务器压力激增
缓存穿透,访问的是一个压根不存在的key,导致数据库服务器压力激增。
Spring-Data-Redis
1.添加依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
2.编写redis的配置文件或者JavaConfig
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 配置连接池 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="50"></property>
<property name="maxIdle" value="5"></property>
</bean>
<!-- Spring整合Jedis(也就是redis) -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="192.168.174.132"></property>
<property name="port" value="6379"></property>
<property name="password" value="foobared"></property>
<!-- 注入连接池 -->
<property name="poolConfig" ref="jedisPoolConfig"></property>
</bean>
<!--配置字符串序列化 -->
<bean id="stringSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"></bean>
<!-- 配置RedisTemplate -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory"></property>
<property name="keySerializer" ref="stringSerializer"></property>
<property name="valueSerializer" ref="stringSerializer"></property>
</bean>
</beans>
<bean id="stringSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"></bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="jedisConnectionFactory"></property> <property name="keySerializer" ref="stringSerializer"></property> 需要对key和value进行序列化配置,否则存入redis的key和value有特殊字符. <property name="valueSerializer" ref="stringSerializer"></property> </bean>
3.编写测试类
package com.woniu.springbootredis;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-redis.xml")
public class AppTest {
//是redis配置文件注入的
@Autowired
private RedisTemplate<String, Object> rt;
@Test
public void test() throws Exception {
//string类型
ValueOperations<String, Object> string = rt.opsForValue();
string.set("goods2","apple");
System.out.println(string.get("goods2"));
//list类型
ListOperations<String, Object> list = rt.opsForList();
//hash类型
HashOperations<String, Object, Object> hash = rt.opsForHash();
//set类型
SetOperations<String, Object> set = rt.opsForSet();
//ZSet类型
ZSetOperations<String, Object> zSet = rt.opsForZSet();
}
}
标签:AOF,redis,哨兵,master,key,RDB,Redis2
From: https://www.cnblogs.com/chaliang/p/18062798