草庐IT

和 chatgpt 聊了一会儿分布式锁 redis/zookeeper distributed lock

老马啸西风 2023-08-10 原文

前言

最近的 chatGPT 很火爆,听说取代程序员指日可待。

于是和 TA 聊了一会儿分布式锁,我的感受是,超过大部分程序员的水平。

Q1: 谈一谈 java 通过 redis 实现分布式 锁

chatGPT:

Java通过Redis实现分布式锁,是在多个Java应用程序之间实现同步的一种方式。通过Redis的原子性和高性能,实现了分布式锁的可靠性和高效性。

具体实现步骤如下:

获取Redis连接:在Java应用程序中,使用Java Redis客户端连接到Redis数据库。

创建锁:Java应用程序向Redis数据库中写入一条记录,作为锁。

设置过期时间:为了避免死锁,需要为锁设置一个过期时间。

判断是否获取到锁:Java应用程序从Redis数据库中读取锁记录,判断当前是否已经有其他应用程序获取到了锁。如果没有,则当前应用程序获取到了锁,可以执行需要同步的操作。

释放锁:Java应用程序在同步操作完成后,从Redis数据库中删除锁记录,释放锁。

在实现分布式锁时,需要注意以下几点:

锁的名字应该是唯一的,并且易于识别和管理。

设置过期时间是为了避免锁一直被占用而无法释放。

应该采用原子性操作来实现锁,以避免出现多个线程同时访问锁而导致的并发问题。

需要考虑锁的持有时间,避免出现死锁的情况。

总之,通过Redis实现分布式锁可以很好地解决多个Java应用程序之间同步的问题。Java应用程序可以通过Redis实现高效、可靠的分布式锁,提高分布式应用程序的性能和可靠性。

我们针对过期时间附加两个小问题。

Q1.1 谈一谈 redis 分布式锁中,锁的过期时间应该设置多久才合理呢

chatGPT:

在 Redis 分布式锁中,锁的过期时间的设置需要考虑到两个方面的因素:锁的超时时间和业务处理时间。

如果锁的超时时间设置过短,那么在高并发的情况下,可能会出现多个进程同时获取到锁的情况,从而导致锁失效,出现并发问题。

因此,通常建议将锁的过期时间设置为稍微长一些,可以考虑设置为 30 秒到 1 分钟左右。

另外,还需要考虑业务处理时间。如果业务处理时间很长,而锁的过期时间很短,那么在业务处理期间锁失效,就会导致其他进程在锁被释放前获取到锁,从而导致并发问题。

因此,需要根据业务处理时间来合理地设置锁的过期时间,通常建议将锁的过期时间设置为业务处理时间的两倍以上。

需要注意的是,锁的过期时间设置过长也会带来风险,例如当获取锁的进程崩溃或被终止时,其他进程无法获取到锁,从而导致死锁问题。因此,在设置锁的过期时间时需要综合考虑以上因素,找到一个合理的平衡点。

Q1.2 如果系统正常业务 30秒处理完成,但是系统受到了攻击,导致处理时间变慢。这个时候,分布式锁的过期时间要怎么设置才合理呢?要求一定不能出错,涉及到金额

chatGPT:

如果系统受到攻击导致处理时间变慢,那么锁的过期时间要根据实际情况进行设置。通常建议将锁的过期时间设置为业务处理时间的两倍以上,但是如果系统受到攻击,处理时间远远超过了正常的业务处理时间,那么在这种情况下,就需要将锁的过期时间适当延长,以确保在极端情况下锁不会过早失效。

具体来说,可以考虑以下两种方案:

动态调整锁的过期时间:当系统受到攻击时,动态调整锁的过期时间。可以根据当前的业务处理时间来决定过期时间的长度,如果业务处理时间变长,就将过期时间适当延长。

采用异步处理的方式:将耗时较长的操作改为异步处理,从而避免阻塞主线程,减少对分布式锁的占用时间。在这种情况下,可以将锁的过期时间设置为正常的业务处理时间的两倍左右。

