• 0719~分布式锁


    概念:在分布式环境下,保证某个资源在同一时间访问时,只有一个线程能访问到资源;

    分布式锁的实现方式:

    1.基于数据库实现:

    innodb行锁;

    排他锁:一次只允许一个线程访问,只有等一个线程执行完后才会有下个线程进入;

    乐观锁:

    版本号控制;在数据库中加一个Version字段;

    基于数据库主键实现分布式锁;

    基于数据库索引实现分布式锁;

    乐观锁的缺点:常见的ABA问题;

    2.基于Redis实现:

    出现的问题:

    原子性问题:设置超时时间

    1. if(jedis.setnx(lock_stock,1) == 1){ //获取锁
    2. expire(lock_stock,5000//设置锁超时
    3. try {
    4. 业务代码需要10秒执行完毕
    5. } finally {
    6. jedis.del(lock_stock) //释放锁
    7. }
    8. }

    死锁问题:(没有释放锁/没有删除锁);删除锁判断一下是不是自己的锁;把value设置uuid

    1. //A-uuid:1 redis:123-1
    2. //B-uuid:2 redis:123-2
    3. String uuid = UUID.randomUUID().toString();
    4. if(jedis.set('123', uuid,"NX","EX",5) == 1){ //获取锁并设置超时
    5. try {
    6. //业务代码
    7. } finally {
    8. String lockValue = jedis.get("123"); //获取锁的值
    9. if(lockValue.equals(uuid)){ //判断是不是自己的锁
    10. jedis.del("123"//释放锁
    11. }
    12. }
    13. }

    释放锁的原子性问题:lua脚本保证原子性;

    1. String uuid = UUID.randomUUID().toString();
    2. if(jedis.set('123',uuid,"NX","EX",5) == 1){ //获取锁并设置超时
    3. try {
    4. 业务代码
    5. } finally {
    6. //lua脚本
    7. String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
    8. if
    9. redis.call('get', '123') == '1111111'
    10. then
    11. return redis.call('del', '123')
    12. else
    13. return 0 end
    14. //执行脚本
    15. jedis.eval(script, Collections.singletonList("123"),Collections.singletonList(uuid));
    16. }
    17. }

     redis提供的redis命令,setnx,比如三个线程同时进入一个业务,A线程进去了,只有A线程执行完释放锁后,其他两个线程才会执行;只有key不存在才会存value返回1,key不存在不会存value返回0;

    但是会有原子性的问题,如果代码没有执行完就出错了,那么数据的一致性如何保证呢?

    此时用Redisson来操作;

    Redission是什么?

    是Java用来操作redis的工具包,Redisson的宗旨是让用户redis的操作分离,为了是让用户更注重处理业务代码;

    Redission常见的锁:

    可重入锁;线程可重新进入的锁;

    联锁;在分布式场景下使用,必须等其他几个线程都上锁之后,主线程才能拿到锁;

    红锁;和联锁一样,唯一区别就是其他几个线程只需要大部分上锁就可以了;

    读写锁;只有写完之后,读的线程才能执行;

    闭锁(重点):如下图,CountdownLatch里面有一个初始值,就是线程的数量,线程每执行完一个就会减一,只有当CountdownLatch里面的值为零的时候,await方法才会放行,否则在await方法出等待;

     

    信号量:并发场景下,把数据库里的库存先拿到缓存里面预热,然后下单在缓存里进行库存扣减;

    公平锁:保持先进先出的原则,和队列一样;

    3.基于zookeeper实现(临时顺序节点+监听):

    zookeeper:解决分布式服务,保证数据一致性的协调解决方案;是层次型的目录树的数据结构;

    原理图:

     四种节点分类:

    1.持久化节点:

    2.持久化顺序节点:

    3.临时节点:

    4.临时顺序化节点(重点):

    使用原理图:

     主要实现原理:临时顺序节点+监听机制实现的;

  • 相关阅读:
    金仓数据库 KingbaseES 插件参考手册 L
    【打卡】【sysfs相关API详解】21天学习挑战赛—RK3399平台开发入门到精通-Day19
    SpringCloud Stream @EnableBinding注解过时
    PAT甲级 1020 Tree Traversals
    笨办法学python3
    工信部教考中心:什么是《研发效能(DevOps)工程师》认证,拿到证书之后有什么作用!(下篇)丨IDCF
    面向订单生产型电子制造企业,如何快速响应客户?
    【数据结构】:二叉树与堆排序的实现
    C++ 基础与深度分析 Chapter8 动态内存管理(动态内存基础、智能指针、相关问题)
    2. 慢查询、索引、执行计划详解
  • 原文地址:https://blog.csdn.net/m0_67574688/article/details/125879150