Redis 初级使用

博文目录


常用数据结构

Redis常用的5种数据结构分别是, string, hash, list, set, zset, 其中string是基本数据类型, 其他4种都是基于string的某种容器, 其内部将一些string按照某种结构组织起来, 提供了便于访问内部string的各种api

Redis官网
Redis官网文档
Redis官网基本命令文档

有一些Api是基于不同数据结构使用的, 有一些Api是公用的, 适用于多种数据结构, 如 del, exists, expire, keys, ttl, type, rename, scan 等命令

string

Redsi官网文档 string get 命令

在这里插入图片描述
在从Redis中获取值然后转换成Java基本数据类型时会有类型转换异常的问题

/**
 * get
 *
 * 通过Json转换后,基本数据类型会被反序列化为默认的类型(Integer和Float),
 * 存Byte,Short,Long取出来是Integer,存Double取出来是Float,可能还有其他的,
 * 需要做特殊处理(我甚至怀疑使用JdkSerializationRedisSerializer会更好,虽然不利于查看,但是会携带类型等信息,api使用会比较方便)
 * 需要明确存储时使用的类型,滥用可能会导致精度丢失
 *
 * String value = (String) redis.get("key");
 * List<String> values = (List<String>) redis.get("key");
 */
@SuppressWarnings("unchecked")
public <T> T get(String key, Class<T> clazz) {
	Object object = redisTemplate.opsForValue().get(key);
	if ((clazz == Long.class || clazz == long.class) && object instanceof Integer) {
		Integer integerObject = (Integer) object;
		return (T) Long.valueOf(integerObject.longValue());
	} else if ((clazz == Short.class || clazz == short.class) && object instanceof Integer) {
		Integer integerObject = (Integer) object;
		return (T) Short.valueOf(integerObject.shortValue());
	} else if ((clazz == Byte.class || clazz == byte.class) && object instanceof Integer) {
		Integer integerObject = (Integer) object;
		return (T) Byte.valueOf(integerObject.byteValue());
	} else if ((clazz == Float.class || clazz == float.class) && object instanceof Double) {
		Double doubleObject = (Double) object;
		return (T) Float.valueOf(doubleObject.floatValue());
	} else if ((clazz == Character.class || clazz == char.class) && object instanceof String) {
		String StringObject = (String) object;
		return (T) Character.valueOf(StringObject.charAt(0));
	} else {
		return (T) object;
	}
}

场景

单值缓存
缓存页面的访问次数

对象缓存
缓存某配置项的对象 (建议配置好Spring的StringRedisSerializer和GenericJackson2JsonRedisSerializer, 直接存储和获取对象本身, 无需自行转换Json)

分布式锁
最基本的 setNX

计数器
电商项目中, 存储某个商品库存

session共享

分布式全局序列号
incrby, 一次一个太浪费, 可一次多个, 本地缓存, 用完再取

hash

类似Map

场景

对象缓存
一个字段当做一个内Key

电商购物车
以用户标识为Key, 以商品标识为Field, 商品数量为Value
操作: 添加商品-hset, 增加数量-hincrby, 商品总数-hlen, 删除商品-hdel, 获取所有-hgetall

优点

  1. 同类数据归类整合存储, 方便数据管理
  2. 相比string, 操作消耗的内存和cpu更少
  3. 相比string, 存储更节省空间

缺点

  1. 过期功能只能使用在Key上, 不能使用在Field上
  2. Redis集群结构下, 使用需要考虑数据平衡, 防止大key产生

list

类似List, 有序

可以实现Stack, Queue, BlockingQueue 的效果

  • Stack: lpush + lpop
  • Queue: lpush + rpop
  • BlockingQueue: lpush + brpop

场景

消息流, 如微博消息和微信公众号消息
假如我(mrathena)关注了XCIOS和备胎说车两个微信公众号, 微信给每个用户都单独维护了一个list(我的list的key是msg:mrathena)

  • XCIOS发布了一篇文章, lpush msg:mrathena 文章id
  • 备胎说车发布了一篇文章, lpush msg:mrathena 文章id
  • 我查看微信公众号消息, lrange msg:mrathena 0 4

