文章目录
- 一、Redis键key基本命令
- 二、Redis数据类型
- 1、String命令(json串)与应用场景
- 2、Hash命令(一个javaBean对象)与应用场景
- 三、java连接Redis
- 四、SpringData整合Redis
一、Redis键key基本命令
Redis 键命令用于管理 redis 的键:
- 该命令用于在 key 存在时删除 key:
del key
- 序列化给定 key ,并返回被序列化的值:
dump key
- 检查给定 key 是否存在:
exists key
- 查找所有符合给定模式( pattern)的 key :
keys pattern
*
代表所有
?
表示代表一个字符 - 为给定 key 设置过期时间(以秒计):
expire key seconds
- 设置 key 的过期时间以毫秒计:
pexpire key milliseconds
- 以秒为单位,返回给定 key 的剩余生存时间(ttl, time to live) :
ttl key
- 以毫秒为单位返回 key 的剩余的过期时间:
pttl key
- 移除 key 的过期时间,key 将持久保持:
persist key
- 修改Key的名称:
rename key newkey
- 将当前数据库的 key 移动到给定的数据库 db 当中 :
move key db
- 返回 key 所储存的值的类型:
type key
- key的命名规范:
1、key不要太长,尽量不要超过1024字节,这不仅消耗内存,而且会降低查找的效率;
2、key也不要太短,太短的话,key的可读性会降低;
3、在一个项目中,key最好使用统一的命名模式,例如user:123:password;
4、key名称区分大小写
二、Redis数据类型
1、String命令(json串)与应用场景
string是redis最基本的类型,一个key对应一个value。
string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。
string类型是Redis最基本的数据类型,一个键最大能存储512MB。
- set命令用于设置给定 key 的值。如果 key 已经存储值, set就覆写旧值,且无视类型 :
set key_name value
- get命令用于获取指定 key 的值。如果 key 不存在,返回 nil 。如果key 储存的值不是字符串类型,返回一个错误:
get key_name
- setnx(set if not exists) 命令在指定的 key 不存在时,为 key 设置指定的值:
setnx key_name value
- 用于获取存储在指定 key 中字符串的子字符串。字符串的截取范围由 start 和 end 两个偏移量决定(包括 start 和 end 在内):
getrange key start end
- getset 命令用于设置指定 key 的值,并返回 key 的旧值,当 key 不存在时,返回 nil
- 返回 key 所储存的字符串值的长度:
strlen key
- 同时设置一个或多个 key-value 对:
mset key value key1 value1....
- 获取所有(一个或多个)给定 key 的值:
mget key1 key2....
- 自增:Incr 命令将 key 中储存的数字值增1。如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行incr 操作 :
inct key_name
- Incrby 命令将 key 中储存的数字加上指定增量值
incrby key_name 增量值
- decr 命令将 key 中储存的数字减1
decr key_name
或decrby key_name 减值
- 字符串拼接: append 命令用于为指定的 key 追加至未尾,如果不存在,为其赋值
:append key_name value
String类型的应用场景
- String通常用于保存单个字符串或JSON字符串数据
- 因String是二进制安全的,所以你完全可以把一个图片文件的内容作为字符串来存储
- 计数器(常规key-value缓存应用。常规计数: 微博数, 粉丝数)
incr等指令本身就具有原子操作的特性,所以我们完全可以利用redis的incr、incrby、decr、decrby等指令来实现原子计数的效果。假如,在某种场景下有3个客户端同时读取了mynum的值(值为2),然后对其同时进行了加1的操作,那么,最后mynum的值一定是5。
2、Hash命令(一个javaBean对象)与应用场景
Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。 Redis 中每个 hash 可以存储:2的32次方-1 键值对(40多亿)
可以看成具有key和value的map容器,该类型非常适合于存储值对象的信息
例如Person的属性:id,age,name)
- 为指定的key设定field value :
hset key field value
- 获取存储在hash中的值,根据field得到value:
hget key field
- 同时将多个 field-value (域-值)对设置到哈希表 key 中:
hmset key field value field1 value1 .....
- 获取key所有给定字段的值 :
hmget key filed field1......
- 返回HASH表中所有的字段和值 :
hgetall key
- 获取所有哈希表中的字段:
hkeys key
- 获取哈希表中字段的数量:
hlen key
- 删除一个或多个hash表字段 :
hdel key field1 field2...
- 只有在字段 field 不存在时,设置哈希表字段的值:
hsetnx key filed value
- 为哈希表 key 中的指定字段的整数值加上增量:
hincrby key field increment
- 为哈希表 key 中的指定字段的浮点数值加上增量 :
hincrbyfloat key field increment
- 查看哈希表 key 中,指定的字段是否存在:
hexists key field
hash类型应用场景:存储一个对象数据
- 为什么不用string存储一个对象?
hash是最接近关系数据库结构的数据类型,可以将数据库一条记录或程序中一个对象转换成hashmap存放在redis中。 - 用户ID为查找的key,存储的value用户对象包含姓名,年龄,生日等信息,如果用普通的key/value结构来存储,主要有以下2种存储方式:
第一种方式将用户ID作为查找key,把其他信息封装成一个对象以序列化的方式存储,这种方式的缺点是,增加了序列化/反序列化的开销,并且在需要修改其中一项信息时,需要把整个对象取回,并且修改操作需要对并发进行保护,引入CAS等复杂问题。
第二种方法是这个用户信息对象有多少成员就存成多少个key-value对,用用户ID+对应属性的名称作为唯一标识来取得对应属性的值,虽然省去了序列化开销和并发问题,但是用户ID为重复存储,如果存在大量这样的数据,内存浪费还是非常可观的。 - 总结:
Redis提供的Hash很好的解决了这个问题,Redis的Hash实际是内部存储的Value为一个HashMap,并提供了直接存取这个Map成员的接口
三、java连接Redis
在官方网站列一些Java客户端访问,有:Jedis/Redisson/Jredis/JDBC-Redis等,其中官方推荐使用Jedis和Redisson。常用Jedis。
1、开始在 Java 中使用 Redis 前, 我们需要确保已经安装了 redis 服务及 Java redis 驱动,且你的机器上能正常使用 Java。
<!--jedis客户端依赖jar-->
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.1.0</version>
</dependency>
2、使用jedis客户端连接linux系统上的redis服务:
public class RedisDemo {
/**
* java通过Jedis客户端操作redis服务器
* @param args
*/
public static void main(String[] args) {
//连接jedis服务器
String host = "192.168.157.130";
int port = 6379;
Jedis jedis = new Jedis(host,port);
//redis服务的密码
jedis.auth("hengheng");
//测试redis连接是否成功
System.out.println(jedis.ping());
}
3、想要连接成功,需要使用linux防护墙开放redis的端口:
firewall-cmd --list-ports
firewall-cmd --zone=public --add-port=6379/tcp --permanent
firewall-cmd --reload
4、Java操作Redis的String类型:
/**
* 测试字符串String
*/
@Test
public void test1(){
//获取redis连接
Jedis jedis = new Jedis("192.168.157.130",6379);
jedis.auth("hengheng");
jedis.set("strName","字符串的值");
String strName = jedis.get("strName");
System.out.println(strName);
jedis.close();
}
/**
* Rsdis的作用:为了减轻数据库MySql的压力
* 需求:判断某key是否存在,如果存在就从Redis中查询
* 如果不存在,就查询数据库,将要查询的数据存入redis中
*/
@Test
public void test2(){
Jedis jedis = new Jedis("192.168.157.130",6379);
jedis.auth("hengheng");
String key = "applicationName";
if(jedis.exists(key)){
String result = jedis.get(key);
System.out.println("Redis数据库中查询到:"+result);
}else{
//在数据库中查询
String result = "哈哈";
jedis.set(key,result);
System.out.println("数据库查询的值结果:"+result);
}
}
5、Java jedis连接池优化以及工具类编写:
public class RedisPoolUtil {
private static JedisPool pool;
static {
//1.连接池Redis Pool的基本配置信息
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(8);//最大连接数
poolConfig.setMaxIdle(8);//最大空闲数
//2.连接池
String host = "192.168.157.130";
int port = 6379;
pool = new JedisPool(poolConfig,host,port);
}
public static Jedis getJedis(){
//3.从连接池中获取连接
Jedis jedis = pool.getResource();
jedis.auth("hengheng");
return jedis;
}
//关闭连接功能
public static void close(Jedis jedis){
jedis.close();
}
}
6、java操作Redis的Hash类型:
User实体类:
@Data
public class User {
private Integer id;
private String username;
private String password;
private String name;
private Integer age;
public static String getKeyName(){
return "user:";
}
}
Redis操作Hash类型数据:
/**
* jedis完成对hash类型的操作
* 需求:hash存储一个对象
* 判断Redis中是否存在key,如果存在,直接返回对应值
* 如果不存在,查询数据库,将查询的数据库存入redis并返回给用户
*/
@Test
public void test4(){
Jedis jedis = RedisPoolUtil.getJedis();
String id="1";
String key = User.getKeyName()+id;
if(jedis.exists(key)){
//redis中取出该对象
Map<String, String> map = jedis.hgetAll(key);
User user = new User();
user.setId(Integer.parseInt(map.get("id")));
user.setName(map.get("name"));
user.setAge(Integer.parseInt(map.get("age")));
user.setUsername(map.get("username"));
user.setPassword(map.get("password"));
System.out.println("Redis缓存中:"+user);
}else{
//mysql中取出该对象
User user = new User();
user.setName("张三");
user.setAge(19);
user.setId(1);
user.setUsername("zhangsan");
user.setPassword("123");
//将filed-value存放在HashMap中
HashMap<String, String> map = new HashMap<>();
map.put("id",user.getId()+"");
map.put("name",user.getName());
map.put("age",user.getAge()+"");
map.put("username",user.getUsername());
map.put("password",user.getPassword());
jedis.hmset(key,map);
System.out.println("数据库中:"+user);
}
}
四、SpringData整合Redis
Spring data 提供了RedisTemplate模版 ,它封装了redis连接池管理的逻辑,业务代码无须关心获取,释放连接逻辑;spring redis同时支持了Jedis,Jredis,rjc 客户端操作。
1、编写spring-redis配置文件:
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc">
<!--开启注解扫描-->
<context:component-scan base-package="service.impl"/>
<!--配置Jedis连接池信息-->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!--最大连接数-->
<property name="maxTotal" value="50"/>
<!--最大剩余数-->
<property name="maxIdle" value="5"/>
</bean>
<!--Spring整合Jedis-->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="192.168.157.130"/>
<property name="port" value="6379"/>
<property name="password" value="hengheng"/>
<!--自定义连接池配置-->
<property name="poolConfig" ref="jedisPoolConfig"></property>
</bean>
<!--RedisTemplate-->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory"/>
<!--key进行序列化设置,默认JDK改为String-->
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<!--value进行序列化设置,默认JDK改为String-->
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
</bean>
</beans>
2、编写Service层:
public interface UserService {
public String getString(String key);
}
@Service
public class UserServiceImpl implements UserService {
@Autowired
RedisTemplate<String,String> redisTemplate;
@Override
public String getString(String key) {
//获取String类型
ValueOperations<String, String> string = redisTemplate.opsForValue();
//redisTemplate.expire("java1802",2, TimeUnit.HOURS);
string.set("java1803","这是一个测试数据",2,TimeUnit.HOURS);
if(redisTemplate.hasKey(key)){
System.out.println("redis中取出。。。");
return string.get(key);
}else{
String result = "RedisTemplate模板";
string.set(key,result);
return result;
}
}
}
3、编写测试类:
public class RedisTemplateTest {
@Test
public void test(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-redis.xml");
UserService bean = context.getBean(UserServiceImpl.class);
String key = "applicationName";
String result = bean.getString(key);
System.out.println(result);
}
}