Redis数据结构及使用场景

说明

  • 在redis客户端命令行中,可通过help @命令查看该命令的具体用法
  • redis命令忽略大小写
  • 一般pop都是取出元素并删除

字符串String

语法

常用操作:

# 存入字符串键值对
SET key value

# 批量存储字符串键值对
MSET key value [key value ...]

# 存入一个不存在的字符串键值对,设置成功返回1,设置失败返回0
SETNX key value

# 获取一个字符串键值
GET key

# 批量获取字符串键值
MGET key [key ...]

# 删除一个键
DEL key [key ...]

# 设置一个键的过期时间(秒),到期删除该key
EXPIRE key seconds

原子操作:

# 将key中储存的数字值加1
INCR key

# 将key中储存的数字值减1
DECR key

# 将key所储存的值加上increment
INCRBY key increment

# 将key所储存的值减去decrement
DECRBY key decrement

如果操作的不是int值,则会报错。

使用场景

  • 单值缓存
  • 对象缓存
# value为json格式数据
SET user:1 value

# 通过命名来装置对象
MSET user:1:name jay user:1:age 44
MGET user:1:name user:1:age
  • 分布式锁
# 返回1代表获取锁成功,返回0代表获取锁失败
SETNX product:10001 true

执行业务操作。。。

# 执行完业务释放锁
DEL product:10001

# 防止程序意外终止导致死锁,添加key过期时间,到期后自动删除释放锁
SET product:10001 true ex 10 nx
  • 计数器
# 记录文章浏览次数
INCR article:readcount:{文章id}

# 查看文章浏览次数
GET article:readcount:{文章id} 
  • session共享

spring session + redis实现session共享。

  • 分布式系统全局序列号
# redis批量生成序列号提升性能
INCRBY orderId 1000

哈希Hash

语法

常用操作:

# 存储一个哈希表key的键值
HSET key field value

# 存储一个不存在的哈希表key的键值,成功返回1,失败返回0
HSETNX key field value

# 在一个哈希表key中存储多个键值对
HMSET key field value [field value ...]

# 获取哈希表key对应的field键值
HGET key field

# 批量获取哈希表key中多个field键值
HMGET key field [field ...]

# 删除哈希表key中的field键值
HDEL key field [field ...]

# 返回哈希表key中field的数量
HLEN key

# 返回哈希表key中所有的键值
HGETALL key

# 为哈希表key中field键的值加上增量increment
HINCRBY key field increment

使用场景

  • 对象缓存
# key看成表,field看成对应字段唯一标识,value看成字段值
HMSET user {userId}:name jay {userId}:age 44
HMSET user 1:name jay 1:age 44
HMGET user 1:name 1:age

表图示:
Redis数据结构及使用场景_第1张图片

  • 电商购物车
# 说明:
# 以用户id为key
# 商品id为field
# 商品数量为value

# 购物车操作:
# 添加商品
hset cart:1001 10088 1
# 增加数量
hincrby cart:1001 10088 1
# 商品总数
hlen cart:1001
# 删除商品
hdel cart:1001 10088
# 获取购物车所有商品
hgetall cart:1001

优缺点

优点:
1)同类数据归类整合储存,方便数据管理
2)相比string操作消耗内存与cpu更小
3)相比string储存更节省空间

缺点:
1)过期功能不能使用在field上,只能用在key上
2)Redis集群架构下不适合大规模使用

列表List

语法

常用操作:

# 将一个或多个值value插入到key列表的表头(最左边)
LPUSH key value [value ...]

# 将一个或多个值value插入到key列表的表尾(最右边)
RPUSH key value [value ...]

# 移除并返回key列表的头元素
LPOP key

# 移除并返回key列表的尾元素
RPOP key

# 返回列表key中指定区间内的元素,区间以偏移量start和stop指定
LRANGE key start stop

# 从key列表表头弹出一个元素,若列表中没有元素,阻塞等待
# timeout秒,如果timeout=0,一直阻塞等待
BLPOP key [key ...] timeout

# 从key列表表尾弹出一个元素,若列表中没有元素,阻塞等待
# timeout秒,如果timeout=0,一直阻塞等待
BRPOP key [key ...] timeout

常用数据结构:

Stack() = LPUSH + LPOP
Queue(队列)= LPUSH + RPOP
Blocking MQ(阻塞队列)= LPUSH + BRPOP

使用场景

  • 微博或微信公众号消息推送

Jay关注Jolin和Quinlivan的微博:

# Jolin发布微博时,消息id为1000
LPUSH msg:Jay_userid 1000

# 昆凌发布微博时,消息id为1001
LPUSH msg:Jay_userid 1001

