Redis 是一个基于 内存 的 key-value 结构数据库。
Redis是一个开源的内存中的数据结构存储系统,可以用作:数据库、缓存和消息中间件。
NoSQL = Not Only Sql, 泛指非关系型数据库,一类数据库,不是特指某一种数据库
关系型数据库RDBMS:MySQL、Oracle、DB2、SQLServer
非关系型数据库NoSQL:Redis、Mongo DB、MemCached
Redis应用场景:缓存热点数据、任务队列、消息队列、分布式锁(解决并发式操作问题)
Redis安装:
Linux安装Redis:
Windows安装Redis:
直接解压即可使用,解压后目录结构如下:
Linux服务启动与停止:
Linux中Redis服务启动,可以进入src目录,然后使用redis-server,默认端口号为6379
复制一个标签窗口,cd /usr/local/redis-4.0.0/src
redis-cli :默认连接本地redis服务
keys * 连接服务
Ctrl + C 停止Redis服务
修改redis的配置:vi redis.conf
输入/ 搜索dae, 找到daemonize 改no 为 yes :wq 退出
设置为后台运行:src/redis-server ./redis.conf
Windows服务启动与停止:
redis 服务默认没有开启密码校验,在redis-4.0.0文件夹下:
1. 从 redis.conf 中 找requirepass,将其注释去掉,并设置一个密码 123456
2. ps -ef | grep redis 将进程杀掉kill -9 xxxxx
3. 然后重新启动:src/redis-server ./redis.conf
4. src/redis-cli -h localhost -p 6379 (p后面是端口号)
5. keys * 会报错 然后输入 auth + 密码 或者第4步骤后边跟上 -a password
修改配置文件,使得redis可以被远程连接
按住shift点右键,将命令行窗口打开:
在powershell中输入 .\redis-cli.exe -h 192.168.153.128 -p 6379 -a 123456
如果显示 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。
firewall-cmd --zone=public --add-port=6379/tcp --permanent
systemctl restart firewalld
Redis存储的是key-value结构的数据,其中key是字符串类型,value有5中常用的数据类型:
Redis 字符串(String)_redis教程
先打开redis-server.ext,再打开redis-cli.exe,然后在redis-cli.ext中运行以下语句:
set key value |
设置指定key的值 |
get key |
获取指定key的值 |
setex key seconds value |
设置指定key的值,并将通过key获取对应的value值的过期时间设为seconds秒,例如手机验证码 |
setnx key value |
只有在key不存在时设置key的值(即一次赋值之后再也不能再赋值),例如分布式锁 |
hset key field value |
将hash表key中的字段field的值设为value |
hget key field |
获取存储在哈希表中指定字段的值 |
hdel key field |
删除存储在哈希表中的指定字段,可以删除多个字段 |
hkeys key |
获取哈希表中所有字段 |
hvals key |
获取哈希表中所有值 |
hgetall key |
获取在哈希表中指定key的所有字段和值 |
lpush key value1 [value2] |
将一个或多个值插入到列表头部 |
lrange key start stop |
获取列表指定范围内的元素,stop:-1 表示到最后 |
drop key |
移除并获取列表最后一个元素 |
llen key |
获取列表长度 |
brpop key1 [key2] timeout |
移出并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。实现任务队列 |
sadd key member1 [member2] |
向集合添加一个或多个成员 |
smembers key |
返回集合中的所有成员 |
scard key |
获取集合的成员数 |
sinter key1 [key2] |
返回给定所有集合的交集 |
sunion key1 [key2] |
返回所有给定集合的并集 |
sdiff key1 [key2] |
返回给定所有集合的差集 |
srem key member1 [member2] |
移除集合中一个或多个成员 |
zadd key score1 member1 [score2 member2] |
向有序集合添加一个或多个成员,或者更新已经存在成员的分数 |
zrange key start stop [withscores] |
通过索引区间返回有序集合中指定区间内的成员 |
zincrby key increment member |
有序集合中对指定成员的分数加上增量increment |
zrem key member [member ... ] |
移除有序集合中的一个或多个成员 |
keys pattern |
查找所有符合给定模式(pattern)的key,pattern多为* |
exists key |
检查给定key是否存在,存在返回1,不存在返回0 |
type key |
返回key所存储的值的类型,以上5种Redis数据类型中的一种 |
ttl key |
返回给定key的剩余生存时间(TTL,time to live),以秒为单位 |
del key |
该命令用于在key存在时删除key |
Redis的java客户端很多:Jedis、Lettuce、Redisson
Spring对Redis客户端进行了整合,提供了Spring Data Redis,在Spring Boot项目中还提供了对应的Starter,即pring-boot-starter-data-redis
Jedis的maven坐标:
redis.clients
jedis
3.2.0
使用Jedis操作Redis的步骤:① 获取连接 ② 执行操作 ③ 关闭连接
@Test
public void testRedis(){
// ① 获取连接
Jedis jedis = new Jedis("localhost", 6379); //类似于jdbc的connection
// ② 执行操作
jedis.set("username", "xiaoming"); //和redis的命令一样
// ③ 关闭连接
jedis.close();
}
打开两个exe服务,运行以上test,在服务中执行get username,即可获得属性值“xiaoming"
@Test
public void testRedis(){
Jedis jedis = new Jedis("localhost", 6379); //类似于jdbc的connection
jedis.set("username", "xiaoming"); //和redis的命令一样
String value = jedis.get("username");
System.out.println(value);
jedis.hset("China", "province", "hebei");
String hget = jedis.hget("China", "province");
System.out.println(hget);
Set keys = jedis.keys("*"); //等价于keys *
for (String key : keys) {
System.out.println(key);
}
jedis.close();
}
在springboot项目中,可以使用spring data redis来简化redis操作,maven坐标:
org.springframework.boot
spring-boot-starter-data-redis
spring data redis中提供了一个高度封装的类:RedisTemplate,针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口,具体分类如下:
ValueOperations |
简单K-V操作 |
SetOperations |
set类型数据操作 |
ZSetOperations |
zset类型数据操作 |
HashOperations |
针对map类型的数据操作 |
ListOperations |
针对list类型的数据操作 |
application.properties配置文件中配置
spring.application.name=jedis
spring.redis.host=localhost //IP
spring.redis.port=6379 //端口号
#spring.redis.password=123456 //密码
spring.redis.database=0 //0号数据库 在redis-cli.exe中切换数据库:select 2 切换到2号数据库
spring.redis.jedis.pool.max-active=8
spring.redis.jedis.pool.max-wait=1ms
spring.redis.jedis.pool.max-idle=4
spring.redis.jedis.pool.min-idle=0
测试类中:
@SpringBootTest
//@RunWith(SpringRunner.class)
public class JedisApplicationTests {
@Resource
private RedisTemplate redisTemplate;
@Test
public void testString(){
ValueOperations valueOperations = redisTemplate.opsForValue();
valueOperations.set("city123", "shanghai");
}
}
得到的结果:
得到的是序列化的结果,要将前缀需要去掉,需要写一个配置类:
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public RedisTemplate
数据类型操作:
// 操作String类型的数据
@Test
public void testString(){
ValueOperations valueOperations = redisTemplate.opsForValue();
valueOperations.set("city555", "shanghai");
String city555 = (String) valueOperations.get("city555"); //获取值
System.out.println(city555);
redisTemplate.opsForValue().set("key111", "value111", 10, TimeUnit.SECONDS); //设置过期时间
Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("city555", "南京"); //key不存在时给key设置值
System.out.println(aBoolean);
}
// 操作hash类型的数据
@Test
public void hashTest(){
HashOperations hashOperations = redisTemplate.opsForHash();
// 存值
hashOperations.put("002", "name", "xiaoming");
hashOperations.put("002", "age", "23");
hashOperations.put("002", "addr", "shanghai");
// 取值
String name = (String) hashOperations.get("002", "name");
String age = (String) hashOperations.get("002", "age");
String addr = (String) hashOperations.get("002", "addr");
System.out.println(name + " " + age + " " + addr);
// 获得hash结构中的所有字段
Set keys = hashOperations.keys("002");
for (Object key : keys) {
System.out.println(key);
}
// 获得hash结构中的所有value值
List values = hashOperations.values("002");
for (Object value : values) {
System.out.println(value);
}
}
// 操作list类型的数据
@Test
public void listTest(){
ListOperations listOperations = redisTemplate.opsForList();
listOperations.leftPush("mylist", "a");
listOperations.leftPushAll("mylist", "a", "b", "c", "d"); //先进后遍历
List mylist = listOperations.range("mylist", 0, -1);
for (String o : mylist) {
System.out.println(o);
}
System.out.println("================================================");
// 出队列
Long len = listOperations.size("mylist");
int length = len.intValue();
for (int i = 0; i < length; i++) {
String element = (String) listOperations.leftPop("mylist"); //leftPop:从右往左;rightPop:从左往右
System.out.println(element);
}
}
// 操作set类型的数据
@Test
public void testSet(){
SetOperations setOperations = redisTemplate.opsForSet();
// 存值
setOperations.add("myset", "1", "a", "a", "d");
// 取值
Set myset = setOperations.members("myset");
for (String o : myset) {
System.out.println(o);
}
// 删除值
setOperations.remove("myset", "a", "b");
System.out.println("================");
// 取值
Set myset1 = setOperations.members("myset");
for (String s : myset1) {
System.out.println(s);
}
}
// 操作ZSet
@Test
public void testZSet(){
ZSetOperations zSetOperations = redisTemplate.opsForZSet();
// 存值
zSetOperations.add("myZset", "a", 10.0);
zSetOperations.add("myZset", "b", 6.0);
zSetOperations.add("myZset", "c", 1.0);
zSetOperations.add("myZset", "d", 5.0);
zSetOperations.add("myZset", "b", 2.0); //重复的value,分数会替换之前设置的分数
zSetOperations.add("myZset", "a", 3.0);
// 取值
Set myZset = zSetOperations.range("myZset", 0, -1);
for (String s : myZset) {
System.out.println(s);
}
System.out.println("=========================");
// 修改分数
zSetOperations.incrementScore("myZset", "b", 10);
// 取值
myZset = zSetOperations.range("myZset", 0, -1);
for (String s : myZset) {
System.out.println(s);
}
System.out.println("+++++++++++++++++++++++++++++");
// 删除
zSetOperations.remove("myZset", "a", "b");
// 取值
myZset = zSetOperations.range("myZset", 0, -1);
for (String s : myZset) {
System.out.println(s);
}
}
通用操作:针对不同的数据类型都可以操作:
@Test
public void testCommon(){
// 获取Redis中所有的key
Set keys = redisTemplate.keys("*");
for (String key : keys) {
System.out.println(key);
}
System.out.println("=======================");
// 判断某个key是否存在
Boolean isExist = redisTemplate.hasKey("wlp666");
System.out.println(isExist);
System.out.println("------------------------------");
// 删除指定key
redisTemplate.delete("username");
System.out.println("++++++++++++++++++++++++");
// 获取指定key对应的value的数据类型
DataType myset = redisTemplate.type("myset");
System.out.println(myset.code());
}