一、是什么
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 key value
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: 清空所有数据库
假设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 编码或者解码或者图片的路径)、序列化后的对象。
命令
SET key value
GET key
MSET key1 value1 key2 value2
MGET key1 key2
INCR key
DECR key
应用场景
- 常规数据缓存
- 计数场景,如实现简单限流
- 分布式锁
List
双向链表
命令
LPUSH key value1 value2
LPOP key
LSET key index value
LLEN key
LRANGE key start end
应用场景
- 信息流展示
- 消息队列
Hash
kv映射表,类似于 JDK1.8 前的 HashMap
,内部实现也差不多(数组 + 链表)。
命令
HSET key field value
HMSET key field1 value1 field2 value2
HGET key field
HMGET key field1 field2
HGETALL key
HDEL key field1 field2
应用场景
- 适合需要对一个对象的某个字段单独设置值
Set
无序集合,约等于HashSet
命令
SADD key member1 member2
SMEMBERS key
SCARD key
SISMEMBER key member
SINTER key1 key2
SUNION key1 key2
SDIFF key1 key2
SRANDMEMBER key count
应用场景
- 数据不能重复场景:网站UV统计、动态点赞
- 取多个数据源交集、并集、差集场景:共同好友、好友推荐
- 随机获取数据源中元素:抽奖
sorted set(zset)
类似于Set,增加了一个权重参数score
,使得集合中的元素能够按照score
进行有序排列,还可以通过score
的范围来获取元素的列表。
命令
ZADD key score1 member1 score2 member2
ZCARD KEY
ZSCORE key member
ZRANGE key start end
应用场景
- 排行榜
- 优先级队列
Bitmap
Bitmap 不是 Redis 中的实际数据类型,而是在 String 类型上定义的一组面向位的操作,
命令
SETBIT key offset value
GETBIT key offset
BITCOUNT key start end
应用场景
- 需要保存状态信息的场景:签到、活跃、行为统计
HyperLogLog
HyperLogLog 是一种有名的基数计数概率算法,Redis 实现了这个算法并提供了一些开箱即用的 API
HyperLogLog 的计数结果并不是一个精确值,存在一定的误差。
命令
PFADD key element1 element2
PFCOUNT key1 key2
PFMERGE destkey sourcekey1 sourcekey2
应用场景
- 数量量巨大(百万、千万级别以上)的计数场景:ip统计、uv统计
Geospatial
主要用于存储地理位置信息,基于 Sorted Set 实现。
命令
GEOADD key longitude1 latitude1 member1
GEOPOS key member1 member2
GEODIST key member1 member2 M/KM/FT/MI
GEORADIUS key longitude latitude radius distance
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
|
应用场景
- 管理地理空间数据:附近的人
五、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
| 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() { 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();
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.keys("*"); template.delete(key); template.expire(key, Duration.ofDays(1)); template.getExpire(key); template.hasKey(key); DataType type = template.type(key);
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.leftPush(listKey, value); opsForList.leftPushAll(listKey, values...); opsForList.leftPop(listKey); opsForList.range(listKey, start, end); opsForList.remove(listKey, count, value); opsForList.size(listKey); opsForSet.add(setKey, values..); opsForSet.remove(setKey, values..); opsForSet.size(setKey); opsForSet.isMember(setKey, value); opsForSet.difference(); opsForSet.interSet(); opsForSet.union(); 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?
定义了两个接口,RedisOperation, ValueOperations(其实是一组,以Value为例子)
RedisOperatioon
定义了通用的命令如execute, opsForValue(return ValueOperations)
ValueOperations
定义了对数据的操作命令,如get set
RedisTemplate
和DefaultValueOperations
定义了默认实现类。一般使用RedisTemplate
即可
六、总结
- Redis是基于C语言的一个NoSQL数据库,具有高性能、高并发的特点,常被用于分布式缓存。
- Redis提供了五种基本的数据结构,分别是string, list, set, hash, sortedSet.
- Spring环境下,使用
RedisTemplate, xxOperations
,可以方便对Redis中数据进行操作