当前位置: 首页 > news >正文

网站备案系统登录企业方案

网站备案系统登录,企业方案,茶庄网站模板,永济做网站单价目录 一、Redis的应用场景 1、限流 2、分布式锁 3、点赞 4、消息队列 二、Redis类型的命令及用法 1、String类型 2、Hash类型 3、List类型 4、Set类型 5、Zset类型 6、Redis工具类 Redis使用缓存的目的就是提升读写性能 实际业务场景下,我们就可以把 Mys…

目录

一、Redis的应用场景

1、限流

2、分布式锁

3、点赞

4、消息队列

二、Redis类型的命令及用法

1、String类型

2、Hash类型

3、List类型

4、Set类型

 5、Zset类型

 6、Redis工具类


Redis使用缓存的目的就是提升读写性能

实际业务场景下,我们就可以把 Mysql 中的热点数据缓 存到 Redis 中,提升读取性能,同时也减轻了 Mysql 的读取压力

一、Redis的应用场景

Redis除了做缓存以外,还可以用

  • 限流
  • 分布式锁
  • 点赞/排行榜
  • 消息队列

还有其他场景:计数器、互关好友、购物车和商品标签等等

1、限流

利用Redis的过期键和计数器功能,实现API的限流功能,防止服务被滥用

方法一记录IP在某个时间段访问某接口的次数

使用IP作为Key和其他信息作为Key,访问次数作为Value,访问一次Incr增加一次,超过规定次数则返回false

但问题是:限流时间段是固定的

比如:某接口在1分钟内请求次数不超过1000次

就是00:59分,用户已经访问了999次,1:00key值过期,1:01又访问了999次

看起来好像是没问题,但是00:59—1:01的仅2s时间段内,接口被访问了1000+999次,明显错误

方法二滑动窗口

为了避免方法一种由于key过期导致短期内访问量增大的情况,将时间改成动态的

在每次接口访问时,记录当前访问的时间点,并计算前1min内用户访问该接口的总次数,如果总次数大于1000次,则不允许用户访问该接口

以上两种利用redis实现限流的方式基本能满足我们大部分的业务需要,对于部分要求限流粒度更高更准的业务,可以引入Sentinel来满足业务需要

2、分布式锁

为什么使用分布式锁?

在单机部署的时候,可以使用 Java 中提供的 JUC 锁机制避免多线程同时操作一个共享变量产生的安全问题,通过锁(synchronzied 或 lock)来锁住自己的线程资源,从而防止缓存击穿

Redis的缓存问题:缓存穿透、缓存击穿和缓存雪崩-CSDN博客

这是一种本地加锁的方式,在分布式情况下会带来数据不一致的问题

比如:服务 A 获取数据后,更新缓存 key =100,服务 B 不受服务 A 的锁限制,并发去更新缓存 key = 99,最后的结果可能是 99 或 100,但这是一种未知的状态,与期望结果不一致

①基础版

Redis的SET命令有一个NX参数,可以实现「key不存在才插入」,因此可以用它来实现分布式锁:

SetNX(key,value)

redisTemplate.opsForValue().setIfAbsent(“k”, “v”)

也就是 

SET lockKey requestId NX PX expireTime
  • lockKey 表示锁的资源,

  • requestId 全局唯一的业务id,避免存在加锁和释放锁乱掉的情况

  • NX:表示只有 lockKey 不存在的时候才能 SET 成功,从而保证只有一个客户端可以获得锁。

  • PX expireTime设置锁的超时时间,单位是毫秒;也可以使用 EX seconds以秒为单位设置超时时间

伪代码:

try {if (jedis.set(lockKey, requestId, "NX", "PX", expireTime))) {//业务处理return true;}
} finally{//判断是不是当前线程加的锁,是才释放if(requestd.equals.(jedis.get(lockKey))){//释放锁unlock(lockKey,requestId);}
}  
return false;

②Redisson实现

Redisson 是 Redis 的 Java 客户端之一,支持原子性加/解锁、锁重试、可重入锁、RedLock 等功能

// 获取分布式锁
RLock lock = redissonClient.getLock("myLock");
try {// 尝试加锁,最多等待 10 秒,加锁后的锁有效期为 30 秒boolean locked = lock.tryLock(10, 30, TimeUnit.SECONDS);if (locked) {// 成功获取锁,执行业务逻辑System.out.println("获取锁成功,执行业务逻辑...");} else {// 获取锁失败,可能是超时等待或者其他原因System.out.println("获取锁失败...");}
} catch (InterruptedException e) {e.printStackTrace();
} finally {// 释放锁lock.unlock();// 关闭 Redisson 客户端redissonClient.shutdown();
}

Redisson存储分布式锁是通过Hash结构进行存储的,内置的键值对是< 线程标识,重入次数>,其中重入次数便可用于实现可重入机制

