认识Redis
认识Redis
- 键值型
- 单线程,每个命令具有原子性
- 低延迟,速度快(基于内存,IO多路复用)
- 支持数据持久化
- 主持主从集群
- 支持多语言客户端
- 默认最多16个库,名称已经给定了,可以设置库的数量
连接Redis
- redis-cli
- -h:指定ip
- -p:指定端口
- -a:指定密码
数据类型
String
"hello world"
Hash
{name: "hu", age: 21}
List
[a -> b -> c]
set
{a, b, c}
SortedSet
{A: 1, B: 2, C: 3}
GEO
{a: (120.3, 30.5)}
BitMap
0101001001010
HyperLog
0101010101
常见指令
help
查看命令的使用
helpselect
select index
选择对应的数据库
select 0
选择0号数据库set
set key value
设置键和键值
set age 21setnx
setnx key value
当不存在key时存在
返回值1成功,0失败
setnx age 1setex
setex key seconds value
设置一个键值对并指明过期时间
setex age 10 2mset
mset k1 v1 k2 v2
批量的去添加键值对
mset age 1 name "jack"get
get key
获取对应键值
get agemget
mget k1 k2
获取多个键的值
mget age namekeys
keys pattern
获取,满足正则的键
keys a*
获取所有以a开头的keydel
del key [key1 key2]
删除对应的键值对
del k1 k2 k3
不存在不操作
返回值为真正删除的数量exists
exists key [k1 k2 k3]
返回存在键存在的数量
expire
expire key seconds
设置一个键的存在秒数
expire age 2ttl
ttl key
永久有效则返回-1,不存在存在-2
有时效则返回对应剩余时间
ttl ageString类型常见命令补充
incr
incr age
让一个整型的key值自增1
incr ageincrby
incrby age 2
指定步长
incrby age 2incrbyfloat
让一个浮点型增长指定步长
incrbyfloat money 0.1Hash

Hash结构

List
类似双向链表

$ LPUSH list el1 el2 el3
# 向左则依次插入el1 el2 el3
# 变成el3<->el2<->el1Set
用于集合的交差并集等很好用


SortedSet


降序就是
ZREVRANK 这样就是降序了key的层级结构
项目名:业务名:类型:id
规范就是用:隔开
set a:c:b '{a:1, b:2, c: 3}'
set a:c:d '{a:1, c:2, d: 3}'
在一些软件中这样的就会分层
Java中使用Redis
Jedis


先创建一个连接池
这里存放连接的,当需要连接的时候,如果这里有就从这里取
public class JedisFactory { private static final JedisPool jedisPool; static {// 这个好像叫静态代码块 JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); // 下面是一些配置 jedisPoolConfig.setMaxIdle(10); jedisPoolConfig.setMaxTotal(10); jedisPoolConfig.setMaxWait(Duration.ofSeconds(5)); // 创建对应的连接池 jedisPool = new JedisPool(jedisPoolConfig, "localhost", 6379, 1000, null); } public static Jedis getJedis() { // 返回连接 return jedisPool.getResource(); } }获取连接
jedis = JedisFactory.getJedis(); // 直接这样就ok了
SpringDataRedis

这就相当于mysql的mybatis了
准备工作


常见操作

连接实践
@Autowired
private RedisTemplate redisTemplate;
@Test
public void setRedisTemplate() {
Object a = redisTemplate.opsForValue().get("a");
// 这样直接获取的在原始操作中key不是a,因为从spring存入的会被对应的序列化器,进行序列化
System.out.println(a);
}改用序列器

有多个自带的序列器,自行选用
添加下方这个配置类就行
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) throws Exception {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
redisTemplate.setKeySerializer(RedisSerializer.string());
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashKeySerializer(RedisSerializer.string());
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
return redisTemplate;
}
}一些小问题
当使用JSON序列化器时,会多存入信息
{"@class":"icu.slovej.springredis.POJO.User","name":"jack","age":20} // 但是要是不存又不能自动反序列化- 解决方法


2. spring老大哥直接给你整好了

@Test
public void setRedisTemplate() throws JsonProcessingException {
User user1 = new User("jack", 20);
// 手动序列化
String json = jacksonObjectMapper.writeValueAsString(user1);
// 写入数据
redisTemplate.opsForValue().set("user:1", json);
String s = stringRedisTemplate.opsForValue().get("user:1");
// 手动反序列化
User user2 = jacksonObjectMapper.readValue(s, User.class);
System.out.println(user2);
}
// 这样手动进行的就不需要存入额外的内容实战
短信登陆

添加Redis缓存





缓存三剑客





秒杀




进一步改进乐观锁就是改成判断库存>0就行,这种情况可以这样做
一人一单
加锁
分布式锁



释放锁存在问题,下面解决方案

Redis_Lua

