解锁Redis的威力:Redis的使用指南| 青训营

51 阅读12分钟

解锁Redis的威力:Redis的使用指南| 青训营

引言

  • Redis是什么?what?
    Redis(Remote Dictionary Server ),即远程字典服务 !
    是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
    在这里插入图片描述
    redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
    免费和开源!是当下最热门的 NoSQL 技术之一!也被人们称之为结构化数据库!
  • Redis能干嘛?
    1、内存存储、持久化,内存中是断电即失、所以说持久化很重要(rdb、aof) 2、效率高,可以用于高速缓存
    3、发布订阅系统
    4、地图信息分析
    5、计时器、计数器(浏览量!)

Redis的关键特性:

Redis是一种NoSQL数据库,将数据存储在内存中,这意味着数据直接存储和访问于RAM。这导致了非常快速的读写操作,使得Redis在对低延迟性能至关重要的场景中非常理想。

数据结构:

Redis支持多种数据结构,包括字符串、哈希、列表、集合、有序集合等。这种多功能性使开发人员能够根据特定的用例选择最合适的数据结构。

在Redis中创建和操作数据结构非常简单。以下是一些常见数据结构的示例代码:

  1. 字符串(String):
bash
复制代码
# 设置一个字符串键值对
SET username "alice"
# 获取字符串值
GET username
  1. 哈希(Hash):
bash
复制代码
# 设置哈希字段
HSET user:id123 name "Alice" age 30
# 获取哈希字段值
HGET user:id123 name
HGET user:id123 age
  1. 列表(List):
bash
复制代码
# 在列表的左侧插入元素
LPUSH tasks "task1"
LPUSH tasks "task2"
# 获取列表的元素
LRANGE tasks 0 -1
  1. 集合(Set):
bash
复制代码
# 向集合中添加元素
SADD tags "tag1" "tag2" "tag3"
# 获取集合的所有元素
SMEMBERS tags
  1. 有序集合(Sorted Set):
bash
复制代码
# 向有序集合添加成员并指定分数
ZADD leaderboard 100 "player1" 200 "player2" 50 "player3"
# 获取有序集合中分数范围内的成员
ZRANGEBYSCORE leaderboard 0 150

二、Redis的五大数据类型

  1. String(字符串)
    添加查询追加获取长度判断是否存在的操作
127.0.0.1:6379> set name dingdada  #插入一个key为‘name’值为‘dingdada’的数据
OK
127.0.0.1:6379> get name  #获取key为‘name’的数据
"dingdada"
127.0.0.1:6379> get key1
"hello world!"
127.0.0.1:6379> keys *  #查看当前库的所有数据
1) "name"
127.0.0.1:6379> EXISTS name  #判断key为‘name’的数据存在不存在,存在返回1
(integer) 1
127.0.0.1:6379> EXISTS name1  #不存在返回0
(integer) 0
127.0.0.1:6379> APPEND name1 dingdada1  #追加到key为‘name’的数据后拼接值为‘dingdada1’,如果key存在类似于java中字符串‘+’,不存在则新增一个,类似于Redis中的set name1 dingdada1 ,并且返回该数据的总长度
(integer) 9
127.0.0.1:6379> get name1
"dingdada1"
127.0.0.1:6379> STRLEN name1  #查看key为‘name1’的字符串长度
(integer) 9
127.0.0.1:6379> APPEND name1 ,dingdada2  #追加,key存在的话,拼接‘+’,返回总长度
(integer) 19
127.0.0.1:6379> STRLEN name1
(integer) 19
127.0.0.1:6379> get name1
"dingdada1,dingdada2"
127.0.0.1:6379> set key1 "hello world!"  #注意点:插入的数据中如果有空格的数据,请用“”双引号,否则会报错!
OK
127.0.0.1:6379> set key1 hello world!  #报错,因为在Redis中空格就是分隔符,相当于该参数已结束
(error) ERR syntax error
127.0.0.1:6379> set key1 hello,world!  #逗号是可以的
OK

123456789101112131415161718192021222324252627282930

自增自减操作

127.0.0.1:6379> set num 0  #插入一个初始值为0的数据
OK
127.0.0.1:6379> get num
"0"
127.0.0.1:6379> incr num  #指定key为‘num’的数据自增1,返回结果  相当于java中 i++
(integer) 1
127.0.0.1:6379> get num  #一般用来做文章浏览量、点赞数、收藏数等功能
"1"
127.0.0.1:6379> incr num
(integer) 2
127.0.0.1:6379> incr num
(integer) 3
127.0.0.1:6379> get num
"3"
127.0.0.1:6379> decr num  #指定key为‘num’的数据自减1,返回结果  相当于java中 i--
(integer) 2
127.0.0.1:6379> decr num
(integer) 1
127.0.0.1:6379> decr num
(integer) 0
127.0.0.1:6379> decr num  #可以一直减为负数~
(integer) -1
127.0.0.1:6379> decr num  #一般用来做文章取消点赞、取消收藏等功能
(integer) -2
127.0.0.1:6379> decr num
(integer) -3
127.0.0.1:6379> INCRBY num 10  #后面跟上by  指定key为‘num’的数据自增‘参数(10)’,返回结果
(integer) 7
127.0.0.1:6379> INCRBY num 10
(integer) 17
127.0.0.1:6379> DECRBY num 3  #后面跟上by  指定key为‘num’的数据自减‘参数(3)’,返回结果
(integer) 14
127.0.0.1:6379> DECRBY num 3
(integer) 11