如果粉丝太多或者关注了太多的人, 可以配合push和pull两种模式, 可以先给在线用户push, 后面再分批给其他用户push, 或者直接等用户上线时自己到大v的list中获取其最新消息, …

set

类似 Set, 无序

除了常规操作还有取交集, 并集, 差集的功能

  • 取交集: sinter key1 key2
  • 取交集并把结果存到新key中: sinterstore newKey key1 key2
  • 取并集: sunion key1 key2, sunionstore newKey key1 key2
  • 取差集(从key1中减去后面所有集合的并集): sdiff key1 key2 key3 [key …], sdiffstore newKey key1 key2

场景

抽奖
年会现场抽奖, 假如要从所有人中抽3个三等奖, 2个二等奖, 1个一等奖, 每个人只有一次获奖机会

  • 把每一个员工加入到集合中 - sadd key mrathena
  • 查看参与抽奖的员工 - smembers key
  • 抽取count名获奖者(可再被抽到) - srandmember key count
  • 抽取count名获奖者(不可再被抽到) - spop key count

点赞,收藏
微信朋友圈, 假如我发了一个朋友圈(我的消息id是101)

  • 点赞 - sadd like:101 点赞用户id
  • 取消但咱 - srem like:101 点赞用户id
  • 判断用户是否点赞过 - sismember like:101 用户id
  • 获取点赞的用户列表(zset有序) - smembers like:101
  • 获取点赞用户数 - scard like:101

关注模型
微博关注, 我关注了张靓颖, 我和她有共同关注, 我关注的人也关注她
假如aSet关注了bc,bSet关注了acdef,cSet关注了abce,dSet关注了cf, 我是a, 我当前在看d的信息

  1. a和d的共同关注 - sinter aSet dSet - c
  2. a关注的人也关注他(d) - sismember bSet d, sismember cSet d
  3. a可能认识的人(d比我多关注的人) - sdiff dset aSet - f

电商商品筛选
sadd brand:huawei p40
sadd brand:xiaomi mi10
sadd brand:iphone iphone12
sadd os:android p40 mi10
sadd cpu:gaotong p40 mi10
sadd ram:6g p40 mi10 iphone12pro

  • 查找符合条件6g运存,安卓系统,高通cpu的手机 - sinter os:android cpu:gaotong ram:6g - p40,mi10

zset

和 set 一样, 只不过每个元素都加了一个 score 属性, 可排序, 可以为操作该分值

场景

排行榜
微博热搜

  • 点击新闻 - zincrby hotnews:20201030 1 iphone12
  • 展示当日排行前十 - zrevrange hotnews:20201030 0 9 withscore
  • 三日榜单统计 - zunionstore hotnews:20201028-20201030 hotnews:20201028 hotnews:20201029 hotnews:20201030
  • 三日榜单前十 - zrevrange hotnews:20201028-20201030 0 9 withscore

公共命令

Redis官网文档 公共 del 命令

其他公共命令在该命令的相关命令中

keys

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

scan

SCAN cursor [MATCH pattern] [COUNT count]

渐进式遍历键, 第一次遍历时, cursor值为0, 然后将返回结果中的第一个整数值作为下一次遍历的cursor, 一直遍历到返回的cursor的值为0

在scan的过程中如果有键的增删改或者rehash操作调整redis的存储结构等变化, 遍历可能会出现丢失key, 重复key等情况, 需要考虑

有三个参数

  • cousor: 游标, 即hash桶的索引值
  • pattern: key的正则匹配模式
  • count: 一次遍历的key的数量(是从所有key中取count个返回其中满足条件的, 并不是取出count个满足条件的, 参考值, 或多或少)

info

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

  • Server: 服务器运行的环境参数
  • Clients: 客户端相关信息
  • Memory: 服务器运行内存统计数据
  • Persistence: 持久化信息
  • Stats: 通用统计数据
  • Replication: 主从复制相关信息
  • CPU: CPU 使用情况
  • Cluster: 集群信息
  • KeySpace: 键值对统计数量信息
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时的淘汰策略
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值