Redis的一些问题,解决并发的

项目通布隆过滤器:

布隆过滤器:
布隆过滤器是一种空间效率非常高的数据结构,用于快速判断一个元素是否可能存在于一个集合中。它由一个位数组(通常是长度为 m 的比特数组)和 k 个不同的哈希函数组成。当一个元素被加入集合时,通过 k 个哈希函数将该元素映射到位数组中的 k 个位置,并将这些位置的比特值设为 1。当需要查询一个元素是否在集合中时,同样通过 k 个哈希函数计算出位数组中的 k 个位置,并检查这些位置的比特值是否都为 1,如果有一个不为 1,则可以确定该元素肯定不在集合中,如果都为 1,则该元素可能存在于集合中。

布隆过滤器具有以下特点:

快速:查询一个元素的时间复杂度是 O(k),其中 k 是哈希函数的数量,通常很小。
空间效率高:相比于存储所有元素的集合,布隆过滤器需要的存储空间很小。
可能出现误判:当一个元素可能存在于集合中时,布隆过滤器会返回 "可能存在",但实际上可能并不存在;而当一个元素肯定不存在于集合中时,布隆过滤器会返回 "不存在",不存在误判。
布隆过滤器常用于缓存、数据库查询优化、网络爬虫的URL去重等场景,但需要注意的是,布隆过滤器一旦创建后,无法删除或修改其中的元素,因为删除或修改元素会影响其他元素的判断结果。

布隆过滤器和空值返回是两种常用的技术,用于缓解Redis的穿透问题。布隆过滤器可以用于快速检查某个键是否存在于Redis中,从而在缓存层面过滤掉一些不存在于Redis中的查询请求;而空值返回则是指在查询Redis中不存在的键时,直接返回一个空值,而不是去查询数据库,从而减少数据库压力。

基于布隆过滤器的缓解穿透问题:

在查询Redis之前,先使用布隆过滤器检查查询的键是否可能存在于Redis中。
如果布隆过滤器认为键不存在于Redis中,则直接返回一个预先设定的空值,而不进行实际的Redis查询。
如果布隆过滤器认为键可能存在于Redis中,则继续向Redis发起查询请求。
如果Redis返回的确实是空值,则在布隆过滤器中将该键标记为不存在,以便下一次查询时可以直接返回空值。
基于Redis构造分布式锁缓解优惠券秒杀问题:

使用Redis的SETNX命令来实现分布式锁,即尝试设置一个特定的键,如果该键不存在,则设置成功并获得锁,否则设置失败表示锁已被其他客户端获取。
在秒杀开始时,客户端请求获取优惠券时,先尝试获取分布式锁。
获取锁成功后,执行秒杀操作,即将优惠券数量减一,并将优惠券分发给用户。
执行完秒杀操作后,释放锁。
如果获取锁失败,则表示已经有其他客户端正在执行秒杀操作,当前客户端需要等待或放弃秒杀。
通过以上两种方法,可以在Redis中缓解穿透问题和秒杀问题,提高系统的稳定性和性能。

使用Redis+lua脚本构造分布式锁,缓解高并发缓解下的优惠卷超卖问题。

下面是一个使用Redis和Lua脚本构造分布式锁来缓解高并发下优惠券超卖问题的示例:

首先,在Redis中设置一个键来表示优惠券的库存数量。
当用户请求优惠券时,通过Lua脚本来进行原子性操作:
获取当前库存数量。
如果库存数量大于0,则将库存数量减1,并返回成功。
如果库存数量已经为0,则返回失败。
如果Lua脚本执行成功,则用户可以获得优惠券;否则,说明优惠券
已经售罄。
以下是一个Java代码示例:

java
import redis.clients.jedis.Jedis;

public class CouponService {
private static final String COUPON_KEY = “coupon_stock”;
private static final String LOCK_KEY = “coupon_lock”;
private static final String SCRIPT = "if redis.call(‘GET’, KEYS[1]) > ‘0’ then " +
"redis.call(‘DECR’, KEYS[1]) " +
"return 1 " +
"else " +
"return 0 " +
“end”;

public static void main(String[] args) {
    // 连接Redis数据库
    Jedis jedis = new Jedis("localhost");

    // 初始化优惠券库存
    jedis.set(COUPON_KEY, "100");

    // 模拟多个用户请求优惠券
    for (int i = 0; i < 150; i++) {
        new Thread(() -> {
            // 加锁
            String lock = jedis.set(LOCK_KEY, "LOCK", "NX", "EX", 5);
            if ("OK".equals(lock)) {
                // 执行Lua脚本
                Object result = jedis.eval(SCRIPT, 1, COUPON_KEY);
                if (result instanceof Long && (Long) result == 1) {
                    System.out.println("Success: User " + Thread.currentThread().getId() + " got the coupon.");
                } else {
                    System.out.println("Failed: Coupon sold out for user " + Thread.currentThread().getId());
                }
                // 释放锁
                jedis.del(LOCK_KEY);
            } else {
                System.out.println("Failed to acquire lock for user " + Thread.currentThread().getId());
            }
        }).start();
    }

    // 等待所有线程执行完毕
    try {
        Thread.sleep(6000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    // 打印最终库存数量
    System.out.println("Final coupon stock: " + jedis.get(COUPON_KEY));

    // 关闭Redis连接
    jedis.close();
}

}
在这个示例中,我们通过Redis的SET命令来尝试获取分布式锁,确保Lua脚本的原子性执行。如果获取锁成功,就执行Lua脚本,如果库存数量大于0,则将库存数量减1,并返回成功;否则返回失败。如果获取锁失败,则说明有其他线程正在执行优惠券领取操作,当前用户需要重试或放弃领取。

这样可以保证在高并发下,多个用户同时请求优惠券时,只有一个用户能够成功领取,避免了优惠券超卖问题。

相关推荐

  1. Redis一些问题解决并发

    2024-03-15 01:32:03       38 阅读
  2. 解决 ArrayList 并发问题

    2024-03-15 01:32:03       38 阅读
  3. 一些常见Redis问题和答案

    2024-03-15 01:32:03       45 阅读
  4. 并发系统中面临问题解决方案

    2024-03-15 01:32:03       30 阅读
  5. redis大key问题怎么解决

    2024-03-15 01:32:03       51 阅读
  6. Redis 常见问题解决方案

    2024-03-15 01:32:03       43 阅读
  7. redis原子命令和 lua 脚本解决并发问题

    2024-03-15 01:32:03       61 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-15 01:32:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-15 01:32:03       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-15 01:32:03       82 阅读
  4. Python语言-面向对象

    2024-03-15 01:32:03       91 阅读

热门阅读

  1. 牛客小白月赛61-E-排队

    2024-03-15 01:32:03       37 阅读
  2. 中国工控网获取详情 API

    2024-03-15 01:32:03       47 阅读
  3. @Import注解作用

    2024-03-15 01:32:03       45 阅读
  4. virsh管理虚拟机的命令行工具

    2024-03-15 01:32:03       43 阅读
  5. 新手如何学习Kubernetes【入门篇】

    2024-03-15 01:32:03       46 阅读
  6. 模块化(理解)

    2024-03-15 01:32:03       37 阅读
  7. 深入理解 MySQL 中的 CASE 语句:从基础到实战

    2024-03-15 01:32:03       39 阅读