# Jay查看最新微博消息
LRANGE msg:Jay_userid 0 10

集合Set

语法

常用操作:

# 往集合key中存入元素,元素存在则忽略,若key不存在则新建
SADD key member [member ...]

# 从集合key中删除元素
SREM key member [member ...]

# 获取集合key中所有元素
SMEMBERS key

# 获取集合key的元素个数
SCARD key

# 判断member元素是否存在于集合key中
SISMEMBER key member

# 从集合key中选出count个元素,元素不从key中删除
SRANDMEMBER key [count]

# 从集合key中选出count个元素,元素从key中删除
SPOP key [count]

运算操作:

# 交集运算
SINTER key [key ...]
# 将交集结果存入新Set集合destination中
SINTERSTORE destination key [key ..]

# 并集运算
SUNION key [key ..]
# 将并集结果存入新Set集合destination中
SUNIONSTORE destination key [key ...]

# 差集运算
SDIFF key [key ...]
# 将差集结果存入新Set集合destination中
SDIFFSTORE destination key [key ...]

使用场景

  • 微信小程序抽奖
# 点击参与抽奖,自动去重
sadd key userid
# 查看参与抽奖所有用户
smembers key
# 随机抽取3名幸运用户
srandmember key 3
# 如果已参与抽奖用户不能继续抽奖
spop key 3
  • 鱼吧点赞、收藏、标签

# 点赞
sadd msg:like:1000 userid
# 取消点赞
srem msg:like:1000 userid
# 检查用户是否点过赞,用于当前用户打开该页面时点赞按钮是否高亮
sismember msg:like:1000 userid
# 获取点赞的用户列表
smembers msg:like:1000
# 获取点赞用户数
scard msg:like:1000

# 共同关注
sinter user:followers:userid_01 user:followers:userid_02
# 我关注的人也关注他
sismember user:followers:userid_01 jay
# 我可能认识的人
sdiff user:followers:userid_01 user:followers:userid_02

有序集合ZSet

语法

常用操作:

# 往有序集合key中加入带分值元素
ZADD key score member [[score member]]

# 从有序集合key中删除元素
ZREM key member [member …]

# 返回有序集合key中元素member的分值
ZSCORE key member

# 为有序集合key中元素member的分值加上increment
ZINCRBY key increment member

# 返回有序集合key中元素个数
ZCARD key

# 正序获取有序集合key从start下标到stop下标的元素
ZRANGE key start stop [WITHSCORES]

# 倒序获取有序集合key从start下标到stop下标的元素
ZREVRANGE key start stop [WITHSCORES]

集合操作:

# 并集计算
ZUNIONSTORE destkey numkeys key [key ...]
# 交集计算
ZINTERSTORE destkey numkeys key [key …]

使用场景

  • 排行榜

# 点击动态
ZINCRBY hostMsgs:20220819 1 msg:1000
# 展示当日排行前十
ZREVRANGE hostMsgs:20220819 0 9 WITHSCORES 
# 七日搜索榜单计算
ZUNIONSTORE hostMsg:20220813-20220819 7 hostMsgs:20220813  hostMsgs:20220814... hostMsgs:20220819
# 展示七日排行前十
ZREVRANGE hostMsgs:20220813-20220819  0  9  WITHSCORES

redis命令

keys

全量遍历键。
用来列出所有满足特定正则字符串规则的key,当redis数据量比较大时,性能比较差,要避免使用

# 列出所有key
keys *

# 列出前缀为user的所有key
keys user*

# 列以user开头,id结尾的所有key
keys user*id

示例:

127.0.0.1:6379> keys user:*
1) "user:3"
2) "user:4"
3) "user:2"
4) "user:5"
5) "user:6"
6) "user:1"

scan

渐进式遍历key,可以替代keys,建议使用

SCAN cursor [MATCH pattern] [COUNT count] 

参数说明:
cursor,整数值,hash桶的索引值
[MATCH pattern],key 的正则模式
[COUNT count],一次遍历的key的数量,参考值,底层遍历的数量不一定,并不是符合条件的结果数量。

注意:
scan并非完美无瑕,如果在scan的过程中有键的变化(增加、 删除、 修改) ,那么遍历效果可能会碰到如下问题:新增的键可能没有遍历到,遍历出了重复的键等情况,也就是说scan并不能保证完整地遍历出所有的键,这些是我们在开发时需要考虑的。

示例:
Redis数据结构及使用场景_第2张图片
第一次遍历时,cursor 值为 0,然后将返回结果中第一个整数值作为下一次遍历的 cursor。一直遍历到返回的 cursor 值为 0 时结束。

