redis 1 - quick start

一、是什么

Redis是基于C语言的一个NoSQL数据库,保存在内存中,读写快,被广泛应用于分布式缓存方向。

二、本地环境搭建

安装

  • redis.io下载redis
  • 解压到/usr/local目录下
  • 文件夹改名:mv redis-7.0.4 redis
  • 进入redis/src目录,sudo make + sudo make test + sudo make install

配置

  • redis 目录下 mkdir bin etc db
  • cd src + cp mkreleasehdr.sh redis-benchmark redis-check-rdb redis-cli redis-server ../bin
  • cd ../etc vim redis.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#修改为守护模式
daemonize yes
#设置进程锁文件
pidfile /usr/local/redis/redis.pid
#端口
port 6379
#客户端超时时间
timeout 300
#日志级别
loglevel debug
#日志文件位置
logfile /usr/local/redis/log-redis.log
#设置数据库的数量,默认数据库为16,可以使用SELECT 命令在连接上指定数据库id
databases 16
##指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合
#save
#Redis默认配置文件中提供了三个条件:
save 900 1
save 300 10
save 60 10000
#指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,
#可以关闭该#选项,但会导致数据库文件变的巨大
rdbcompression yes
#指定本地数据库文件名
dbfilename dump.rdb
#指定本地数据库路径
dir /usr/local/redis/db/
#指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能
#会在断电时导致一段时间内的数据丢失。因为 redis本身同步数据文件是按上面save条件来同步的,所以有
#的数据会在一段时间内只存在于内存中
appendonly no
#指定更新日志条件,共有3个可选值:
#no:表示等操作系统进行数据缓存同步到磁盘(快)
#always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)
#everysec:表示每秒同步一次(折衷,默认值)
appendfsync everysec

启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#服务器启动
redis-server /usr/local/redis/etc/redis.conf

#客户端启动
redis-cli [-h 127.0.0.1] [-p 6379]

#客户端set
set key value

#客户端get
get key

#客户端发起关闭服务器
shutdown

三、API

列举通用的API

列举常用的,具体使用的时候可以查阅redisdoc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#数据库相关
select 下标: 切换数据库
dbsize: 查看当前数据库key的数量
flushdb: 清空当前数据库
flushall: 清空所有数据库

#key相关
假设set ss 1
exists key ss: 判断ss是否存在
move ss 1: 将ss移到数据库1中
expire key 1: 设置ss的过期时间为1s
ttl ss: 查询ss的过期时间
type ss: 查询ss的数据类型
keys *: 查看所有key

四、数据类型

Redis有五种基本的数据类型:String, List, Hash, Set, Sorted set

还提供了一些进阶的数据类型:Bitmap, Hyperloglog, Geospatial

String

二进制安全的数据类型,可以用来存储任何类型的数据比如字符串、整数、浮点数、图片(图片的 base64 编码或者解码或者图片的路径)、序列化后的对象。

string-example

命令

  1. SET key value
  2. GET key
  3. MSET key1 value1 key2 value2
  4. MGET key1 key2
  5. INCR key
  6. DECR key

应用场景

  1. 常规数据缓存
  2. 计数场景,如实现简单限流
  3. 分布式锁

List

双向链表

命令

  1. LPUSH key value1 value2
  2. LPOP key
  3. LSET key index value
  4. LLEN key
  5. LRANGE key start end

应用场景

  1. 信息流展示
  2. 消息队列

Hash

kv映射表,类似于 JDK1.8 前的 HashMap,内部实现也差不多(数组 + 链表)。

string和hash的区别

命令

  1. HSET key field value
  2. HMSET key field1 value1 field2 value2
  3. HGET key field
  4. HMGET key field1 field2
  5. HGETALL key
  6. HDEL key field1 field2

应用场景

  1. 适合需要对一个对象的某个字段单独设置值

Set

无序集合,约等于HashSet

命令

  1. SADD key member1 member2
  2. SMEMBERS key
  3. SCARD key
  4. SISMEMBER key member
  5. SINTER key1 key2
  6. SUNION key1 key2
  7. SDIFF key1 key2
  8. SRANDMEMBER key count

应用场景

  1. 数据不能重复场景:网站UV统计、动态点赞
  2. 取多个数据源交集、并集、差集场景:共同好友、好友推荐
  3. 随机获取数据源中元素:抽奖

sorted set(zset)

类似于Set,增加了一个权重参数score,使得集合中的元素能够按照score进行有序排列,还可以通过score的范围来获取元素的列表。

命令

  1. ZADD key score1 member1 score2 member2
  2. ZCARD KEY
  3. ZSCORE key member
  4. ZRANGE key start end

应用场景

  1. 排行榜
  2. 优先级队列

Bitmap

Bitmap 不是 Redis 中的实际数据类型,而是在 String 类型上定义的一组面向位的操作,

