个人网站推广 公司,温州网站建设有限公司,建个什么网站赚钱,微信微网站统计引言
在现代分布式系统中#xff0c;Redis 作为高性能的键值存储系统#xff0c;广泛应用于缓存、消息队列、实时计数器等多种场景。然而#xff0c;在高并发和分布式环境下#xff0c;如何有效地管理和控制资源访问成为一个关键问题。Redis 分布式锁正是为了解决这一问题…引言
在现代分布式系统中Redis 作为高性能的键值存储系统广泛应用于缓存、消息队列、实时计数器等多种场景。然而在高并发和分布式环境下如何有效地管理和控制资源访问成为一个关键问题。Redis 分布式锁正是为了解决这一问题而诞生的技术。
本文将从 Redis 的数据结构应用入手结合 Redisson 分布式锁的实现深入探讨如何解决常见的缓存问题如穿透、击穿、雪崩并提供详尽的代码示例和注释。
一、Redis 数据结构应用
Redis 提供了多种数据结构每种数据结构都有其特定的应用场景。以下是几种常见数据结构及其典型应用场景
1. String字符串
应用场景适用于简单的键值存储如用户会话、计数器等。示例代码
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service; Service
public class CounterService {Autowired private StringRedisTemplate stringRedisTemplate;public void incrementCounter(String key) {stringRedisTemplate.opsForValue().increment(key, 1);}public Long getCounter(String key) {return stringRedisTemplate.opsForValue().get(key); }
} increment(key, 1)原子递增计数器。get(key)获取计数器的值。
2. List列表
应用场景适用于队列或栈结构如消息队列、任务队列等。示例代码
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service; Service
public class QueueService {Autowired private RedisTemplateString, String redisTemplate;public void addToQueue(String queueName, String message) {ListOperationsString, String listOps redisTemplate.opsForList(); listOps.rightPush(queueName, message);}public String removeFromQueue(String queueName) {ListOperationsString, String listOps redisTemplate.opsForList(); return listOps.leftPop(queueName); }
} rightPush(queueName, message)将消息添加到队列尾部。leftPop(queueName)从队列头部取出消息。
3. Hash哈希
应用场景适用于存储对象或映射表如用户信息、商品详情等。示例代码
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service; Service
public class UserService {Autowired private RedisTemplateString, Object redisTemplate;public void saveUser(String userId, MapString, Object userMap) {HashOperationsString, String, Object hashOps redisTemplate.opsForHash(); hashOps.putAll(userId, userMap);}public MapString, Object getUser(String userId) {HashOperationsString, String, Object hashOps redisTemplate.opsForHash(); return hashOps.entries(userId); }
} putAll(userId, userMap)将用户信息存储到哈希中。entries(userId)获取用户的完整信息。
4. Set集合
应用场景适用于存储唯一元素的集合如用户关注列表、标签分类等。示例代码
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service; Service
public class TagService {Autowired private RedisTemplateString, String redisTemplate;public void addTagToUser(String userId, String tag) {SetOperationsString, String setOps redisTemplate.opsForSet(); setOps.add(userId, tag);}public SetString getAllTags(String userId) {SetOperationsString, String setOps redisTemplate.opsForSet(); return setOps.members(userId); }
}
add(userId, tag)向用户的标签集合中添加一个标签。members(userId)获取用户的全部标签。
5. ZSet有序集合
应用场景适用于需要排序的场景如排行榜、优先级队列等。示例代码
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service; Service
public class RankingService {Autowired private RedisTemplateString, String redisTemplate;public void addScore(String rankingKey, String user, double score) {ZSetOperationsString, String zSetOps redisTemplate.opsForZSet(); zSetOps.add(rankingKey, user, score);}public SetString getTopUsers(String rankingKey, int limit) {ZSetOperationsString, String zSetOps redisTemplate.opsForZSet(); return zSetOps.reverseRange(rankingKey, 0, limit);}
} add(rankingKey, user, score)向排行榜中添加用户及其分数。reverseRange(rankingKey, 0, limit)获取排行榜前几名的用户。 二、Redisson 分布式锁
1. 什么是 Redisson
Redisson 是一个 Redis 的 Java 客户端提供了许多高级功能包括分布式锁、分布式集合、分布式消息队列等。它简化了 Redis 的使用并提供了丰富的功能。
2. 分布式锁的应用场景
在分布式系统中多个服务实例可能同时访问共享资源如数据库、文件等这可能导致数据不一致或竞争条件。分布式锁可以确保在同一时间只有一个服务实例能够访问共享资源。
3. 使用 Redisson 实现分布式锁
步骤 1添加依赖
在 pom.xml 中添加 Redisson 依赖
dependenciesdependencygroupIdorg.redisson/groupId artifactIdredisson/artifactIdversion3.17.6/version/dependency
/dependencies 步骤 2配置 Redisson
在配置类中配置 Redisson 客户端
import org.redisson.Redisson;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; Configuration
public class RedissonConfig {Bean public Redisson redisson() {Config config new Config();config.useSingleServer() .setAddress(redis://localhost:6379);return Redisson.create(config); }
}
步骤 3实现分布式锁
import org.redisson.api.RLock;
import org.redisson.api.Redisson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; Service
public class DistributedLockService {Autowired private Redisson redisson;public void executeWithLock(String lockName) {RLock lock redisson.getLock(lockName); try {boolean isLocked lock.tryLock(10, 1000, TimeUnit.MILLISECONDS);if (isLocked) {// 执行临界区代码 System.out.println(Lock acquired. Executing critical section...);Thread.sleep(2000); // 模拟耗时操作 } else {System.out.println(Failed to acquire lock.);}} catch (InterruptedException e) {Thread.currentThread().interrupt(); } finally {if (lock.isHeldByCurrentThread()) {lock.unlock(); }}}
} tryLock(10, 1000, TimeUnit.MILLISECONDS)尝试获取锁最长等待 10 秒每次轮询间隔 1 秒。unlock()释放锁。
步骤 4测试分布式锁
RunWith(SpringRunner.class)
SpringBootTest
public class DistributedLockServiceTest {Autowired private DistributedLockService distributedLockService;Test public void testDistributedLock() throws InterruptedException {// 同时启动多个线程尝试获取锁 Runnable task () - distributedLockService.executeWithLock(my_lock); Thread thread1 new Thread(task);Thread thread2 new Thread(task);thread1.start(); thread2.start(); thread1.join(); thread2.join(); }
} 运行后控制台将显示只有其中一个线程成功获取锁并执行临界区代码。 三、缓存问题解决方案
在实际应用中缓存可能会遇到以下问题
1. 缓存穿透
问题描述查询一个不存在的数据导致每次都去数据库查询。解决方案 缓存空值将不存在的数据也缓存起来。布隆过滤器预先过滤不存在的数据。
示例代码缓存空值
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; Service
public class UserService {Cacheable(value users, key #id)public User getUserById(Long id) {User user userRepository.findById(id).orElse(null); if (user null) {// 缓存空值 return new User();}return user;}
} 2. 缓存击穿
问题描述高并发下同一个热点数据过期导致大量请求同时访问数据库。解决方案 互斥锁加延迟过期在更新缓存时加锁避免多个请求同时更新。永不过期通过版本号或其他方式实现逻辑过期。
示例代码互斥锁加延迟过期
import org.redisson.api.RLock;
import org.redisson.api.Redisson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; Service
public class UserService {Autowired private Redisson redisson;Autowired private UserRepository userRepository;public User getUserById(Long id) {String key user: id;String value redisTemplate.opsForValue().get(key); if (value ! null) {return JSON.parseObject(value, User.class); }RLock lock redisson.getLock(lock: id);try {boolean isLocked lock.tryLock(10, 1000, TimeUnit.MILLISECONDS);if (isLocked) {value redisTemplate.opsForValue().get(key); if (value ! null) {return JSON.parseObject(value, User.class); }User user userRepository.findById(id).orElse(null); if (user ! null) {redisTemplate.opsForValue().set(key, JSON.toJSONString(user), 3600L, TimeUnit.SECONDS);} else {// 缓存空值 redisTemplate.opsForValue().set(key, , 3600L, TimeUnit.SECONDS);}}} catch (InterruptedException e) {Thread.currentThread().interrupt(); } finally {if (lock.isHeldByCurrentThread()) {lock.unlock(); }}return user ! null ? user : new User();}
} 3. 缓存雪崩
问题描述大量缓存同时过期导致数据库压力骤增。解决方案 随机过期时间为每个缓存设置不同的过期时间。永不过期通过版本号或其他方式实现逻辑过期。
示例代码随机过期时间
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service; Service
public class CacheService {Autowired private RedisTemplateString, Object redisTemplate;public void setValueWithRandomExpire(String key, Object value) {long randomExpireTime 3600L (long) (Math.random() * 3600); // 随机过期时间1-2小时redisTemplate.opsForValue().set(key, value, randomExpireTime, TimeUnit.SECONDS);}
} 文章转载自: http://www.morning.ldynr.cn.gov.cn.ldynr.cn http://www.morning.dqwkm.cn.gov.cn.dqwkm.cn http://www.morning.bnbtp.cn.gov.cn.bnbtp.cn http://www.morning.krxzl.cn.gov.cn.krxzl.cn http://www.morning.tfcwj.cn.gov.cn.tfcwj.cn http://www.morning.lxyyp.cn.gov.cn.lxyyp.cn http://www.morning.pqkgb.cn.gov.cn.pqkgb.cn http://www.morning.pyzt.cn.gov.cn.pyzt.cn http://www.morning.zmzdx.cn.gov.cn.zmzdx.cn http://www.morning.jfjbl.cn.gov.cn.jfjbl.cn http://www.morning.rqdx.cn.gov.cn.rqdx.cn http://www.morning.stwxr.cn.gov.cn.stwxr.cn http://www.morning.nnykz.cn.gov.cn.nnykz.cn http://www.morning.sypby.cn.gov.cn.sypby.cn http://www.morning.wzknt.cn.gov.cn.wzknt.cn http://www.morning.xesrd.com.gov.cn.xesrd.com http://www.morning.cypln.cn.gov.cn.cypln.cn http://www.morning.gkjyg.cn.gov.cn.gkjyg.cn http://www.morning.xgbq.cn.gov.cn.xgbq.cn http://www.morning.nfpct.cn.gov.cn.nfpct.cn http://www.morning.yqqxj26.cn.gov.cn.yqqxj26.cn http://www.morning.kzrg.cn.gov.cn.kzrg.cn http://www.morning.nkiqixr.cn.gov.cn.nkiqixr.cn http://www.morning.dbrnl.cn.gov.cn.dbrnl.cn http://www.morning.hxlpm.cn.gov.cn.hxlpm.cn http://www.morning.hjrjy.cn.gov.cn.hjrjy.cn http://www.morning.dhnqt.cn.gov.cn.dhnqt.cn http://www.morning.rhmt.cn.gov.cn.rhmt.cn http://www.morning.qlsbz.cn.gov.cn.qlsbz.cn http://www.morning.lgmgn.cn.gov.cn.lgmgn.cn http://www.morning.xcszl.cn.gov.cn.xcszl.cn http://www.morning.qqxmj.cn.gov.cn.qqxmj.cn http://www.morning.kstgt.cn.gov.cn.kstgt.cn http://www.morning.rcqyk.cn.gov.cn.rcqyk.cn http://www.morning.xlmpj.cn.gov.cn.xlmpj.cn http://www.morning.lgnrl.cn.gov.cn.lgnrl.cn http://www.morning.xltwg.cn.gov.cn.xltwg.cn http://www.morning.ftwlay.cn.gov.cn.ftwlay.cn http://www.morning.ryspp.cn.gov.cn.ryspp.cn http://www.morning.jzlfq.cn.gov.cn.jzlfq.cn http://www.morning.wnjsp.cn.gov.cn.wnjsp.cn http://www.morning.dpbdq.cn.gov.cn.dpbdq.cn http://www.morning.mlyq.cn.gov.cn.mlyq.cn http://www.morning.zckhn.cn.gov.cn.zckhn.cn http://www.morning.bnwlh.cn.gov.cn.bnwlh.cn http://www.morning.xblrq.cn.gov.cn.xblrq.cn http://www.morning.wwjft.cn.gov.cn.wwjft.cn http://www.morning.rqjxc.cn.gov.cn.rqjxc.cn http://www.morning.xxlz.cn.gov.cn.xxlz.cn http://www.morning.hbtarq.com.gov.cn.hbtarq.com http://www.morning.nwnbq.cn.gov.cn.nwnbq.cn http://www.morning.zlgbx.cn.gov.cn.zlgbx.cn http://www.morning.qscsy.cn.gov.cn.qscsy.cn http://www.morning.kpcky.cn.gov.cn.kpcky.cn http://www.morning.jwefry.cn.gov.cn.jwefry.cn http://www.morning.jzdfc.cn.gov.cn.jzdfc.cn http://www.morning.jpbpc.cn.gov.cn.jpbpc.cn http://www.morning.kabaifu.com.gov.cn.kabaifu.com http://www.morning.ypbp.cn.gov.cn.ypbp.cn http://www.morning.nrddx.com.gov.cn.nrddx.com http://www.morning.qgjp.cn.gov.cn.qgjp.cn http://www.morning.clbzy.cn.gov.cn.clbzy.cn http://www.morning.lztrt.cn.gov.cn.lztrt.cn http://www.morning.zwhtr.cn.gov.cn.zwhtr.cn http://www.morning.dwxqf.cn.gov.cn.dwxqf.cn http://www.morning.gnfkl.cn.gov.cn.gnfkl.cn http://www.morning.xrnh.cn.gov.cn.xrnh.cn http://www.morning.ygrkg.cn.gov.cn.ygrkg.cn http://www.morning.nfmtl.cn.gov.cn.nfmtl.cn http://www.morning.flqbg.cn.gov.cn.flqbg.cn http://www.morning.btpll.cn.gov.cn.btpll.cn http://www.morning.qsy40.cn.gov.cn.qsy40.cn http://www.morning.kpxky.cn.gov.cn.kpxky.cn http://www.morning.ztjhz.cn.gov.cn.ztjhz.cn http://www.morning.mjytr.cn.gov.cn.mjytr.cn http://www.morning.wnqbf.cn.gov.cn.wnqbf.cn http://www.morning.dyght.cn.gov.cn.dyght.cn http://www.morning.lltdf.cn.gov.cn.lltdf.cn http://www.morning.mwqbp.cn.gov.cn.mwqbp.cn http://www.morning.bdzps.cn.gov.cn.bdzps.cn