info

查看redis服务运行信息,分为 9 大块,每个块都有非常多的参数。

这 9 个块分别是:

  • Server 服务器运行的环境参数
  • Clients 客户端相关信息
  • Memory 服务器运行内存统计数据
  • Persistence 持久化信息
  • Stats 通用统计数据
  • Replication 主从复制相关信息
  • CPU CPU 使用情况
  • Cluster 集群信息
  • KeySpace 键值对统计数量信息

示例:

127.0.0.1:6379> info
# Server
redis_version:5.0.3
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:ac8e080269e636db
redis_mode:standalone
os:Linux 3.10.0-1160.92.1.el7.x86_64 x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:4.8.5
process_id:31959
run_id:672d37cbed3fc6180c3df126cdce18c2ee14b841
tcp_port:6379
uptime_in_seconds:40410
uptime_in_days:0
hz:10
configured_hz:10
lru_clock:13778700
executable:/usr/local/redis-5.0.3/src/./redis-server
config_file:/usr/local/redis-5.0.3/redis.conf

# Clients
connected_clients:1
client_recent_max_input_buffer:2
client_recent_max_output_buffer:0
blocked_clients:0

# Memory
used_memory:1359032
used_memory_human:1.30M
used_memory_rss:11472896
used_memory_rss_human:10.94M
used_memory_peak:4860120
used_memory_peak_human:4.63M
used_memory_peak_perc:27.96%
used_memory_overhead:841894
used_memory_startup:791032
used_memory_dataset:517138
used_memory_dataset_perc:91.05%
allocator_allocated:1762376
allocator_active:2060288
allocator_resident:8593408
total_system_memory:3972710400
total_system_memory_human:3.70G
used_memory_lua:37888
used_memory_lua_human:37.00K
used_memory_scripts:0
used_memory_scripts_human:0B
number_of_cached_scripts:0
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
allocator_frag_ratio:1.17
allocator_frag_bytes:297912
allocator_rss_ratio:4.17
allocator_rss_bytes:6533120
rss_overhead_ratio:1.34
rss_overhead_bytes:2879488
mem_fragmentation_ratio:8.71
mem_fragmentation_bytes:10156080
mem_not_counted_for_evict:0
mem_replication_backlog:0
mem_clients_slaves:0
mem_clients_normal:49694
mem_aof_buffer:0
mem_allocator:jemalloc-5.1.0
active_defrag_running:0
lazyfree_pending_objects:0

# Persistence
loading:0
rdb_changes_since_last_save:6
rdb_bgsave_in_progress:0
rdb_last_save_time:1691499755
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:4554752
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:0

# Stats
total_connections_received:905
total_commands_processed:1800161
instantaneous_ops_per_sec:0
total_net_input_bytes:96406387
total_net_output_bytes:1317127498
instantaneous_input_kbps:0.00
instantaneous_output_kbps:0.00
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:1
expired_stale_perc:0.00
expired_time_cap_reached_count:0
evicted_keys:0
keyspace_hits:500053
keyspace_misses:4
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:655
migrate_cached_sockets:0
slave_expires_tracked_keys:0
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0

# Replication
role:master
connected_slaves:0
master_replid:4292fd12d5801e12b6335388d5cff9054950c134
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

# CPU
used_cpu_sys:28.435130
used_cpu_user:30.810385
used_cpu_sys_children:0.024317
used_cpu_user_children:0.009445

# Cluster
cluster_enabled:0

# Keyspace
db0:keys=22,expires=0,avg_ttl=0

重点参数解释:

connected_clients:2                  # 正在连接的客户端数量

instantaneous_ops_per_sec:789        # 每秒执行多少次指令

used_memory:929864                   # Redis分配的内存总量(byte),包含redis进程内部的开销和数据占用的内存
used_memory_human:908.07K            # Redis分配的内存总量(Kb,human会展示出单位)
used_memory_rss_human:2.28M          # 向操作系统申请的内存大小(Mb)(这个值一般是大于used_memory的,因为Redis的内存分配策略会产生内存碎片)
used_memory_peak:929864              # redis的内存消耗峰值(byte)
used_memory_peak_human:908.07K       # redis的内存消耗峰值(KB)

maxmemory:0                         # 配置中设置的最大可使用内存值(byte),默认0,不限制,一般配置为机器物理内存的百分之七八十,需要留一部分给操作系统
maxmemory_human:0B                  # 配置中设置的最大可使用内存值
maxmemory_policy:noeviction         # 当达到maxmemory时的淘汰策略

你可能感兴趣的:(分布式微服务,redis,数据结构,使用场景,命令)