有一个出库的任务,有多个用户,只要一个用户的出库参数是true,这个任务就要一直执行
目前有两台后端服务器做负载均衡,为了保证任务唯一,用redis做状态控制,用一个key来表示任务的运行状态,任务在用户前端点击启动的时候通过判断对应key的状态来选择是否要新启一个线程执行任务。
现在有问题,有时候出错误了会直接将这个线程中断掉,这时候只能把所有用户的参数设置为关闭再打开,才可以重新执行,除了现在的redis怎么设计可以让用户知道这个线程现在是运行,还是停止的状态
一个脚本任务
两台服务器
用户前端点击按钮开启/关闭脚本任务——只要一个用户是开启的,脚本任务就不停止。全部关闭脚本任务关闭
redis做脚本任务状态控制
脚本任务目前是另起一个线程,然后死循环执行,当用户都关闭的时候跳出死循环
你们是怎么设计的,这样设计好像问题很多,项目启动的时候怎么自动启动脚本任务并且保证集群中只有一个,怎么让用户知道当前脚本任务确实在执行
可以使用redisson分布式锁来保证只有一个后端服务在运行该脚本任务,由于其创建的分布式锁是有过期时间(默认30秒)的且有锁续期机制(默认每隔10秒续期),所以尽管当执行脚本任务的服务崩溃,锁也会在一定时间之后过期,另一个服务则可以拿到锁执行任务。
用分布式锁的存在与否来判断当前脚本任务状态,锁存在表示脚本任务正在执行,反之则不在执行(当然如果服务崩溃后,锁没有被及时释放,这里会存在一定的延迟,可以通过调整锁的默认过期时间来缩短延迟时间
)。
大致流程:
要解决这个问题,可以考虑使用一个更健壮的状态管理方案,例如使用分布式锁或者使用消息队列。
分布式锁解决方案:
使用一个分布式锁,如基于Redis的Redlock,Zookeeper等,可以解决单点故障问题。当一个线程获取到锁时,就执行出库任务,并在Redis中保存执行状态。如果因为某种原因线程被中断,用户可以尝试再次获取锁来继续执行任务。
消息队列解决方案:
使用一个消息队列(如RabbitMQ,Kafka等)来处理任务也是一种常见的做法。用户将出库任务发送到消息队列,然后有一个或多个消费者线程从队列中获取任务并执行。消费者线程在执行任务前会检查任务状态,如果任务已停止,则不会尝试执行。
对于用户如何知道脚本线程运行状态的问题,你可以设计一个API接口,用户可以通过这个接口查询任务的执行状态。例如,当用户启动出库任务时,可以通过这个接口得到任务的状态。如果任务被中止,用户可以通过这个接口重新启动任务。
以下是一个简单的示例代码片段,用于说明如何使用Redis分布式锁来管理任务的执行状态:
import redisimport timedef start_task(user_id, is_active): # Connect to Redis server r = redis.StrictRedis(host='localhost', port=6379, db=0) lock_key = f'task_lock:{user_id}' # Try to acquire the lock while True: if r.set(lock_key, 1, nx=True, ex=3600): # Set lock for 1 hour break time.sleep(1) # Wait for 1 second and try again # Check if task is active task_status = r.get(f'task_status:{user_id}') if task_status and task_status == 'active': print(f'Task is already active for user {user_id}') r.delete(lock_key) # Release the lock return # Start the task print(f'Starting task for user {user_id}') # TODO: Start your task here... # Update task status r.set(f'task_status:{user_id}', 'active') r.expire(f'task_status:{user_id}', 3600) # Set expiration time for 1 hourdef stop_task(user_id): # Connect to Redis server r = redis.StrictRedis(host='localhost', port=6379, db=0) lock_key = f'task_lock:{user_id}' # Acquire the lock (this will fail if the lock is already set) if r.set(lock_key, 1, nx=True, ex=3600): # Set lock for 1 hour print(f'Acquired lock for user {user_id}') try: # Update task status r.set(f'task_status:{user_id}', 'stopped') # Update task status to stopped r.expire(f'task_status:{user_id}', 3600) # Set expiration time for 1 hour print(f'Stopped task for user {user_id}') finally: r.delete(lock_key) # Release the lock regardless of success or failure of the task stop operation
在下面的代码中,javascript运行在与主线程不同的单独线程中。该脚本是一个无限循环,因此需要以某种方式终止。怎样 使命感脚本开始运行后,cancel()不起作用。但如果我打电话。cancel()在线程初始化之后,它将终止它(注释掉的行)。
本文向大家介绍在 Java 程序中怎么保证多线程的运行安全?相关面试题,主要包含被问及在 Java 程序中怎么保证多线程的运行安全?时的应答技巧和注意事项,需要的朋友参考一下 方法一:使用安全类,比如 Java. util. concurrent 下的类。 方法二:使用自动锁 synchronized。 方法三:使用手动锁 Lock。 手动锁 Java 示例代码如下:
问题内容: 在下面的代码中,我使javascript在与主要线程不同的线程中运行。该脚本是一个无限循环,因此需要以某种方式终止。怎么样? 脚本开始运行后,调用.cancel()无效。但是,如果我在线程初始化之后立即调用.cancel(),它将终止它(注释行)。 问题答案: 与Java一样,JavaScript(在Nashorn下)也不会像Java那样在紧密循环中响应中断。该脚本需要轮询中断并自动终
Redisson的看门狗实现中,对于续期失败的异常处理就是释放锁: 见红框 也就是说主线程不会知道当前锁是否还有效,可能锁因为续期失败已经过期了,但主线程还在处理业务。 这种情况应该怎么处理呢?
问题内容: 我有这个线程可以从服务器下载一些图像。因此,一旦下载了图像,我就调用处理程序并进行UI更新。因此,由于不建议使用stop()线程,因此无法使用它。我在这里有两个问题。 最终该线程会发生什么?(意味着我调用处理程序方法后会发生什么)。 或者如何不使用stop()停止该线程? 这是我的代码。 问题答案: 线程将结束并自行死亡。您不必自己结束。如果不创建新对象,将无法重新启动它。垃圾收集器将
根据http://wiki.apache.org/jmeter/JMeterFAQ我应该能够在jmeter Gui中指定jmeter测试计划的用户/线程数,如下所示: 其中defaultvalue可以是1,2,3,无论什么。。。 当我尝试这样做时,我的测试甚至没有开始。 有什么提示吗? 谢谢