wordpress站点获利,宣传片拍摄手法有哪些,电子元器件做哪个网站好,wordpress识别环境的文件夹目录
一、Redis的应用场景
1、限流
2、分布式锁
3、点赞
4、消息队列
二、Redis类型的命令及用法
1、String类型
2、Hash类型
3、List类型
4、Set类型 5、Zset类型 6、Redis工具类 Redis使用缓存的目的就是提升读写性能
实际业务场景下#xff0c;我们就可以把 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时间段内接口被访问了1000999次明显错误
方法二滑动窗口
为了避免方法一种由于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.ActivityManageEntitylambdaUpdate().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.ActivityManageEntitylambdaUpdate().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 RedisTemplateString, 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 ListObject range(String key, long start, long end) {return redisTemplate.opsForList().range(key, start, end);}/*** 返回集合中的所有元素*/public SetObject 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 SetZSetOperations.TypedTupleObject rangeWithScores(String key, long start, long end) {return redisTemplate.opsForZSet().rangeWithScores(key, start, end);}
}