需要注意的是,在设置锁的过期时间时,一定要根据实际情况进行合理的设置。如果过期时间设置过短,会导致锁失效,出现并发问题;如果过期时间设置过长,会带来死锁的风险。因此,在设置锁的过期时间时,需要综合考虑业务处理时间和系统稳定性等因素,找到一个合理的平衡点。同时,在实际应用中,也可以结合监控系统和预警机制,及时发现和处理系统异常情况,保障系统的稳定性和安全性。

说的倒也算不错,让他给一下代码。

Q2: 给出具体的代码实现

下面是Java通过Redis实现分布式锁的代码示例:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;

public class RedisLock {
    private Jedis jedis;
    private String lockKey;
    private String lockValue;
    private int expireTime;

    public RedisLock(Jedis jedis, String lockKey, String lockValue, int expireTime) {
        this.jedis = jedis;
        this.lockKey = lockKey;
        this.lockValue = lockValue;
        this.expireTime = expireTime;
    }

    public boolean acquire() {
        SetParams setParams = new SetParams();
        setParams.nx();
        setParams.ex(expireTime);
        String result = jedis.set(lockKey, lockValue, setParams);
        if ("OK".equals(result)) {
            return true;
        }
        return false;
    }

    public boolean release() {
        String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Object result = jedis.eval(luaScript, 1, lockKey, lockValue);
        if ("1".equals(result.toString())) {
            return true;
        }
        return false;
    }
}

chatGPT 的解释:

在上面的代码中,我们定义了一个RedisLock类,用于封装获取和释放锁的操作。其中,acquire()方法用于获取锁,release()方法用于释放锁。

在获取锁时,我们使用Redis的set()方法设置一个键值对,并使用NX(不存在则创建)和EX(过期时间)两个参数来保证锁的原子性和可靠性。如果set()方法返回的结果为"OK",则表示获取到了锁,可以执行同步操作。

在释放锁时,我们使用Redis的eval()方法执行一个Lua脚本,判断当前锁的值是否为当前线程所持有的值。如果是,则调用Redis的del()方法删除该键值对,释放锁。

需要注意的是,在使用Redis实现分布式锁时,我们需要确保获取和释放锁的操作是原子性的。同时,我们也需要考虑锁的过期时间,避免出现死锁的情况。

诚然,这个代码写的作为入门是够用了。

1) 但是还是有一些改进空间,比如 expireTime/lockKey/lockValue 应该作为方法的参数。

其实 AI 无论怎么发展,我们还是需要知道底层的原理,不然都不知道如何改进

对于程序员如此,对于画师也是如此。

2)这个是单点的算法,我们问一下如何解决。

Q3:如果 redis 是多个节点,存在主节点重启,上面的方法存在什么问题?

chatGPT:

如果 Redis 是多个节点,存在主节点重启,上面的代码实现可能会出现如下问题:

主节点重启后,由于获取锁和释放锁的操作不在同一个节点上,可能会导致锁的失效或者其他线程获取到该锁,从而导致数据不一致的情况。

如果Redis的主从复制模式中,主节点重启后从节点升为主节点,那么原来的锁信息将无法被获取和释放。

为了解决这些问题,可以考虑使用Redis的RedLock算法。RedLock算法是由Redis的创始人Salvatore Sanfilippo提出的一种分布式锁方案,可以在多个节点之间协作实现可靠的分布式锁。

具体来说,RedLock算法使用多个Redis节点组成一个集群,获取锁和释放锁的操作在多个节点上执行,并且需要满足以下条件:

获取锁时,至少在大部分(如5个节点中的3个)节点上获取到锁才算成功获取到锁。

释放锁时,需要向所有节点发送释放锁的请求,只有大部分节点(如5个节点中的3个)成功释放锁才算成功释放锁。

通过这样的方式,可以在多个节点之间协作实现可靠的分布式锁,避免出现单点故障和数据不一致的情况。

以下是使用Java代码实现RedLock算法的示例:
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;

import java.util.ArrayList;
import java.util.List;

public class RedisRedLock {
    private List<Jedis> jedisList;
    private String lockKey;
    private String lockValue;
    private int expireTime;
    private int quorum;

    public RedisRedLock(List<Jedis> jedisList, String lockKey, String lockValue, int expireTime) {
        this.jedisList = jedisList;
        this.lockKey = lockKey;
        this.lockValue = lockValue;
        this.expireTime = expireTime;
        this.quorum = jedisList.size() / 2 + 1;
    }

    public boolean acquire() {
        int count = 0;
        long startMillis = System.currentTimeMillis();
        while ((System.currentTimeMillis() - startMillis) < expireTime) {
            for (Jedis jedis : jedisList) {
                SetParams setParams = new SetParams();
                setParams.nx();
                setParams.ex(expireTime);
                String result = jedis.set(lockKey, lockValue, setParams);
                if ("OK".equals(result)) {
                    count++;
                }
                if (count >= quorum) {
                    return true;
                }
            }
        }
        return false;
    }

    public boolean release() {
        boolean success = true;
        for (Jedis jedis : jedisList) {
            String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
            Object result = jedis.eval(luaScript, 1, lockKey, lockValue);
            if
    (!(result instanceof Long) || (Long) result != 1)) {
            success = false;
        }
    }
    return success;
}
在上述示例代码中,RedisRedLock类表示了一个RedLock分布式锁,包括多个Redis节点、锁的名称、锁的值、锁的过期时间等属性,以及获取锁和释放锁的方法。在获取锁时,需要循环遍历多个Redis节点,使用NX(不存在则创建)命令尝试在Redis中创建一个新的key-value对,并设置过期时间。只有当大部分节点(如5个节点中的3个)都成功获取到锁时,才算获取锁成功。在释放锁时,需要向所有节点发送释放锁的请求,使用Lua脚本来判断当前锁是否为当前线程持有,如果是则释放锁,否则返回0表示锁已被其他线程持有。

需要注意的是,使用RedLock算法可以提高分布式锁的可靠性和稳定性,但是并不能完全避免分布式锁的问题。

例如,当Redis节点之间的网络延迟较大时,可能会导致某些节点无法及时获取到锁信息,从而出现数据不一致的情况。因此,在使用RedLock算法时,需要仔细评估应用场景和业务需求,权衡分布式锁的可靠性和性能,以便选择最适合的方案。

当然,redlock 也并非是完美的,可以参考下面的文章:

redis 分布式锁设计 redis lock

Q4: RedLock 存在什么缺点?如何解决

chatGPT:

RedLock算法虽然可以提高分布式锁的可靠性和稳定性,但仍然存在一些缺点和局限性,如下所述:

可能存在网络分区问题:在Redis集群节点之间的网络延迟较大或出现网络分区时,可能会导致某些节点无法及时获取到锁信息,从而出现数据不一致的情况。

Redis节点故障问题:如果一个或多个Redis节点发生故障或宕机,可能会导致某些节点无法正常工作,从而影响分布式锁的可用性和性能。

同时获取锁的线程数量问题:RedLock算法中要求大部分节点都需要获取到锁才能认为获取成功,但是如果同时有大量线程请求获取锁,可能会导致节点的处理能力不足,从而导致获取锁的时间过长。

针对上述缺点和局限性,可以采取以下措施进行解决:

使用多个Redis集群:为了避免网络分区和节点故障等问题,可以使用多个Redis集群进行分布式锁的实现,从而提高可用性和稳定性。

采用自适应锁超时时间:针对同时获取锁的线程数量问题,可以根据实际情况采用自适应的锁超时时间,避免获取锁的时间过长。

使用其他分布式锁方案:RedLock算法虽然具有一定的优势,但并不是适用于所有场景。根据实际需求,可以选择其他分布式锁方案,如基于ZooKeeper实现的分布式锁等。

Q5: java 语言,使用 zookeeper 如何实现分布式锁

chatGPT:

在Java语言中,可以使用ZooKeeper实现分布式锁,具体步骤如下:

创建ZooKeeper客户端连接:使用ZooKeeper提供的Java API创建一个ZooKeeper客户端连接,用于访问ZooKeeper服务。

创建锁节点:在ZooKeeper中创建一个顺序临时节点,表示当前请求获取锁的节点。如果创建成功,则表示当前节点获取到了锁,否则需要等待。

监听前一个节点的删除事件:当前节点创建完成后,需要监听前一个节点的删除事件,一旦前一个节点被删除,说明前一个节点已经释放了锁,当前节点可以获取到锁。

释放锁:释放锁时需要删除当前节点。

