简体   繁体   English

在Rails应用程序上与所有用户共享大型阵列

[英]Sharing an large array with all users on a rails app

I have inherited an app that generates a large array for every user that visit the app. 我继承了一个应用程序,该应用程序会为访问该应用程序的每个用户生成一个大型数组。 I recently discovered that it is identical for nearly all the users!! 我最近发现几乎所有用户都一样!!

Now I want to somehow make one copy of it so it is not built over and over again. 现在,我想以某种方式对其进行复制,这样就不会一遍又一遍地构建它。 I have thought of a few options and wanted input to see which one is the best: 我考虑了一些选项,并希望输入以查看哪个选项最好:

1) Create a model and shove the data into the database 2) Create a YAML file and have the app load it when it initializes. 1)创建一个模型并将数据推送到数据库中。2)创建一个YAML文件,并在初始化时由应用加载。

I personally like the model idea but a few engineers at work feel as though it does not deserve to be a full model. 我个人喜欢模型的想法,但是一些工作的工程师认为它不应该成为完整的模型。 97% of the times users will see the same exact thing but 3% of the time users will get a slightly different array (a few elements will have changed). 97%的时间用户将看到相同的东西,但3%的时间用户将获得略有不同的数组(一些元素已更改)。
Any other approaches that I should consider.??..thanks in advance. 我应该考虑的任何其他方法。

Remember that if you store the data in the DB, each request which requires the data will have to execute a DB query to pull it out. 请记住,如果将数据存储在数据库中,则每个需要数据的请求都必须执行数据库查询才能将其提取。 If you are running multiple server threads, each thread could have its own copy in memory (if they are all handling requests which require the use of the array). 如果运行多个服务器线程,则每个线程可以在内存中拥有自己的副本(如果它们都处理需要使用数组的请求)。 In that case, you wouldn't be saving any memory (though you might save time from not having to regenerate the array). 在这种情况下,您将不会节省任何内存(尽管您可以节省不必重新生成阵列的时间)。

If you are running multiple server processes (not threads), and if the array contents change as the application is running, and the changes have to be visible to all the processes, caching in memory won't work. 如果您正在运行多个服务器进程(而不是线程),并且数组内容在应用程序运行时发生了变化,并且更改必须对所有进程可见,则无法在内存中进行缓存。 You will have to use the DB in that case. 在这种情况下,您将不得不使用数据库。

From the information in your comment, I suggest you try something like this: 根据您评论中的信息,建议您尝试如下操作:

Store the array in your DB, and make sure that the record(s) used have created/updated timestamps. 将数组存储在数据库中,并确保使用的记录已创建/更新了时间戳。 Cache the contents in memory using a constant/global variable/class variable. 使用常量/全局变量/类变量将内容缓存在内存中。 Also store the last time the cache was updated. 还存储上次更新缓存的时间。

Every time you need to use the array, retrieve the relevant "updated" timestamp from the DB. 每次需要使用数组时,请从数据库中获取相关的“更新”时间戳。 (You may need to use hand-coded SQL and ModelName.connection.execute to avoid pulling back all the data in the record, which ActiveRecord will probably do.) If the timestamp is later than the last time your cache was updated, pull the array from the DB and update your cache. (您可能需要使用手工编码的SQL和ModelName.connection.execute来避免拉回记录中的所有数据,ActiveRecord可能会这样做。)如果时间戳记晚于上次更新缓存的时间,请拉回数据库中的数组并更新您的缓存。

Use a Mutex ( 'require thread' ) when retrieving/updating the cached data, in case your server setup may use multiple threads. 检索/更新缓存的数据时,请使用Mutex( 'require thread' ),以防服务器设置可能使用多个线程。 (I don't think that Passenger does, but I have had problems similar to threading problems when using Passenger+RMagick, so I would still use a Mutex to be safe.) (我不认为Passenger会这样做,但是在使用Passenger + RMagick时,我遇到了类似于线程问题的问题,因此为了安全起见,我仍然会使用互斥体。)

Wrap all the code which deals with the cached array in a library class (or a class method on the model used to store the data), so the details of cache management don't spill over into the rest of the application. 将处理缓存数组的所有代码包装在库类(或用于存储数据的模型上的类方法)中,因此缓存管理的详细信息不会溢出到应用程序的其余部分。

Do a little bit of performance testing on the cache setup using Benchmark.measure {} . 使用Benchmark.measure {}对缓存设置进行一些性能测试。 If a bug in the setup actually made performance worse rather than better, that would be sad... 如果设置中的错误实际上使性能变差而不是变好,那将是可悲的...

I'd go with option 2. You can add two constants (for the 97% and 3%) that load from a YAML file when the app initializes. 我会选择选项2。可以在应用初始化时添加两个从YAML文件加载的常量(分别为97%和3%)。 That ought to shrink your memory footprint considerably. 那应该大大减少您的内存占用。

Having said that, yikes, this is just a band-aid on a hack, but you knew that already. 话虽如此,是的,这只是对黑客的创可贴,但您已经知道了。 I'd consider putting some time into a redesign, if you have that luxury. 如果您愿意的话,我会考虑花一些时间进行重新设计。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM