分布式锁(数据库、Redis、ZK)拍了拍你

发表于 4年以前  | 总阅读数:668 次

前言

标题使用最近异常火热的微信拍一拍的方式命名,最近拍一拍的玩法被各位网友玩坏了,出现了各种版本的拍一拍。

比如:下面的这个版本是不是似曾相识的感觉,曾几何时你也曾有这种冲动的想法,但是奈于生活,你不得不把这股冲动埋在心底,毕竟冲动是魔鬼。

还有比较重口味的,有点哭笑不得,这网友的脑洞真大,要是能把这些心思放在学习和事业上,必是成大事之人,不得不佩服,假如你在吃饭,千万别打我。

不得不说拍一拍有点东西,好了,水话就说那么一两句,在开始真正的分布式锁讲解之前,先来个人的分析一下拍一拍的战略动机。

对于老板和一个公司来说,公司付出的每一个商品都是有商用价值的,老板不会把没有商用的价值功能和产品创造出来。

对于拍一拍这个功能,我想是一个引导性的战略思维,对于这个拍一拍新功能,很多网友都会跃跃欲试,不经意间就会尝试,双击别人的头像进行拍一拍。

那么这个双击的动作可能将来微信服务于某项功能而做的准备,待微信的用户习惯了双击操作,微信对于后面的这类操作的功能的推广会变得更加容易。

好了,不能再深究下去了,要是被小马哥看到,估计小马哥就要拍一拍我了,这个纯属个人观点,不代表官方的观点,下面开始我们的分布式锁的讲解。

分布式锁简介

分布式锁的实现方式有以下三种方式:「数据库分布式锁、Redis实现分布式锁、ZooKeeper实现分布式锁」

为什么需要分布式锁呢?在很久以前,用户全体不大的时候,单体应用就可以足够满足用户的所有请求,当用户增加的时候,出现了一定的并发度,可以使用简单的锁机制来协调并发的共享资源的获取。

但是,随着业务的增大,用户数量的增加,为了满足业务的高效性,集群的出现,简单的锁机制已经不能够满足协调多个应用之间的共享资源了,于是就出现了分布式锁。

分布式锁是协调集群中多应用之间的共享资源的获取的一种方式,可以说它是一种约束、规则。

那么对于一个分布式系统中分布式锁应该满足什么条件呢?也就是它应该具备怎样的约束、规则,下面是我总结的分布式锁至少拥有的几个规则。

1.「锁的互斥性」:在分布式集群应用中,共享资源的锁在同一时间只能被一个对象获取。2. 「可重入」:为了避免死锁,这把锁是可以重入的,并且可以设置超时。3. 「高效的加锁和解锁」:能够高效的加锁和解锁,获取锁和释放锁的性能也好。4. 「阻塞、公平」:可以根据业务的需要,考虑是使用阻塞、还是非阻塞,公平还是非公平的锁。

一个分布式锁能够具备上面的几种条件,应该来说是比较好的分布式锁了,但是现实中没有十全十美的锁,对于不同的分布式锁,没有最好,只能说那种场景更加适合。

下面我们详细的聊一聊上面说的三种分布式锁的实现原理,先来看看数据库的分布式锁。

数据库分布式锁

在数据库的分布式锁的实现中,分为「悲观锁和乐观锁」「悲观锁的实现依赖于数据库自身的锁机制实现」

若是要测试数据库的悲观的分布式锁,可以执行下面的sql:select … where … for update (排他锁),注意:where 后面的查询条件要走索引,若是没有走索引,会使用全表扫描,锁全表。

当一个数据库表被加上了排它锁,其它的客户端是不能够再对加锁的数据行加任何的锁,只能等待当前持有锁的释放锁。

全表扫描对于测试就没有太大意义了,where后面的条件是否走索引,要注意自己的索引的使用方式是否正确,并且还取决于「mysql优化器」

排它锁是基于InnoDB存储引擎的,在执行操作的时候,在sql中加入for update,可以给数据行加上排它锁。