12345678910111213141516171819202122232425262728293031323334

截取替换字符串操作

#截取
127.0.0.1:6379> set key1 "hello world!"
OK
127.0.0.1:6379> get key1
"hello world!"
127.0.0.1:6379> GETRANGE key1 0 4  #截取字符串,相当于java中的subString,下标从0开始,不会改变原有数据
"hello"
127.0.0.1:6379> get key1
"hello world!"
127.0.0.1:6379> GETRANGE key1 0 -1  #0至-1相当于 get key1,效果一致,获取整条数据
"hello world!"
#替换
127.0.0.1:6379> set key2 "hello,,,world!"
OK
127.0.0.1:6379> get key2
"hello,,,world!"
127.0.0.1:6379> SETRANGE key2 5 888  #此语句跟java中replace有点类似,下标也是从0开始,但是有区别:java中是指定替换字符,Redis中是从指定位置开始替换,替换的数据根据你所需替换的长度一致,返回值是替换后的长度
(integer) 14
127.0.0.1:6379> get key2
"hello888world!"
127.0.0.1:6379> SETRANGE key2 5 67  #该处只替换了两位
(integer) 14
127.0.0.1:6379> get key2
"hello678world!"

123456789101112131415161718192021222324

设置过期时间不存在设置操作

#设置过期时间,跟Expire的区别是前者设置已存在的key的过期时间,而setex是在创建的时候设置过期时间
127.0.0.1:6379> setex name1 15  dingdada  #新建一个key为‘name1’,值为‘dingdada’,过期时间为15秒的字符串数据
OK
127.0.0.1:6379> ttl name1  #查看key为‘name1’的key的过期时间
(integer) 6
127.0.0.1:6379> ttl name1
(integer) 5
127.0.0.1:6379> ttl name1
(integer) 3
127.0.0.1:6379> ttl name1
(integer) 1
127.0.0.1:6379> ttl name1
(integer) 0
127.0.0.1:6379> ttl name1  #返回为-2时证明该key已过期,即不存在
(integer) -2
#不存在设置
127.0.0.1:6379> setnx name2 dingdada2  #如果key为‘name2’不存在,新增数据,返回值1证明成功
(integer) 1
127.0.0.1:6379> get name2
"dingdada2"
127.0.0.1:6379> keys *
1) "name2"
127.0.0.1:6379> setnx name2 "dingdada3"  #如果key为‘name2’的已存在,设置失败,返回值0,也就是说这个跟set的区别是:set会替换原有的值,而setnx不会,存在即不设置,确保了数据误操作~
(integer) 0
127.0.0.1:6379> get name2
"dingdada2"

1234567891011121314151617181920212223242526

msetmget操作

127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3  #插入多条数据
OK
127.0.0.1:6379> keys *  #查询所有数据
1) "k2"
2) "k3"
3) "k1"
127.0.0.1:6379> mget k1 k2 k3  #查询key为‘k1’,‘k2’,‘k3’的数据
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> MSETNX k1 v1 k4 v4  #msetnx是一个原子性的操作,在一定程度上保证了事务!要么都成功,要么都失败!相当于if中的条件&&(与)
(integer) 0
127.0.0.1:6379> keys *
1) "k2"
2) "k3"
3) "k1"
127.0.0.1:6379> MSETNX k5 v5 k4 v4  #全部成功
(integer) 1
127.0.0.1:6379> keys *
1) "k2"
2) "k4"
3) "k3"
4) "k5"
5) "k1"

123456789101112131415161718192021222324

添加获取对象getset操作

#这里其实本质上还是字符串,但是我们讲其key巧妙的设计了一下。
##mset student:1:name  student 相当于类名,1 相当于id,name 相当于属性
#如果所需数据全部这样设计,那么我们在java的业务代码中,就不需要关注太多的key
#只需要找到student类,下面哪个id,需要哪个属性即可,减少了代码的繁琐,在一定程度上可以理解为这个一个类的对象!
127.0.0.1:6379> mset student:1:name dingdada student:1:age 22  #新增一个key为‘student:1:name’,value为‘dingdada ’。。等数据
OK
127.0.0.1:6379> keys *  #查看所有的key
1) "student:1:age"
2) "student:1:name"
127.0.0.1:6379> mget student:1:age student:1:name  #获取数据
1) "22"
2) "dingdada"

