Rails 这边是 unique 的,数据库 migration 那边应该同时加上约束吧。擦皮鞋哪有只擦一只的道理,只擦一只鞋不应该过 Pull request。
有些高并发并且不要求 unique 的情况下,也可能造成数据混乱,比如要求只能一个 worker 处理一个对象的数据,但 workers 从一个任务池拿任务时,有可能多个 workers 先后拿到同一个对象不同的耗时任务,因为这个对象可能前前后后有很多任务,这时候用最简单的 advisory_lock 就可以避免了,可以用对象的 id 做 锁的 key。
https://dev.mysql.com/doc/refman/9.1/en/locking-functions.html
任务开始的时候用 IS_FREE_LOCK('#{id}')
查一下,如果 free 就 get_advisory_lock
, 最后 ensure
一下 release_advisory_lock
ActiveRecord::Base.connection.get_advisory_lock(id)
ActiveRecord::Base.connection.release_advisory_lock(id)
这样就保证了只有一个 worker 能处理这个耗时任务,其它的 works 拿到这个对象的任务时,要把这个任务放回任务池。
https://apidock.com/rails/ActiveRecord/ConnectionAdapters/AbstractAdapter/get_advisory_lock
Quote: “如果不是经常更新的内容,比如首页的 Banner 和广告这类首页接口,并发量最大,而且更新少”
常更新的也没有问题,设置好过期时间就行了,一小时更新一次,一天也就 24 次,虽然每个 puma 进程都管理自己的 cache,比如说有 8 个 puma 进程,同一个缓存就要重复保存 8 次,那一天也只更新 24*8 = 192 次,但现在内存这么便宜,数据库又放在 ssd 上,不用太在乎。
Rails 官方的文档不建议在生产环境中使用 MemoryStore 是因为多进程或多服务器之间不能共享缓存,另外就是上面说的会浪费内存。理解了原因就可以打破规则了。
我经手的一个生产环境的 k8s 里有十几台 64GB 的 rails 服务器,直接配置的 MemoryStore 作为 Cache, 再用另外的全局变量 redis_client 连接 Redis cluster 用来处理经常变动 (1 小时以下,一般是分钟以下,秒级别) 的缓存,目前运行得非常稳。
对于那种又大又不定期更新的缓存,还希望能在各进程和服务器间同步更新,并且不希望把这么大的缓存存在 redis,也有办法:
:categories_cache
中,永不过期,另外再把缓存生成的时间保存在 :categories_lazy_updated_at
中,永不过期。在更新 model 的同时,用 after_save
钩子在 Redis 中更新一个对应的键 categories_redis_updated_at
,值就是当下的 timestamp,在各个服务器每个进程中的 MemoryStore 缓存这个 Redis 的键值对,键名 :categories_eager_updated_at
,过期时间一分钟或你期望的间隔。
每次读取 :categories_cache
时都比较 :categories_lazy_updated_at
和 :categories_eager_updated_at
的值,这个过程都在本地,时间忽略不计,如果前者小于后者,说明 Category 已经更新了,那重新生成缓存 :category_cache
,再把 :categories_lazy_updated_at
的值更新为 categories_eager_updated_at
的值,其实也是categories_redis_updated_at
的值。
这样在 Redis 中只用了一个 timestamp 就在极小的间隔同步了各个进程和各个服务器之间的缓存更新。如果有多个这样的缓存,还可以优化,比如把多个缓存的 timestamps 组成一个 hash 放在 Redis 的一个键中。我最后还做了一个页面,所有的缓存都一目了然,包括值,占用空间大小,过期时间,当然页面中的本地缓存只是某一台服务器中某一个 puma 进程中的值
Rails 的 MemoryStore 效率奇高,因为以前内存贵 HDD 慢,一直在业界没好好利用,我看完源码后觉得现在不在生产环境用真是太浪费了,特别是那些大块头又常年不更新的缓存,现在它们极大概率可以在 garbage collection 中 survive。
沉下心来好好学习了一下这个 docker 示例以后,坚定成为 docker 党。
Rails dev prod 和 docker-compose 用同一个.env 配置文件。开发环境生产环境完全一致,操作系统 Win Mac Linux 完全无关,升级各种软件环境只要改文本配置。
一次学习,之后完全不在这方面耗任何时间,强烈推荐。
“做”和“做到极致”是两个不同的概念。如果你耐心看完所有内容,相信你会认同那么多 star. 不然你可以开个 repo, 我给你 star.
这哥们是 docker 船长,真把 docker 玩明白了,比 Rails 官方还玩得明白,我深度使用后觉得值得推荐。
https://github.com/nickjj/docker-rails-example
我的 pg 和 redis 没放 docker. 但我有一个 python 项目把 pg 和 redis 放在 docker 里,数据文件存母机,大小过 TB, 运行得也非常稳。
赞,很好的项目,如果在开发的时候,顺便做个笔记,那将会是一个很好的初学者教程。
如果我会搭,那我会自己搭一个,而不是用你的,因为总有一些需求/细节跟你不一样。
如果我不会搭,那就更不会用你的了,有耐心想学的话,可能要从头爬你的 commits.
cool
是 MIT 吗?没有 License 信息。
点赞👍
要不要把这个翻译成 ruby? https://github.com/ccxt/ccxt
也许把你实现的方法分享出来才对大家更有帮助吧?
很好的想法。想知道相对我自己注册公司,你们有什么优势。这也应该是你们宣传的重点吧。
这个好像不容易。
最简单的方式就是选 n, 然后 copy paste.
程序方面,可能可以加个 e 选项,打开默认编辑器编辑 commit 信息,我有空试一下。
谢谢 Rei 对中文 Rails 圈的贡献
另外挑个骨头:alias 重音在最前面。 http://dict.cn/alias
RubyMine 家的授权比较特殊,个人版可以在公司用,公司版又贵很多,公司又不能私下给我点钱买个人版。 最后公司给我买的公司版,贵是贵了点,但都合规。
用了 RubyMine 就不想换了,Debug 下断点太方便了,包括 RSpec 也能下断点,再也不用 binding.pry 了。
好像 VS Code 也能下断点,没空研究,但猜测应该不如 RubyMine,希望我错了。
跳转也很方便,当然遇到个 小明 小红 小帅 的方法名,那就要在一堆列表里找了。
请问是 #10 楼说的那样使用源码编译,加上 --enable-yjit 吗?
我也不会,但可以看别人的代码: https://github.com/howl-anderson/scel2txt
现在中国 ruby 程序员的工资大概在什么水平? 我在德国,一般的程序员,税前大概 6 万欧左右,德国税重保险贵,能扣一少半。其实我所在的公司也想招远程,但这工资水平,感觉国内的人看不上。
https://edgeapi.rubyonrails.org/classes/ActiveSupport/Cache/Store.html#method-i-fetch
Rails 6.0 以后有 skip_nil
选项了。
向你学习!英语的受众的确广很多!
感觉前 100 中,除了我都自由了,沙滩晒太阳太忙了,没时间上网
热心管理员上线了!
谢谢 ,忘记看 Test 了,最好还是写在 Readme.md 吧。
在 macOS 下试用了一下,发现不能通过键盘上下键移动选中行,只能通过 touchpad,估计鼠标也可以。
看到有人推 Ruby 还是很高兴的。
课程设置上,建议偏向 Rails,Ruby 工程师大概率还是去做 Rails 相关的工作。
有其它语言基础的话,Ruby 语法应该很快过一遍,然后在 Rails 工作中边用边加深就可以了。
好久没这么热闹了,开心,撒花!
一台工作笔记本,一台私人笔记本,接上三个显示器,桌子虽然很大,但可用面积其实很小,这时候什么键盘都不重要了,笔电默认的就可以接受。买的几把高档键盘已经在吃灰了。
如果程序和数据库是在同一主机,这个功能就没有意义了。
其实我更期待一个连运营者也无法知道内容的加密 Gem.