以下是一段基于ZooKeeper实现分布式锁的Java代码示例:
public class DistributedLock {
    private ZooKeeper zooKeeper;
    private String lockPath;
    private String lockName;
    private String currentNodePath;
    private String previousNodePath;

    public DistributedLock(ZooKeeper zooKeeper, String lockPath, String lockName) {
        this.zooKeeper = zooKeeper;
        this.lockPath = lockPath;
        this.lockName = lockName;
    }

    public void lock() throws Exception {
        // 创建锁节点
        currentNodePath = zooKeeper.create(lockPath + "/" + lockName + "-", null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);

        // 获取锁节点的序号
        int currentNodeSeqNum = Integer.parseInt(currentNodePath.substring(currentNodePath.lastIndexOf('-') + 1));

        // 获取锁节点的父节点下的所有子节点
        List<String> children = zooKeeper.getChildren(lockPath, false);

        // 对子节点进行排序
        Collections.sort(children);

        // 获取当前节点在子节点列表中的位置
        int currentNodeIndex = children.indexOf(currentNodePath.substring(lockPath.length() + 1));

        // 如果当前节点是第一个节点,则获取锁成功
        if (currentNodeIndex == 0) {
            return;
        }

        // 获取前一个节点的路径
        previousNodePath = lockPath + "/" + children.get(currentNodeIndex - 1);

        // 监听前一个节点的删除事件
        Stat stat = zooKeeper.exists(previousNodePath, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                try {
                    lock();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        // 如果前一个节点已经不存在,则重新获取锁
        if (stat == null) {
            lock();
        } else {
            synchronized (this) {
                wait();
            }
        }
    }

    public void unlock() throws Exception {
        zooKeeper.delete(currentNodePath, -1);
    }
}
在这个示例代码中,我们首先创建了一个ZooKeeper客户端连接,然后定义了一个DistributedLock类来实现分布式锁,其中lockPath表示锁节点的路径,lockName表示锁节点的名称。

在lock()方法中,我们首先创建了一个顺序临时节点,然后获取锁节点的序号和当前节点在子节点列表中的位置,如果当前节点是第一个节点,则获取锁成功;

有一说一,对于基本不会使用 zookeeper 的开发者而言,上面的代码作为入门还是不错的。

但是最后我们还是需要理解原理,作为学习路上的良师益友,chatGPT 是当之无愧的。

Q6:zookeeper 是 AP 还是 CP?如果是 CP,那么出现服务不可用怎么办?

他推荐我们使用 zk,我们就问一下 cp 的问题。

chatGPT:

ZooKeeper是一个CP系统,即在网络分区的情况下,系统优先保证一致性,而可能牺牲可用性。

在ZooKeeper集群中,一旦发生网络分区,可能会导致部分节点无法连接到主节点,这时候这部分节点就会成为不可用状态。对于这种情况,可以采取以下措施:

保证集群的健康状态:在使用ZooKeeper的过程中,需要对集群进行定期的监控,确保每个节点的健康状态,及时发现故障。

使用重试机制:如果某个节点无法连接到主节点,可以采用重试机制,等待一段时间后再次尝试连接,如果仍然失败,可以通过切换到备用节点来保证服务的可用性。

合理设置超时时间:在使用ZooKeeper时,需要设置合理的超时时间,以便在出现网络分区等异常情况时,能够及时检测并作出相应的处理。

总之,在使用ZooKeeper实现分布式锁时,需要考虑到网络分区等异常情况,采取相应的措施来保证服务的可用性和一致性。

Q7: redis 和 zookeeper 实现分布式锁,你总结一下二者的利弊,对比一下。详细的表格

感觉聊的差不多了,我们让 chatGPT 出一个对比的表格。

chatGPT:

下面是Redis和ZooKeeper实现分布式锁的利弊对比表格:
特点RedisZooKeeper
数据结构Redis使用字符串数据类型存储锁信息ZooKeeper使用ZNode节点存储锁信息
实现方式Redis使用单节点或者Redis集群实现分布式锁ZooKeeper使用ZooKeeper集群实现分布式锁
性能Redis读写速度较快,适用于高并发场景ZooKeeper在写入数据时需要进行同步操作,写入速度相对较慢
可靠性Redis的主从复制和Sentinel保证了Redis集群的高可用性ZooKeeper采用了Paxos算法保证了集群的数据一致性和高可用性
稳定性Redis的稳定性较好,不易出现死锁和脑裂等问题ZooKeeper在网络分区时可能出现脑裂问题,需要进行特殊处理
开发难度Redis的API简单易用,易于开发和维护ZooKeeper的API较为复杂,需要一定的开发经验和技术储备
功能扩展Redis支持多种数据结构和数据操作,具有更强的功能扩展性ZooKeeper主要用于分布式协调和服务发现等场景,功能相对局限
总的来说,Redis适合处理高并发、读写频繁的场景,而ZooKeeper则更适合处理数据一致性和高可用性要求较高的场景。

在开发实践中,需要根据具体的业务需求和系统特点选择合适的分布式锁实现方式。

Q8: 你建议使用哪一种方式呢

chatGPT:

建议根据具体业务场景和系统架构选择合适的分布式锁实现方式。

如果业务场景中主要是处理高并发请求,读写操作较为频繁,且对数据一致性要求不是特别高,可以优先考虑Redis实现分布式锁。

如果系统对数据一致性和高可用性要求较高,可以考虑使用ZooKeeper实现分布式锁。

同时,如果系统中同时使用了Redis和ZooKeeper,可以考虑综合使用两者实现更为灵活和可靠的分布式锁方案。

他说到了结合二者,怎么个结合法?

Q9:综合使用两者实现是什么意思?展开说一说

chatGPT:

综合使用Redis和ZooKeeper实现分布式锁,主要是将两者的优势结合起来,达到更好的性能和可靠性。

一种常见的方式是,使用Redis实现分布式锁的快速获取和释放,同时使用ZooKeeper实现分布式锁的可靠性和数据一致性。具体实现方式是:

使用Redis的SETNX命令获取锁,如果获取成功,则表示获取到了分布式锁;否则,等待一段时间再次尝试获取锁。

获取到锁之后,设置锁的过期时间,并在Redis中记录当前线程持有锁的标识,用于后续释放锁时进行验证。

在业务逻辑执行完成后,使用Lua脚本或Redis的事务机制,保证释放锁的原子性。释放锁时,首先验证当前线程持有锁的标识,如果匹配,则使用Redis的DEL命令删除锁的标识,释放锁。

同时,将锁的释放同步到ZooKeeper中。在释放锁时,使用ZooKeeper的分布式锁机制,确保同一时刻只有一个线程可以修改锁的状态,避免多个线程同时释放锁的问题。

综合使用Redis和ZooKeeper实现分布式锁,既可以保证锁的获取和释放的高效性,又可以确保分布式锁的数据一致性和高可用性,是一种比较优秀的分布式锁实现方案。

Q10: 这样不会导致复杂性变高吗?如果二者不一致怎么办

chatGPT:

综合使用Redis和ZooKeeper实现分布式锁的确会增加一定的复杂性,需要更多的编码工作和配置调整,但是它能够更好地满足分布式锁的可靠性和高可用性要求,确保分布式锁的正确性和稳定性。

在使用Redis和ZooKeeper时,确实存在二者之间的数据一致性问题,例如锁在Redis中已经被释放,但在ZooKeeper中还未被删除,或者锁在ZooKeeper中已经被释放,但在Redis中还未被删除。如果发生这种情况,就会导致分布式锁的状态不一致,可能会造成一些问题。

为了避免这种情况,可以采用以下几种方式:

尽可能减少使用两种不同的分布式锁实现,如果可以,最好使用Redis或ZooKeeper其中一种实现分布式锁,而不是两者同时使用。

在代码实现时,加入检查分布式锁状态的逻辑,确保Redis和ZooKeeper中的分布式锁状态一致,例如在释放分布式锁时,先检查Redis中的锁是否已经被删除,再去ZooKeeper中删除锁的状态。

使用心跳机制定期同步两种分布式锁实现之间的状态,例如每隔一段时间,在Redis中设置一个带有过期时间的key,同时在ZooKeeper中创建一个持久化节点,表示分布式锁的状态,每次检查分布式锁状态时,都先在Redis中检查是否过期,如果过期则到ZooKeeper中检查分布式锁状态。

小结

chatGPT 其实比一般的博文质量要高不少,而且可以不停地提问拓展,对于知识的学习和拓展很有帮助。

但是需要我们有一定的辨别能力,因为他可能会胡说八道,而且死不悔改。

AI 不会取代人,只有会说用 AI 的人取代不会使用 AI 的人

我是老马,期待与你的下次重逢。

有关和 chatgpt 聊了一会儿分布式锁 redis/zookeeper distributed lock的更多相关文章

  1. ruby - 分布式事务和队列,ruby,erlang,scala - 2

    我有一个涉及多台机器、消息队列和事务的问题。因此,例如用户点击网页,点击将消息发送到另一台机器,该机器将付款添加到用户的帐户。每秒可能有数千次点击。事务的所有方面都应该是容错的。我以前从未遇到过这样的事情,但一些阅读表明这是一个众所周知的问题。所以我的问题。我假设安全的方法是使用两阶段提交,但协议(protocol)是阻塞的,所以我不会获得所需的性能,我是否正确?我通常写Ruby,但似乎Redis之类的数据库和Rescue、RabbitMQ等消息队列系统对我的帮助不大——即使我实现某种两阶段提交,如果Redis崩溃,数据也会丢失,因为它本质上只是内存。所有这些让我开始关注erlang和

  2. 亚特兰蒂斯的回声(中文版): chatGPT 的杰作 - 2

    英文版英文链接关注公众号在“亚特兰蒂斯的回声”中踏上一段难忘的冒险之旅,深入未知的海洋深处。足智多谋的考古学家AriaSeaborne偶然发现了一件古代神器,揭示了一张通往失落之城亚特兰蒂斯的隐藏地图。在她神秘的导师内森·兰登教授的指导和勇敢的冒险家亚历克斯·默瑟的帮助下,阿丽亚开始了一段危险的旅程,以揭开这座传说中城市的真相。他们的冒险之旅带领他们穿越险恶的大海、神秘的岛屿和充满陷阱和谜语的致命迷宫。随着Aria潜在的魔法能力的觉醒,她被睿智勇敢的QueenNeria的幻象所指引,她让她为即将到来的挑战做好准备。三人组揭开亚特兰蒂斯令人惊叹的隐藏文明,并了解到邪恶的巫师马拉卡勋爵试图利用其古

  3. ruby - 在 Ruby 中,如果我们定义了一个方法调用 "c=",为什么 c = 3 不能调用它? - 2

    例如,如果我们defc=(foo)p"hello"endc=3c=(3)并且不会打印“hello”。我知道它可以被self.c=3调用,但为什么呢?可以通过哪些其他方式调用它? 最佳答案 c=3(和c=(3),完全等同于它)总是被解释为局部变量赋值。你可能会说只有当方法c=没有在self上定义时,它才应该被解释为局部变量赋值,但是这有很多问题:至少MRI需要在解析时知道在给定范围内定义了哪些局部变量。但是,在解析时并不知道给定的方法是否已定义。所以ruby​​直到运行时才知道c=3是否定义了变量c或者调用了方法c=,这意味着它不会知

  4. 智能客服 | 浅谈人工智能聊天机器人ChatGPT - 2

    2022年底,OpenAI的预训练模型ChatGPT给人工智能领域的爱好者和研究人员留下了深刻的印象和启发,他展现的惊人能力将人工智能的研究和应用热度推向高潮,网上也充斥着和ChatGPT的各种聊天,他可以作诗、写小说、写代码、讨论疫情问题等。下面就是一些他的神回复:人命关天的坑: 写歌,留给词作者的机会不多了。。。 回答人类怎么样面对人工智能: 什么是ChatGPT?借用网上的一段介绍,ChatGPT是由人工智能研究实验室OpenAI在2022年11月30日发布的全新聊天机器人模型,一款人工智能技术驱动的自然语言处理工具。它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动

  5. 【ChatGPT】ChatGPT 的 N 种用法 - 2

    目录ChatGPT简介技术原理应用未来发展ChatGPT的10 种用法ChatGPT简介ChatGPT是一种基于深度学习的大型语言模型,由OpenAI公司开发。技术原理GPT是GenerativePre-trainedTransformer的缩写,意为生成式预训练变压器。它的技术原理是使用了一个基于注意力机制的变压器(Trans

  6. ruby - 停止分布式 Ruby 服务 - 2

    我有一个启动DRb服务的脚本,然后生成处理程序对象并通过DRb.thread.join等待。我希望脚本一直运行直到被明确杀死,所以我添加了trap"INT"doDRb.stop_serviceend在Ruby1.8下成功停止DRb服务并退出,但在1.9下似乎死锁(在OSX10.6.7上)。对该进程进行采样显示在semaphore_wait_signal_trap中有几个线程在旋转。我假设我在调用stop_service时做错了什么,但我不确定是什么。谁能给我任何关于如何正确处理它的指示? 最佳答案 好的,我想我已经找到了解决方案。如

  7. L2TP连接尝试失败,因为安全层在初始化与远程计算机的协商时遇到了一个处理错误 - 2

    废话不多先看bug解决方案在下面!!!!启动服务查看服务是否开启首先我的电脑-右键-管理-服务和应用程序-服务-找到IPsecPolicyAgent-右键属性-启动方式改为自动,并重启服务,如下图打开设置-更改适配器选项如下图点击连接失败的连接-右键-属性-安全-允许使用这些协议编辑注册表按Ctrl+R打开命令行窗口输入regedit打开注册表输入下面命令进入以下页面HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\RasMan\Parameters如下图在右侧编辑菜单上,鼠标右键新建,然后单击DWORD(32)位值。键入Prohibit

  8. 「想体验ChatGPT中文聊天?」那快进来,你用不上算我输 - 2

    ♥️作者:白日参商🤵‍♂️个人主页:白日参商主页♥️坚持分析平时学习到的项目以及学习到的软件开发知识,和大家一起努力呀!!!🎈🎈加油!加油!加油!加油🎈欢迎评论💬点赞👍🏻收藏📂加关注+!「想体验ChatGPT中文聊天?」那快进来,你用不上算我输项目场景:项目条件一、那就开始吧1、安装ChatGPT-Desktop2、OpenAPI设置二、使用实例恭喜你!!!配置成功了!!!API和URL都是博主免费提供给大家的!!!恭喜你!!!配置成功了!!!API和URL都是博主免费提供给大家的!!!🎈🎈加油!加油!加油!加油🎈欢迎评论💬点赞👍🏻收藏📂加关注+!项目场景:近几个月可以说ChatGPT是火得一

  9. 半个月狂飙1000亿,ChatGPT概念股凭什么? - 2

    ChatGPT掀起了AI股历史上最疯狂的一轮市值狂飙。自春节后至今,ChatGPT概念股开始了暴走模式,短短半月时间,海天瑞声、开普云等ChatGPT概念股市值累计增加了近1400亿。如此的爆炸效应,得益于ChatGPT所展现出商业化落地的巨大潜力。要知道,在此之前,无论是十年AI投入超千亿的百度,还是困在硬件化里的AI四小龙,都在重复着AI商业化难落地的故事。ChatGPT的出现,让AI从生产力的赋能者直接成为一种创造生产力的工具。随着订阅模式的推出,ChatGPT已经成为第一个以AI技术为核心直接变现的消费者应用。本文持有以下核心观点:1、ChatGPT是AI技术迭代的受益者。过去受限技术

  10. 未来的趋势————以ChatGPT为标杆的AI对生活的影响是巨大的 - 2

    文章目录前言1.AI的发展历程2.我是如何接触到人工智能的概念和产品的3.对于ChatGPT的一点看法4.AI对大学毕业生的职业发展的利与弊5.对于AI的思考和问题前言随着ChatGPT的爆火,生成式AI,大模型的人工智能被越来越多的人注意到,同时他也带来了许多问题。本文将对几方面进行探讨。1.AI的发展历程远古时期在公元前第一个千禧年,中国,印度和希腊哲学家都提出了一些推理的研究理论,比如亚里士多德(Aristotle)进行了演绎推理三段论的完整分析,欧几里得(Euclid)所著Elements是一种形式推理的模型,MuḥammadibnMūsāal-Khwārizmī,发明了代数学,即我们

随机推荐