##getset操作
127.0.0.1:6379> getset name1 dingdada1  #先get再set,先获取key,如果没有,set值进去,返回的是get的值
(nil)
127.0.0.1:6379> get name1
"dingdada1"
127.0.0.1:6379> getset name1 dingdada2  ##先获取key,如果有,set(替换)最新的值进去,返回的是get的值
"dingdada1"
127.0.0.1:6379> get name1  #替换成功
"dingdada2"

12345678910111213141516171819202122

总结
String是Redis中最常用的一种数据类型,也是Redis中最简单的一种数据类型。首先,表面上它是字符串,但其实他可以灵活的表示字符串、整数、浮点数3种值。Redis会自动的识别这3种值。

持久化:

尽管Redis主要将数据存储在内存中,但它提供了各种持久化选项,如快照和追加-only文件,以确保数据的持久性和在故障情况下的恢复能力。

以下是如何配置Redis进行持久化的示例代码(在redis.conf配置文件中):

bash
复制代码
# 启用快照持久化
save 900 1
save 300 10
save 60 10000

# 启用追加-only文件持久化
appendonly yes

缓存:

Redis最常见的用例之一是缓存。通过将经常访问的数据存储在Redis中,应用程序可以减轻对主数据库的负载,从而显著提高响应时间。

以下是如何在应用程序中使用Redis作为缓存的示例代码(使用Python的Redis库):

python
复制代码
import redis

# 连接到Redis服务器
r = redis.Redis(host='localhost', port=6379, db=0)

# 检查缓存中是否存在数据
cached_data = r.get('cached_key')
if cached_data:
    # 使用缓存数据
    print("Using cached data:", cached_data)
else:
    # 从主数据库中获取数据
    data = fetch_data_from_primary_db()
    # 将数据存储在缓存中,设置过期时间
    r.setex('cached_key', 3600, data)
    print("Using fetched data:", data)

发布/订阅消息:

Redis支持发布/订阅消息模式,可以用于实现应用程序不同组件之间的实时通信。

以下是如何使用Redis的发布/订阅功能的示例代码(使用命令行):

在一个终端中执行以下命令以创建一个订阅者:

bash
复制代码
SUBSCRIBE notifications

在另一个终端中执行以下命令以发布消息给订阅者:

bash
复制代码
PUBLISH notifications "New message: Hello, subscribers!"

原子操作:  Redis确保各种操作的原子性,适用于需要一致性和可靠性数据操作的任务。

以下是如何在Redis中执行原子操作的示例代码(使用Lua脚本):

lua
复制代码
-- 原子性地增加计数器
local counter = redis.call('INCR', 'counter_key')
return counter

用例

  1. 缓存:  如前所述,缓存是Redis的主要用例之一。它允许应用程序在内存中存储经常访问的数据,减少了反复查询主数据源的需求。这导致了改进的响应时间和更好的整体性能。Redis设置缓存数据的过期时间确保缓存保持相关性。
  2. 会话存储:  Redis经常用于管理Web应用程序中的用户会话。在Redis中存储会话数据可以确保快速访问,并实现应用程序的无缝扩展。
  3. 实时分析:  Redis快速的读写操作使其非常适合实时分析。它可以以低延迟存储和处理大量数据,提供有关用户行为和应用程序性能的见解。
  4. 排行榜和计数:  Redis的有序集合可用于创建游戏或应用程序的排行榜。它还适用于计数操作,如跟踪赞数、分享数或查看数。
  5. 消息队列:  Redis的发布/订阅功能使其成为构建实时通信系统或后台作业处理队列的消息代理。
  6. 地理空间数据:  Redis对地理空间索引的支持使其适用于需要基于位置的数据的应用,例如地图服务或基于位置的推荐。

最佳实践

  1. 数据建模:  根据您的用例选择适当的数据结构。Redis的数据结构提供不同的优势,因此了解它们对于优化性能至关重要。
  2. 内存管理:  由于Redis将数据存储在内存中,监控内存使用情况非常重要。使用诸如redis-cli之类的工具来跟踪内存消耗,并配置驱逐策略以处理超出可用内存的数据。
  3. 持久化配置:  根据数据的耐久性要求配置持久化选项。快照和追加文件在性能和数据安全性之间提供不同的权衡。
  4. 安全性:  必须充分保护Redis实例。设置强密码、配置网络访问控制,并考虑为传输中的数据启用SSL加密。
  5. 扩展性:  尽管Redis以速度闻名,但在应用程序增长时规划扩展很重要。考虑使用分片或集群等技术,将负载分布到多个Redis实例中。

总结

Redis已经在现代应用程序中存储和访问数据的方式上带来了革命性的变化。它的速度、多功能性和各种功能使得开发人员能够构建高性能的应用程序。通过深入理解Redis的基本概念、探索其用例以及实施最佳实践,您可以利用Redis的强大功能来创建出能够满足当今技术环境要求的高效、响应迅速的应用程序。