在代码的代码的层面上使用connection.commit();,便可以释放锁,但是数据库复杂的加锁和解锁、事务等一系列消耗性能的操作,终归是无法抗高并发。

数据库乐观锁的方式实现分布式锁是基于「版本号控制」的方式实现,类似于「CAS的思想」,它认为操作的过程并不会存在并发的情况,只有在update version的时候才会去比较。

乐观锁的方式并没有锁的等待,不会因为所等待而消耗资源,下面来测试一下乐观锁的方式实现的分布式锁。

乐观锁的方式实现分布式锁要基于数据库表的方式进行实现,我们认为在数据库表中成功存储该某方法的线程获取到该方法的锁,才能操作该方法。

首先要创建一个表用于储存各个线程操作方法的对应该关系表LOCK

CREATE TABLE `LOCK` ( 
`ID` int PRIMARY KEY NOT NULL AUTO_INCREMENT,  
`METHODNAME` varchar(64) NOT NULL DEFAULT '',
`DESCRIPTION` varchar(1024) NOT NULL DEFAULT '',  
`TIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,  
UNIQUE KEY `UNIQUEMETHODNAME` (`METHODNAME`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

该表是存储某个方法的是否已经被锁定的信息,若是被锁定则无法获取到该方法的锁,这里注意的是使用UNIQUE KEY唯一约束,表示该方法布恩那个够被第二个线程同时持有。

当你要获取锁的时候,通过执行下面的sql来尝试获取锁:insert into LOCK(METHODNAME,DESCRIPTION) values (‘getLock’,‘获取锁’) ;来获取锁。

这条sql执行的结果有两种成功和失败,成功说明该方法还没有被某个线程所持有,失败则表明数据库中已经存在该条数据,该方法的锁已经被某个线程所持有。

当你需要释放锁的时候,可以通过执行这条sql:delete from LOCK where METHODNAME='getLock';来释放锁。

乐观锁实现方式还是存在很多问题的,一个是「并发性能问题」,再者「不可重入」以及「没有自动失效的功能」「非公平锁」,只要当前的库表中已经存在该信息,执行插入就会失败。

其实,对于上面的问题基于数据库也可以解决,比如:不可重复,你可以「增加字段保存当前线程的信息以及可重复的次数」,只要是再判断是当前线程,可重复的次数就会+1,每次执行释放锁就会-1,直到为0。

「没有失效的功能,可以增加一个字段存储最后的失效时间」,根据这个字段判断当前时间是否大于存储的失效时间,若是大于则表明,该方法的索索已经可以被释放。

「非公平锁可以增加一个中间表的形式,作为一个排队队列」,竞争的线程都会按照时间存储于这个中间表,当要某个线程尝试获取某个方法的锁的时候,检查中间表中是否已经存在等待的队列。

每次都只要获取中间表中最小的时间的锁,也实现公平的排队等候的效果,所有的问题总是有解决的思路。

上面就是两种基于数据库实现分布式锁的方式,但是,数据库实现分布式锁的方式只作为学习的例子,实际中不会使用它作为实现分布式锁,重要的是学习解决问题的思路和思想。

Redis实现的分布式锁

之前讲了一篇Redis事务的文章,很多读者Redis事务有啥用,主要是因为Redis的事务并没有Mysql的事务那么强大,所以一般的公司一般确实是用不到。[面试竟被问到Redis事务,触及知识盲区,脸都绿了]

这里就来说一说Redis事务的一个实际用途,它可以用来实现一个简单的秒杀系统的库存扣减,下面我们就来进行代码的实现。

(1)首先使用线程池初始化5000个客户端。

public static void intitClients() {
 ExecutorService threadPool= Executors.newCachedThreadPool();
 for (int i = 0; i < 5000; i++) {
  threadPool.execute(new Client(i));
 }
 threadPool.shutdown();

 while(true){ 
         if(threadPool.isTerminated()){  
             break;  
         }  
     }  
}

(2)接着初始化商品的库存数为1000。

public static void initPrductNum() {
  Jedis jedis = RedisUtil.getInstance().getJedis();
  jedisUtils.set("produce", "1000");// 初始化商品库存数
  RedisUtil.returnResource(jedis);// 返还数据库连接
 }
}

(3)最后是库存扣减的每条线程的处理逻辑。

/**
 * 顾客线程
 * 
 *
 */
class client implements Runnable {
 Jedis jedis = null;
 String key = "produce"; // 商品数量的主键
 String name;

 public ClientThread(int num) {
  name= "编号=" + num;
 }

 public void run() {

  while (true) {
   jedis = RedisUtil.getInstance().getJedis();
   try {
    jedis.watch(key);
    int num= Integer.parseInt(jedis.get(key));// 当前商品个数
    if (num> 0) {
     Transaction ts= jedis.multi(); // 开始事务
     ts.set(key, String.valueOf(num - 1)); // 库存扣减
     List<Object> result = ts.exec(); // 执行事务
     if (result == null || result.isEmpty()) {
      System.out.println("抱歉,您抢购失败,请再次重试");
     } else {
      System.out.println("恭喜您,抢购成功");
      break;
     }
    } else {
     System.out.println("抱歉,商品已经卖完");
     break;
    }
   } catch (Exception e) {
    e.printStackTrace();
   } finally {
    jedis.unwatch(); // 解除被监视的key
    RedisUtil.returnResource(jedis);
   }
  }
 }
}

在代码的实现中有一个重要的点就是「商品的数据量被watch了」,当前的客户端只要发现数量被改变就会抢购失败,然后不断的自旋进行抢购。

这个是基于Redis事务实现的简单的秒杀系统,Redis事务中的watch命令有点类似乐观锁的机制,只要发现商品数量被修改,就执行失败。

Redis实现分布式锁的第二种方式,可以使用setnx、getset、expire、del这四个命令来实现。

  1. setnx:命令表示如果key不存在,就会执行set命令,若是key已经存在,不会执行任何操作。
  2. getset:将key设置为给定的value值,并返回原来的旧value值,若是key不存在就会返回返回nil 。
  3. expire:设置key生存时间,当当前时间超出了给定的时间,就会自动删除key。
  4. del:删除key,它可以删除多个key,语法如下:DEL key [key …],若是key不存在直接忽略。

下面通过一个代码案例是实现以下这个命令的操作方式:

public void redis(Produce produce) {
        long timeout= 10000L; // 超时时间
        Long result= RedisUtil.setnx(produce.getId(), String.valueOf(System.currentTimeMillis() + timeout));
        if (result!= null && result.intValue() == 1) { // 返回1表示成功获取到锁
         RedisUtil.expire(produce.getId(), 10);//有效期为5秒,防止死锁
         //执行业务操作
         ......
         //执行完业务后,释放锁
         RedisUtil.del(produce.getId());
        } else {
           System.println.out("没有获取到锁")
        }
    }

在线程A通过setnx方法尝试去获取到produce对象的锁,若是获取成功就会返回1,获取不成功,说明当前对象的锁已经被其它线程锁持有。

获取锁成功后并设置key的生存时间,能够有效的防止出现死锁,最后就是通过del来实现删除key,这样其它的线程就也可以获取到这个对象的锁。

执行的逻辑很简单,但是简单的同时也会出现问题,比如你在执行完setnx成功后设置生存时间不生效,此时服务器宕机,那么key就会一直存在Redis中。

当然解决的办法,你可以在服务器destroy函数里面再次执行:

RedisUtil.del(produce.getId());

或者通过「定时任务检查是否有设置生存时间」,没有的话都会统一进行设置生存时间。

还有比较好的解决方案就是,在上面的执行逻辑里面,若是没有获取到锁再次进行key的生存时间:

public void redis(Produce produce) {
        long timeout= 10000L; // 超时时间
        Long result= RedisUtil.setnx(produce.getId(), String.valueOf(System.currentTimeMillis() + timeout));
        if (result!= null && result.intValue() == 1) { // 返回1表示成功获取到锁
         RedisUtil.expire(produce.getId(), 10);//有效期为10秒,防止死锁
         //执行业务操作
         ......
         //执行完业务后,释放锁
         RedisUtil.del(produce.getId());
        } else {
            String value= RedisUtil.get(produce.getId());
            // 存在该key,并且已经超时
            if (value!= null && System.currentTimeMillis() > Long.parseLong(value)) {
                String result = RedisUtil.getSet(produce.getId(), String.valueOf(System.currentTimeMillis() + timeout)); 
                if (result == null || (result != null && StringUtils.equals(value, result))) {
                     RedisUtil.expire(produce.getId(), 10);//有效期为10秒,防止死锁
           //执行业务操作
           ......
           //执行完业务后,释放锁
           RedisUtil.del(produce.getId());
                } else {
                    System.println("没有获取到锁")
                }
            } else {
                System.println("没有获取到锁")
            }
        }
    }

这里对上面的代码进行了改进,在获取setnx失败的时候,再次重新判断该key的锁时间是否失效或者不存在,并重新设置生存的时间,避免出现死锁的情况。

第三种Redis实现分布式锁,可以使用Redisson来实现,它的实现简单,已经帮我们封装好了,屏蔽了底层复杂的实现逻辑。

先来一个Redisson的原理图,后面会对这个原理图进行详细的介绍:

图片来源于网络

我们在实际的项目中要使用它,只需要引入它的依赖,然后执行下面的代码:

RLock lock = redisson.getLock("lockName");
lock.locl();
lock.unlock();

并且它还支持「Redis单实例、Redis哨兵、redis cluster、redis master-slave」等各种部署架构,都给你完美的实现,不用自己再次拧螺丝。

但是,crud的同时还是要学习一下它的底层的实现原理,下面我们来了解下一下,对于一个分布式的锁的框架主要的学习分为下面的5个点:

  1. 加锁机制
  2. 解锁机制
  3. 生存时间延长机制
  4. 可重入加锁机制
  5. 锁释放机制

只要掌握一个框架的这五个大点,基本这个框架的核心思想就已经掌握了,若是要你去实现一个锁机制框架,就会有大体的一个思路。

Redisson中的加锁机制是通过lua脚本进行实现,Redisson首先会通过「hash算法」,选择redis cluster集群中的一个节点,接着会把一个lua脚本发送到Redis中。

它底层实现的lua脚本如下:

returncommandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, command,
 "if (redis.call('exists', KEYS[1]) == 0) then " +
       "redis.call('hset', KEYS[1], ARGV[2], 1); " +
       "redis.call('pexpire', KEYS[1], ARGV[1]); " +
       "return nil; " +
   "end; " +
   "if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +
       "redis.call('hincrby', KEYS[1], ARGV[2], 1); " +
       "redis.call('pexpire', KEYS[1], ARGV[1]); " +
       "return nil; " +
   "end; " +
   "return redis.call('pttl', KEYS[1]);",
     Collections.<Object>singletonList(getName()), internalLockLeaseTime, getLockName(threadId));

「redis.call()的第一个参数表示要执行的命令,KEYS[1]表示要加锁的key值,ARGV[1]表示key的生存时间,默认时30秒,ARGV[2]表示加锁的客户端的ID。」

比如第一行中redis.call('exists', KEYS[1]) == 0) 表示执行exists命令判断Redis中是否含有KEYS[1],这个还是比较好理解的。

lua脚本中封装了要执行的业务逻辑代码,它能够保证执行业务代码的原子性,它通过hset lockName命令完成加锁。

若是第一个客户端已经通过hset命令成功加锁,当第二个客户端继续执行lua脚本时,会发现锁已经被占用,就会通过pttl myLock返回第一个客户端的持锁生存时间。

若是还有生存时间,表示第一个客户端会继续持有锁,那么第二个客户端就会不停的自旋尝试去获取锁。

假如第一个客户端持有锁的时间快到期了,想继续持有锁,可以给它启动一个watch dog看门狗,他是一个后台线程会每隔10秒检查一次,可以不断的延长持有锁的时间。

Redisson中可重入锁的实现是通过incrby lockName来实现,「重入一个计数就会+1,释放一次锁计数就会-1」

最后,使用完锁后执行del lockName就可以直接「释放锁」,这样其它的客户端就可以争抢到该锁了。

这就是分布式锁的开源Redisson框架底层锁机制的实现原理,我们可以在生产中实现该框架实现分布式锁的高效使用。

下面通过一个多窗口抢票的例子代码来实现:

public class SellTicket implements Runnable {
    private int ticketNum = 1000;
    RLock lock = getLock();
    // 获取锁 
    private RLock getLock() {
        Config config = new Config();
        config.useSingleServer().setAddress("redis://localhost:6379");
        Redisson redisson = (Redisson) Redisson.create(config);
        RLock lock = redisson.getLock("keyName");
        return lock;
    }

    @Override
    public void run() {
        while (ticketNum>0) {
            // 获取锁,并设置超时时间
            lock.lock(1, TimeUnit.MINUTES);
            try {
                if (ticketNum> 0) {
                    System.out.println(Thread.currentThread().getName() + "出售第 " + ticketNum-- + " 张票");
                }
            } finally {
                lock.unlock(); // 释放锁
            }
        }
    }
}

测试的代码如下:

public class Test {
    public static void main(String[] args) {
        SellTicket sellTick= new SellTicket();
        // 开启5五条线程,模拟5个窗口
        for (int i=1; i<=5; i++) {
            new Thread(sellTick, "窗口" + i).start();
        }
    }
}

是不是感觉很简单,因为多线程竞争共享资源的复杂的过程它在底层都帮你实现了,屏蔽了这些复杂的过程,而你也就成为了优秀的API调用者。

上面就是Redis三种方式实现分布式锁的方式,基于Redis的实现方式基本都会选择Redisson的方式进行实现,因为简单命令,不用自己拧螺丝,开箱即用。

ZK实现的分布式锁

ZK实现的分布式锁的原理是基于一个「临时顺序节点」实现的,开始的时候,首先会在ZK中创建一个ParentLock持久化节点。

当有client1请求锁的时候,,就会在ParentLock下创建一个临时顺序节点,如下图所示:

并且,该节点是有序的,在ZK的内部会自动维护一个节点的序号,比如:第一个进来的创建的临时顺序节点叫做xxx-000001,那么第二个就叫做xxx-000002,这里的序号是一次递增的。

当client1创建完临时顺序节点后,就会检查ParentLock下面的所有的子节点,会判断自己前面是否还有节点,此时明显是没有的,所以获取锁成功。

当第二个客户端client2进来获取锁的时候,也会执行相同的逻辑,会先在创建一个临时的顺序节点,并且序号是排在第一个节点的后面:

并且第二部也会判断ParnetLock下面的所有的子节点,看自己是否是第一个,明显不是,此时就会加锁失败。

那么此时client2会创建一个对client1的lock1的监听(Watcher),用于监听lock1是否存在,同时client2会进入等待状态:

当client1执行完自己的业务逻辑之后,就会删除锁,删除锁很简单,就是把这个lock1给删除掉:

此时就会通知client2:监听的lock1已经被删除,锁被释放,此时client2创建的lock2也就变成了第一个节点,尝试获取所得时候就会获取锁成功。

这就是ZK分布式锁的底层实现原理,内容还是挺多的,毕竟分布式锁要求有一定并发度才会用到,对于一般的用户群体不大的根本就不会涉及到,所以第一次接触的肯定也是需要时间吸收的。

总结

三种方案的比较,从不同的角度看这三种实现方式,比较的结果也不一样:

  1. 性能:缓存 > Zookeeper >= 数据库。
  2. 可靠性:Zookeeper > 缓存 > 数据库

本文由哈喽比特于4年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/TuueFtwEMvc0yE5FNHuk1w

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 目录