3、点赞

点赞就需要用到Redis的Set类型,Set类型是Redis中的一个无序集合,它可以存储一组字符串元素,并且每个元素都是唯一的

【点赞】SADD key member:向集合中添加一个或多个元素

 redisTemplate.opsForSet().add(key, values)

【取消点赞】SREM key:删除元素

redisTemplate.opsForSet().remove(key,value)

【点赞的所有用户】SMEMBERS key:返回集合中的所有元素

 redisTemplate.opsForSet().members(key)

【是否点赞】SISMEMBER key member:判断元素是否在集合中

redisTemplate.opsForSet().isMember(key, value)

【点赞数】scard(key):元素长度

redisTemplate.opsForSet().size(key)

场景:对活动的相册图片进行点赞且对点赞数量进行计数的功能

public void like(Long activityId) {LzmUserInfo userInfo = UserContextHolder.getLzmUserInfo();String key = ACTIVITY.ACTIVITY_LIKE_KEY + activityId;Boolean member = stringRedisTemplate.opsForSet().isMember(key, userInfo.getUserId().toString());if (BooleanUtil.isFalse(member)) {//未点赞,点赞数+1this.update(Wrappers.<ActivityManageEntity>lambdaUpdate().setSql("like_num = like_num + 1").eq(ActivityManageEntity::getActivityId, activityId).eq(ActivityManageEntity::getIsDelete, IsDeleteEnum.NORMAL.getCode()));redisTemplate.opsForSet().add(key, userInfo.getUserId().toString());} else {//取消点赞,点赞数-1this.update(Wrappers.<ActivityManageEntity>lambdaUpdate().setSql("like_num = like_num - 1").gt(ActivityManageEntity::getLikeNum, 0).eq(ActivityManageEntity::getActivityId, activityId).eq(ActivityManageEntity::getIsDelete, IsDeleteEnum.NORMAL.getCode()));redisTemplate.opsForSet().remove(key, userInfo.getUserId().toString());}}

4、消息队列

Redis可以实现简单的队列。在生产者端,使用LPUSH加入到某个列表中;在消费端,不断的使用RPOP指令取出这些数据,或者使用阻塞的BRPOP指令获取数据,用于处理异步任务,例如邮件发送、后台任务处理,小规模的抢购需求等

场景:邮件发送

生产者发布消息

LPUSH queue msg1

 消费者 拉取消息

RPOP queue

二、Redis类型的命令及用法

1、String类型

操作命令用法
设置set(“k”,“v”)template.opsForValue().set(“k”,“v”)
获取get(“k”)template.opsForValue().get(“k”)
增1incr(“k”)template.boundValueOps(“k”).increment(1)
减1decr(“k”)template.boundValueOps(“k”).increment(-1)
设置时效setex(“k”,seconds,“v”)template.opsForValue().set(“k”,“v”,20, TimeUnit.SECONDS)
key不存在就设置setnx(“k”,“v”)template.opsForValue().setIfAbsent(“k”, “v”)
获取key过期时间ttl(“k”)template.getExpire(“k”)
删除del(“k”)template.delete(“k”)

2、Hash类型

操作命令用法
设置hset(“k1”,“k2”,“k3”)template.opsForHash().put(“k1”,“k2”,“k3”)
获取hget(“k1”,“k2”)template.opsForHash().get(“k1”,“k2”) /template.opsForHash().values(“k1”)
删除hdel(“k1”,“k2”)template.opsForHash().delete(“k1”,“k2”)
是否存在hexists(“k1”,“k2”)template.opsForHash().hasKey(“k1”,“k2”)

3、List类型

操作命令用法
从右侧添加rpush(“k”,“v”)template.opsForList().rightPush(“k”,“v”)
从右侧移除rpop(“list”)template.opsForList().rightPop(“k”)
长度llen(“k”)template.opsForList().size(“k”)
获取指定范围的元素lrange(“list”,0,-1)  -1指全部template.opsForList().range(“list”, 0, -1)

4、Set类型

操作命令用法
添加sadd(“k”,“v”)template.opsForSet().add(“k”,“v”)
值移除srem(“k”,“v”)template.opsForSet().remove(“k”,“v”)
直接移除spop(“k”)template.opsForSet().pop(“k”)
获取所有smembers("k")template.opsForSet().members("k")
是否存在sismember("k")emplate.opsForSet().isMember("k","v")
长度scard(“k”)template.opsForSet().size(“k”)
交集sinter(“k1”,“k2” )template.opsForSet().intersect(“k1”, “k2”)
并集sunion(“k1”,“k2” )template.opsForSet().union(“k1”, “k2”)
差集sdiff(“k1”,“k2” )template.opsForSet().difference(“k1”, “k2”)

 5、Zset类型

操作命令用法
增加zadd(“k”,1,“a”)template.opsForZSet().add(“k”,“1”,a)
排名结果zrevrange(“k”, 0, -1)template.opsForZSet().reverseRange(“k”, 0, -1)
排名分数

zrevrangeByScoreWithScores(“k”, 1, 10);

template.opsForZSet().reverseRangeByScore(“k”, 1, 100)
修改分数zincrby(“k”,20,“a”)template.opsForZSet().incrementScore(“k”,“20”,a)
数量zcard(“k”)template.opsForZSet().zCard(“k”)
获取排名zrank(“k”,“a”)template.opsForZSet().rank(“k”,“a”)

 6、Redis工具类

@Component
public class RedisUtils {@Resourceprivate RedisTemplate<String, Object> redisTemplate;/*** 添加数据*/public void set(String key, Object value) {redisTemplate.opsForValue().set(key, value);}/*** 如果key不存在,则设置key的值为value并返回true,否则返回false*/public boolean setNx(String key, String value) {return Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(key, value));}/*** 如果key不存在,则设置key的值为value以及过期时间,并返回true,否则返回false,*/public boolean setNx(String key, String value, long timeout, TimeUnit unit) {return Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(key, value, timeout, unit));}/*** 根据key获取数据*/public Object get(String key) {return redisTemplate.opsForValue().get(key);}/*** 根据key删除数据*/public void delete(String key) {redisTemplate.delete(key);}/*** 向集合中添加一个或多个元素*/public void add(String key, Object... values) {redisTemplate.opsForSet().add(key, values);}/*** 将 value 插入到 key 对应的列表的头部*/public void leftPush(String key, Object value) {//。redisTemplate.opsForList().leftPush(key, value);}/*** 将 value 插入到 key 对应的列表的尾部*/public void rightPush(String key, Object value) {redisTemplate.opsForList().rightPush(key, value);}/*** 从 key 对应的列表的头部删除并返回一个元素*/public Object leftPop(String key) {return redisTemplate.opsForList().leftPop(key);}/*** 从 key 对应的列表的尾部删除并返回一个元素*/public Object rightPop(String key) {return redisTemplate.opsForList().rightPop(key);}/*** 返回列表中指定范围内的元素*/public List<Object> range(String key, long start, long end) {return redisTemplate.opsForList().range(key, start, end);}/*** 返回集合中的所有元素*/public Set<Object> members(String key) {return redisTemplate.opsForSet().members(key);}/*** 判断元素是否在集合中*/public Boolean isMember(String key, Object value) {return redisTemplate.opsForSet().isMember(key, value);}/*** 向有序集合中添加一个元素并指定分数*/public void add(String key, double score, Object value) {redisTemplate.opsForZSet().add(key, value, score);}/*** 获取指定score范围内元素*/public Set<ZSetOperations.TypedTuple<Object>> rangeWithScores(String key, long start, long end) {return redisTemplate.opsForZSet().rangeWithScores(key, start, end);}
}

http://www.yayakq.cn/news/15860/

相关文章:

  • 温州网站开发服务商如何选择郑州网站建设
  • 手机商城网站系统城乡企业建设部网站
  • 购物网站哪个便宜seo快速推广
  • 查看网站 vps简单网站开发流程图
  • 餐馆网站模板重庆建筑工程
  • 做设计挣钱的网站wordpress如何添加二级菜单
  • 网站建设带支付源码菏泽做公司简介网站
  • 任丘做网站价格软件系统开发平台
  • 外国优秀设计网站推荐中国互联网协会
  • 做网站什么都不懂 怎么做网站功能需求列表
  • 广东省建设见证员网站宠物网站开发与实现
  • 莱芜益寿堂网站如何自己免费创建网站
  • 网站建设应用程序开发nginx wordpress 固定链接 404
  • 个人备案能做公司网站吗重庆建设网站首页
  • 网站开发完没人运营企业门户网站建设方案文档
  • asp手机网站统计代码wordpress数据库教程
  • 做个网站设计多少钱做论坛和做网站有什么区别
  • 成都网站设计精选柚v米科技广告发布合同
  • 电子商务网站建设与维护考试题宁德网站建设51yunsou
  • 网站群建设工作网站建设免费按词收费
  • 安阳企业网站建设公司购物网站建设源码
  • 专业购物网站建设报价商业网站开发岗位需求分析
  • 门户网站 模板杭州专业的网站制作成功案例
  • 门户网站建设方案ppt冯耀宗seo博客
  • 外部网站跳转小程序全国备案网站数量
  • 怎么给网站做关键词排名罗源城乡建设网站
  • 传统企业营销型网站建设做电影网站程序哪个好
  • 精品课网站怎么做wordpress删除用户下所有文章
  • 网站右侧 回到顶部wordpress不支持apk
  • 产品展示的手机网站希音跨境电商官网