命令

  1. SETBIT key offset value
  2. GETBIT key offset
  3. BITCOUNT key start end

应用场景

  1. 需要保存状态信息的场景:签到、活跃、行为统计

HyperLogLog

HyperLogLog 是一种有名的基数计数概率算法,Redis 实现了这个算法并提供了一些开箱即用的 API

HyperLogLog 的计数结果并不是一个精确值,存在一定的误差。

命令

  1. PFADD key element1 element2
  2. PFCOUNT key1 key2
  3. PFMERGE destkey sourcekey1 sourcekey2

应用场景

  1. 数量量巨大(百万、千万级别以上)的计数场景:ip统计、uv统计

Geospatial

主要用于存储地理位置信息,基于 Sorted Set 实现。

命令

  1. GEOADD key longitude1 latitude1 member1
  2. GEOPOS key member1 member2
  3. GEODIST key member1 member2 M/KM/FT/MI
  4. GEORADIUS key longitude latitude radius distance
  5. GEORADIUSBYMEMBER key member radius distance

举例

1
2
3
4
5
6
7
> GEOADD personLocation 116.33 39.89 user1 116.34 39.90 user2 116.35 39.88 user3
3
> GEOPOS personLocation user1
116.3299986720085144
39.89000061669732844
> GEODIST personLocation user1 user2 km
1.4018

应用场景

  1. 管理地理空间数据:附近的人

五、Spring集成

引入依赖

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

配置文件

1
2
3
4
5
6
7
8
# application.properties 不填写会有默认配置
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.database=0
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

使用

1
2
3
4
5
6
7
@Autowired
private StringRedisTemplate template;

public void set(String key, Object value) {
ValueOperations<String, String> opsForValue = template.opsForValue();
opsForValue.set(key, new Gson().toJson(value));
}

Spring API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
@Autowired
private RedisTemplate redisTemplate;

public void testOps() {
// ops
ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
HashOperations<Stirng, Object, Object> opsForHash = redisTempalte.opsForHash();
SetOperations<String, String> opsForSet = template.opsForSet();
ListOperations<String, String> opsForList = template.opsForList();
ZSetOperations<String, String> opsForZSet = template.opsForZSet();

// 不常用的ops
ClusterOperations<String, String> opsForCluster = template.opsForCluster();
GeoOperations<String, String> opsForGeo = template.opsForGeo();
HyperLogLogOperations<String, String> opsForHyperLogLog = template.opsForHyperLogLog();
StreamOperations<String, Object, Object> opsForStream = template.opsForStream();

// template API
template.keys("*");
template.delete(key);
template.expire(key, Duration.ofDays(1));
template.getExpire(key);
template.hasKey(key);
DataType type = template.type(key);


// opsForValue API
opsForValue.set(key, new Gson().toJson(value));
opsForValue.get(key);
opsForValue.setIfPresent(key, new Gson().toJson(value));
opsForValue.multiGet(list);
opsForValue.multiSet(map);
opsForValue.set(key, new Gson().toJson(value), expireTime));

// opsForList API
opsForList.leftPush(listKey, value);
opsForList.leftPushAll(listKey, values...);
opsForList.leftPop(listKey);
opsForList.range(listKey, start, end);
opsForList.remove(listKey, count, value);
opsForList.size(listKey);

// opsForSet API
opsForSet.add(setKey, values..);
opsForSet.remove(setKey, values..);
opsForSet.size(setKey);
opsForSet.isMember(setKey, value);
opsForSet.difference();
opsForSet.interSet();
opsForSet.union();

// opsForHash API
opsForHash.put(hashKey, key, value);
opsForHash.putAll(hashKey, map);
opsForHash.get(hashKey, key);
opsForHash.multiGet(hashKey, keys);
opsForHash.values(hashKey);
opsForHash.size(hashKey);
opsForHash.keys(hashKey);
opsForHash.entries(hashKey);
opsForHash.values(hashKey);
}

RedisTemplate? Operations?

image-20230409153306627

定义了两个接口,RedisOperation, ValueOperations(其实是一组,以Value为例子)

RedisOperatioon定义了通用的命令如execute, opsForValue(return ValueOperations)

ValueOperations定义了对数据的操作命令,如get set

RedisTemplateDefaultValueOperations定义了默认实现类。一般使用RedisTemplate即可

六、总结

  1. Redis是基于C语言的一个NoSQL数据库,具有高性能、高并发的特点,常被用于分布式缓存。
  2. Redis提供了五种基本的数据结构,分别是string, list, set, hash, sortedSet.
  3. Spring环境下,使用RedisTemplate, xxOperations,可以方便对Redis中数据进行操作

redis 1 - quick start
https://yzaf.top/2023/redis/redis-1/
作者
why
发布于
2023年4月6日
许可协议