ar_cache 1.1.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '09eeda930c7263476f3b09e53747f9ec87ac070e65f18031856cdb05ad57a083'
4
- data.tar.gz: 425c321debdcc05d81d4c0815abecb0d9e19fa417bb251265ba6dab420dd03e1
3
+ metadata.gz: d4d25cbd1abb845a90dbd29d50d1dfb5b622e454e6c0bfe4a1ae65b4eddb818f
4
+ data.tar.gz: 821f3036d2df0db1f143a3212cffacf306ac30aa2335385defde6b41edf5f46d
5
5
  SHA512:
6
- metadata.gz: 827f0ecdf9e583870a454c16cfaa44c95b9d7b0ba4f3942097daf1c76fed218adfdafcd5733b68fa6476297c8b6d35c728e1a1b6f66db615d9fde834183ea4e8
7
- data.tar.gz: 273bef3daea68391d681045c384488bf9266a1f75cd5ea7057b6aaf70928ebe97934cb65daadf3f6a3442177d948923116867be503f479c6ac8ab06ac23bb286
6
+ metadata.gz: a0a9706501fa606ee7cf02931bdbfc5efd3e2668fb5b51c55b971d616233b43595363b30ccf279d500df64789268398c140870c8683b7e79e8b70717ebd2983a
7
+ data.tar.gz: 46e0a6c9a76401dec6d2f3c11f52e4e9a3e0d1b975c827df7eca05f0068612d78755238db00c5f170ab30523c5aee15eb6556b3956599490d0a812d4f8d917d5
data/CHANGELOG.md CHANGED
@@ -1,13 +1,3 @@
1
1
  # Change log
2
2
 
3
3
  ## main
4
-
5
- ## 1.0.0 (2021-03-02)
6
-
7
- - Initial version.
8
-
9
- ## 1.1.0 (2021-03-11)
10
-
11
- - Fully automatic delete cache when call delete_all/update_all method.
12
- - Optimize has_one(through:) cache implementation.
13
- - ActiveRecord::Relation#reload and ActiveRecord::Associations::Association#reload should skip read cache if associated target is already loaded.
data/Gemfile.common CHANGED
@@ -5,6 +5,8 @@ gemspec
5
5
 
6
6
  gem 'rake'
7
7
 
8
+ gem 'redis'
9
+ gem 'dalli'
8
10
  gem 'sqlite3'
9
11
  gem 'database_cleaner'
10
12
 
data/Gemfile.lock CHANGED
@@ -1,66 +1,67 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ar_cache (1.1.0)
4
+ ar_cache (2.0.0)
5
5
  activerecord (>= 6.1, < 7)
6
+ oj (>= 3, < 4)
6
7
 
7
8
  GEM
8
9
  remote: https://rubygems.org/
9
10
  specs:
10
- actioncable (6.1.1)
11
- actionpack (= 6.1.1)
12
- activesupport (= 6.1.1)
11
+ actioncable (6.1.3.2)
12
+ actionpack (= 6.1.3.2)
13
+ activesupport (= 6.1.3.2)
13
14
  nio4r (~> 2.0)
14
15
  websocket-driver (>= 0.6.1)
15
- actionmailbox (6.1.1)
16
- actionpack (= 6.1.1)
17
- activejob (= 6.1.1)
18
- activerecord (= 6.1.1)
19
- activestorage (= 6.1.1)
20
- activesupport (= 6.1.1)
16
+ actionmailbox (6.1.3.2)
17
+ actionpack (= 6.1.3.2)
18
+ activejob (= 6.1.3.2)
19
+ activerecord (= 6.1.3.2)
20
+ activestorage (= 6.1.3.2)
21
+ activesupport (= 6.1.3.2)
21
22
  mail (>= 2.7.1)
22
- actionmailer (6.1.1)
23
- actionpack (= 6.1.1)
24
- actionview (= 6.1.1)
25
- activejob (= 6.1.1)
26
- activesupport (= 6.1.1)
23
+ actionmailer (6.1.3.2)
24
+ actionpack (= 6.1.3.2)
25
+ actionview (= 6.1.3.2)
26
+ activejob (= 6.1.3.2)
27
+ activesupport (= 6.1.3.2)
27
28
  mail (~> 2.5, >= 2.5.4)
28
29
  rails-dom-testing (~> 2.0)
29
- actionpack (6.1.1)
30
- actionview (= 6.1.1)
31
- activesupport (= 6.1.1)
30
+ actionpack (6.1.3.2)
31
+ actionview (= 6.1.3.2)
32
+ activesupport (= 6.1.3.2)
32
33
  rack (~> 2.0, >= 2.0.9)
33
34
  rack-test (>= 0.6.3)
34
35
  rails-dom-testing (~> 2.0)
35
36
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
36
- actiontext (6.1.1)
37
- actionpack (= 6.1.1)
38
- activerecord (= 6.1.1)
39
- activestorage (= 6.1.1)
40
- activesupport (= 6.1.1)
37
+ actiontext (6.1.3.2)
38
+ actionpack (= 6.1.3.2)
39
+ activerecord (= 6.1.3.2)
40
+ activestorage (= 6.1.3.2)
41
+ activesupport (= 6.1.3.2)
41
42
  nokogiri (>= 1.8.5)
42
- actionview (6.1.1)
43
- activesupport (= 6.1.1)
43
+ actionview (6.1.3.2)
44
+ activesupport (= 6.1.3.2)
44
45
  builder (~> 3.1)
45
46
  erubi (~> 1.4)
46
47
  rails-dom-testing (~> 2.0)
47
48
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
48
- activejob (6.1.1)
49
- activesupport (= 6.1.1)
49
+ activejob (6.1.3.2)
50
+ activesupport (= 6.1.3.2)
50
51
  globalid (>= 0.3.6)
51
- activemodel (6.1.1)
52
- activesupport (= 6.1.1)
53
- activerecord (6.1.1)
54
- activemodel (= 6.1.1)
55
- activesupport (= 6.1.1)
56
- activestorage (6.1.1)
57
- actionpack (= 6.1.1)
58
- activejob (= 6.1.1)
59
- activerecord (= 6.1.1)
60
- activesupport (= 6.1.1)
61
- marcel (~> 0.3.1)
62
- mimemagic (~> 0.3.2)
63
- activesupport (6.1.1)
52
+ activemodel (6.1.3.2)
53
+ activesupport (= 6.1.3.2)
54
+ activerecord (6.1.3.2)
55
+ activemodel (= 6.1.3.2)
56
+ activesupport (= 6.1.3.2)
57
+ activestorage (6.1.3.2)
58
+ actionpack (= 6.1.3.2)
59
+ activejob (= 6.1.3.2)
60
+ activerecord (= 6.1.3.2)
61
+ activesupport (= 6.1.3.2)
62
+ marcel (~> 1.0.0)
63
+ mini_mime (~> 1.0.2)
64
+ activesupport (6.1.3.2)
64
65
  concurrent-ruby (~> 1.0, >= 1.0.2)
65
66
  i18n (>= 1.6, < 2)
66
67
  minitest (>= 5.1)
@@ -71,86 +72,92 @@ GEM
71
72
  coderay (1.1.3)
72
73
  concurrent-ruby (1.1.8)
73
74
  crass (1.0.6)
74
- database_cleaner (1.8.5)
75
+ dalli (2.7.11)
76
+ database_cleaner (2.0.1)
77
+ database_cleaner-active_record (~> 2.0.0)
78
+ database_cleaner-active_record (2.0.1)
79
+ activerecord (>= 5.a)
80
+ database_cleaner-core (~> 2.0.0)
81
+ database_cleaner-core (2.0.1)
75
82
  erubi (1.10.0)
76
83
  globalid (0.4.2)
77
84
  activesupport (>= 4.2.0)
78
- i18n (1.8.7)
85
+ i18n (1.8.10)
79
86
  concurrent-ruby (~> 1.0)
80
- loofah (2.9.0)
87
+ loofah (2.9.1)
81
88
  crass (~> 1.0.2)
82
89
  nokogiri (>= 1.5.9)
83
90
  mail (2.7.1)
84
91
  mini_mime (>= 0.1.1)
85
- marcel (0.3.3)
86
- mimemagic (~> 0.3.2)
92
+ marcel (1.0.1)
87
93
  method_source (1.0.0)
88
- mimemagic (0.3.5)
89
- mini_mime (1.0.2)
90
- minitest (5.14.3)
91
- nio4r (2.5.4)
92
- nokogiri (1.11.1-x86_64-linux)
94
+ mini_mime (1.0.3)
95
+ minitest (5.14.4)
96
+ nio4r (2.5.7)
97
+ nokogiri (1.11.6-x86_64-linux)
93
98
  racc (~> 1.4)
99
+ oj (3.11.5)
94
100
  parallel (1.20.1)
95
- parser (3.0.0.0)
101
+ parser (3.0.1.1)
96
102
  ast (~> 2.4.1)
97
- pry (0.13.1)
103
+ pry (0.14.1)
98
104
  coderay (~> 1.1)
99
105
  method_source (~> 1.0)
100
106
  racc (1.5.2)
101
107
  rack (2.2.3)
102
108
  rack-test (1.1.0)
103
109
  rack (>= 1.0, < 3)
104
- rails (6.1.1)
105
- actioncable (= 6.1.1)
106
- actionmailbox (= 6.1.1)
107
- actionmailer (= 6.1.1)
108
- actionpack (= 6.1.1)
109
- actiontext (= 6.1.1)
110
- actionview (= 6.1.1)
111
- activejob (= 6.1.1)
112
- activemodel (= 6.1.1)
113
- activerecord (= 6.1.1)
114
- activestorage (= 6.1.1)
115
- activesupport (= 6.1.1)
110
+ rails (6.1.3.2)
111
+ actioncable (= 6.1.3.2)
112
+ actionmailbox (= 6.1.3.2)
113
+ actionmailer (= 6.1.3.2)
114
+ actionpack (= 6.1.3.2)
115
+ actiontext (= 6.1.3.2)
116
+ actionview (= 6.1.3.2)
117
+ activejob (= 6.1.3.2)
118
+ activemodel (= 6.1.3.2)
119
+ activerecord (= 6.1.3.2)
120
+ activestorage (= 6.1.3.2)
121
+ activesupport (= 6.1.3.2)
116
122
  bundler (>= 1.15.0)
117
- railties (= 6.1.1)
123
+ railties (= 6.1.3.2)
118
124
  sprockets-rails (>= 2.0.0)
119
125
  rails-dom-testing (2.0.3)
120
126
  activesupport (>= 4.2.0)
121
127
  nokogiri (>= 1.6)
122
128
  rails-html-sanitizer (1.3.0)
123
129
  loofah (~> 2.3)
124
- railties (6.1.1)
125
- actionpack (= 6.1.1)
126
- activesupport (= 6.1.1)
130
+ railties (6.1.3.2)
131
+ actionpack (= 6.1.3.2)
132
+ activesupport (= 6.1.3.2)
127
133
  method_source
128
134
  rake (>= 0.8.7)
129
135
  thor (~> 1.0)
130
136
  rainbow (3.0.0)
131
137
  rake (13.0.3)
138
+ redis (4.2.5)
132
139
  regexp_parser (2.1.1)
133
- rexml (3.2.4)
134
- rubocop (1.11.0)
140
+ rexml (3.2.5)
141
+ rubocop (1.15.0)
135
142
  parallel (~> 1.10)
136
143
  parser (>= 3.0.0.0)
137
144
  rainbow (>= 2.2.2, < 4.0)
138
145
  regexp_parser (>= 1.8, < 3.0)
139
146
  rexml
140
- rubocop-ast (>= 1.2.0, < 2.0)
147
+ rubocop-ast (>= 1.5.0, < 2.0)
141
148
  ruby-progressbar (~> 1.7)
142
149
  unicode-display_width (>= 1.4.0, < 3.0)
143
- rubocop-ast (1.4.1)
144
- parser (>= 2.7.1.5)
145
- rubocop-minitest (0.10.3)
146
- rubocop (>= 0.87, < 2.0)
147
- rubocop-performance (1.9.2)
148
- rubocop (>= 0.90.0, < 2.0)
150
+ rubocop-ast (1.6.0)
151
+ parser (>= 3.0.1.1)
152
+ rubocop-minitest (0.12.1)
153
+ rubocop (>= 0.90, < 2.0)
154
+ rubocop-performance (1.11.3)
155
+ rubocop (>= 1.7.0, < 2.0)
149
156
  rubocop-ast (>= 0.4.0)
150
- rubocop-rails (2.9.1)
157
+ rubocop-rails (2.10.1)
151
158
  activesupport (>= 4.2.0)
152
159
  rack (>= 1.1)
153
- rubocop (>= 0.90.0, < 2.0)
160
+ rubocop (>= 1.7.0, < 2.0)
154
161
  rubocop-rake (0.5.1)
155
162
  rubocop
156
163
  ruby-progressbar (1.11.0)
@@ -166,7 +173,7 @@ GEM
166
173
  tzinfo (2.0.4)
167
174
  concurrent-ruby (~> 1.0)
168
175
  unicode-display_width (2.0.0)
169
- websocket-driver (0.7.3)
176
+ websocket-driver (0.7.4)
170
177
  websocket-extensions (>= 0.1.0)
171
178
  websocket-extensions (0.1.5)
172
179
  zeitwerk (2.4.2)
@@ -176,11 +183,13 @@ PLATFORMS
176
183
 
177
184
  DEPENDENCIES
178
185
  ar_cache!
186
+ dalli
179
187
  database_cleaner
180
188
  minitest
181
189
  pry
182
190
  rails
183
191
  rake
192
+ redis
184
193
  rubocop
185
194
  rubocop-minitest
186
195
  rubocop-performance
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # ArCache
1
+ # ArCache (This is outdated, please see [中文文档](README.zh-CN.md))
2
2
 
3
3
  ![Test Status](https://github.com/OuYangJinTing/ar_cache/workflows/CI/badge.svg)
4
4
  [![Gem Version](https://badge.fury.io/rb/ar_cache.svg)](https://badge.fury.io/rb/ar_cache)
@@ -16,7 +16,7 @@ then query the database and write the result to the cache.
16
16
  - `Read cache`: Automatically intercept ActiveRecord queries, then try to fetch data from cache.
17
17
  - `Write cache`: If the query is cacheable and the cached data is not exists, it will be automatically written to the cache after the query.
18
18
  - `Expire cache`: Automatically expire cache after updated/modified data.
19
- - `Iterative cache`: The cache version will be updated after table fields, `ArCache` switch or `ArCache` coder changed.
19
+ - `Iterative cache`: The cache version will be updated after table fields or `ArCache` switch changed.
20
20
  - `Shared cache`: The cache is not only used with ActiveRecord, you can easily use it in other places.([see examples](examples))
21
21
 
22
22
  ## Installation
@@ -55,17 +55,31 @@ rake db:migrate
55
55
 
56
56
  Skip cache:
57
57
 
58
+ - `ArCache#skip_cache`, eg:
59
+
60
+ ```ruby
61
+ # All queries in the block will not use the cache.
62
+ ArCache.skip_cache { User.find(1) }
63
+ ```
64
+
58
65
  - `ActiveRecord::Persistence#reload`, eg:
59
66
 
60
67
  ```ruby
61
68
  User.find(1).reload
62
69
  ```
63
70
 
64
- - `ActiveRecord::Relation#skip_ar_cache`, eg:
71
+ - `ActiveRecord::Relation#reload`, eg:
72
+
73
+ ```ruby
74
+ # When reload is called after the associated target has been loaded, the cache will be skipped.
75
+ User.where(id: 1).load.reload
76
+ ```
77
+
78
+ - `ActiveRecord::Associations::Association#reload`, eg:
65
79
 
66
80
  ```ruby
67
- User.skip_ar_cache.find(1)
68
- User.where(id: [1, 2]).skip_ar_cache.load
81
+ # When reload is called after the associated target has been loaded, the cache will be skipped.
82
+ user.association(:account).load_target.reload
69
83
  ```
70
84
 
71
85
  Delete cache:
@@ -91,7 +105,7 @@ If all the following conditions are met, ArCache will try to read the cache:
91
105
  - No call `#select` or select value is table column.
92
106
  - No call `#order` or order value is table column and only one.
93
107
  - No call `#limit` or value of the unique index isn't array.
94
- - No call `#joins`, `#left_joins`, `#skip_query_cache!`, `#skip_ar_cache`, `#explain`, `#from`, `#group`, `#offset`, `#lock`
108
+ - No call `#joins`, `#left_joins`, `#skip_query_cache!`, `#explain`, `#from`, `#group`, `#offset`, `#lock`
95
109
  - ...
96
110
 
97
111
  **Cacheable example:**
data/README.zh-CN.md ADDED
@@ -0,0 +1,165 @@
1
+ # ArCache
2
+
3
+ ![Test Status](https://github.com/OuYangJinTing/ar_cache/workflows/CI/badge.svg)
4
+ [![Gem Version](https://badge.fury.io/rb/ar_cache.svg)](https://badge.fury.io/rb/ar_cache)
5
+
6
+ `ArCache` 是一个现代的 `ActiveRecord` 查询缓存库,它受 [`cache-money`](https://github.com/ngmoco/cache-money) 和 [`second_level_cache`](https://github.com/hooopo/second_level_cache) 的启发而创作。
7
+ 当 `ActiveRecord` 实例化查询条件命中唯一索引时,`ArCache` 会拦截此次查询,尝试从缓存中获取结果;如果缓存缺失,
8
+ 将在 `ActiveRecord` 查询完成后自动填充缓存。
9
+ `ArCache` 会自动维护缓存的正确性。
10
+
11
+ ## 特点
12
+
13
+ - **低影响**:如果项目里数据库操作的相关代码符合 `ActiveRecord` 风格的话,那么你可以直接引入 `ArCache`,无需修改任何代码。([详细](#警告))
14
+ - **读缓存**:当实例化查询的条件命中唯一索引时,`ArCache` 会尝试从缓存中获取结果返回。
15
+ - **写缓存**:当读缓存操作没有获取到结果时,`ArCache` 会在 `ActiveRecord` 查询操作结束后,写入缓存。
16
+ - **删缓存**:在更新或删除数据后,`ArCache` 会自动移除对应的缓存。
17
+ - **迭代缓存**:当表结构发生改变后,`ArCache` 会更新这个表对应的缓存版本。
18
+ - **共享缓存**:`ArCache` 里面缓存是完整表字段与数据的哈希结果的 `json` 序列化字符串(仅当使用 `redis/memcached` 作为存储器时),因此缓存的使用是没有局限的。([实例](examples))
19
+
20
+ ## 安装
21
+
22
+ 向项目的 `Gemfile` 文件里增加一行内容:
23
+
24
+ ```ruby
25
+ gem 'ar_cache'
26
+ ```
27
+
28
+ 之后,执行:
29
+
30
+ ```shell
31
+ bundle install
32
+ ```
33
+
34
+ ## 初始化配置文件
35
+
36
+ 如果是 `rails` 项目,直接执行命令:
37
+
38
+ ```shell
39
+ rails generate ar_cache:install
40
+ ```
41
+
42
+ 不是,则将 [configuration.rb](lib/generators/ar_cache/templates/configuration.rb) 文件手动复制到项目对应的目录。
43
+
44
+ ## 配置项
45
+
46
+ 关于配置项的说明,请直接查看 [configuration.rb](lib/generators/ar_cache/templates/configuration.rb) 文件.
47
+
48
+ ## 用法
49
+
50
+ 只需要了解如何删除缓存和跳过缓存即可。
51
+
52
+ 删除缓存:
53
+
54
+ - `ArCache::Table#delete`, 例如:
55
+
56
+ ```ruby
57
+ User.ar_cache_table.delete(id...)
58
+ User.first.ar_cache_table.delete(id...)
59
+ ```
60
+
61
+ 跳过缓存:
62
+
63
+ - `ArCache#skip_cache`, 例如:
64
+
65
+ ```ruby
66
+ ArCache.skip_cache do
67
+ # 块里面的全部查询将跳过缓存
68
+ end
69
+ ```
70
+
71
+ - `ActiveRecord::Persistence#reload`, 例如:
72
+
73
+ ```ruby
74
+ User.find(1).reload
75
+ ```
76
+
77
+ - `ActiveRecord::Relation#reload`, 例如:
78
+
79
+ ```ruby
80
+ # 当 relation 已加载查询后,再调用 reload 方法时,将跳过缓存
81
+ User.where(id: 1).load.reload
82
+ ```
83
+
84
+ - `ActiveRecord::Associations::Association#reload`, 例如:
85
+
86
+ ```ruby
87
+ # 当关联对象已加载查询后,再调用 reload 方法时,将跳过缓存
88
+ user.association(:account).load_target.reload
89
+ ```
90
+
91
+ ## 可读缓存的查询
92
+
93
+ 必须满足下列全部条件:
94
+
95
+ - 使用哈希作为查询条件
96
+ - 查询条件包含唯一索引
97
+ - 没有事务存在,或者事务里面没有查询表的更新或删除操作(后续会尝试解除这个限制)
98
+ - 没有调用过 `select` 方法,或者 `select` 字段都是表字段
99
+ - 没有调用过 `order/order!` 方法,或者 `order` 字段只有一个,并且该字段是表字段
100
+ - 没有调用过 `limit/limit!` 方法,或者查询条件只能命中一个结果
101
+ - 没有调用过 `skip_query_cache!` 方法
102
+ - 没有调用过 `lock/lock!` 方法
103
+ - 没有调用过 `distinct/distinct!` 方法
104
+ - 没有调用过 `group/group!` 方法
105
+ - 没有调用过 `joins/joins!` 方法
106
+ - 没有调用过 `left_outer_joins/left_outer_joins!` 方法
107
+ - 没有调用过 `offset/offset!` 方法
108
+ - 没有调用过 `eager_load/eager_load!` 方法
109
+ - 没有调用过 `references/references!` 方法
110
+ - 没有调用过 `from/from!` 方法
111
+ - ...
112
+
113
+ ```ruby
114
+ User.find(1) # 主键查询是可读缓存的
115
+ User.where(email: 'foobar@gmail.com') # 唯一索引查询是可读缓存的
116
+ User.where(id: [1, 2]) # 唯一索引有多个值的情况,依然是可读缓存的
117
+ User.where(name: 'foobar', status: :active) # 联合字段的唯一索引查询是可读缓存的
118
+ User.includes(:account).where(id: [1, 2]) # ActiveRecord 的预加载是可读缓存的(仅当为 has_one 关联时)
119
+ User.first.account # ActiveRecord 的关联对象是可读缓存的(仅当为 has_one 关联时)
120
+ ```
121
+
122
+ 注意: `has_many` 的关联缓存,目前是不支持的,后续会尝试支持,但希望不大。
123
+
124
+ ## 缓存迭代
125
+
126
+ `ArCache` 的缓存是以表为层级的,当触发缓存迭代后,这个表的全部缓存都会失效,导致一种类似缓存雪崩的情况,请特别注意。
127
+ 下述的这些情况会导致缓存迭代:
128
+
129
+ - 表结构发生变化
130
+ - 激活/禁用 `ArCache`
131
+ - 使用 `ActiveRecord::Persistence::ClassMethods#upsert_all` 方法
132
+
133
+ ## 注意事项
134
+
135
+ - `ArCache` 的缓存清除操作,是在事务提交或 `sql` 操作结束后开始的,这意味是可能出现脏读的(后续会尝试解决)。
136
+ - `ArCache` 缓存数据是完整的表行数据,因此当 `sql` 包含 `select` 字段,并且缓存缺失时,`ArCache` 会将其改成 `select *`,但最终实例化的对象依旧符合预期。
137
+ - 当使用跳过 `ActiveReord` 的回调方法,更新/删除数据时,`ArCache` 可能会多执行一条 `select primary_key` 的 `sql`,因为清除缓存需要 `primary_key` 数据。
138
+
139
+ ## 警告
140
+
141
+ 下述的这些情况都是严禁发生的行为,这些行为会导致 `ArCache` 的缓存正确性。
142
+ PS:`ActiveRecord` 使用者,不应该写出这些代码。
143
+
144
+ - 直接使用 `execute` 方法 更新/删除 数据。
145
+ - 直接使用比 `execute` 更底层方式,更新/删除 数据。
146
+ - 跳过 `ActiveRecord` 直接 更新/删除 数据。(后续会提供数据库触发器来解除这个限制)
147
+
148
+ 如果这些行为无法避免的话,请按照上述[删除缓存](#用法)的方法,手动删除受影响的缓存数据,或者干脆直接禁止对应表的 `ArCache` 功能。
149
+
150
+ ## 其它类似的库
151
+
152
+ 这里还有一些其它的 `gem`,也提供了 `ActiveRecord` 的查询缓存功能。
153
+
154
+ - [identity_cache](https://github.com/Shopify/identity_cache)
155
+ - [second_level_cache](https://github.com/hooopo/second_level_cache)
156
+ - [cache-money](https://github.com/ngmoco/cache-money)
157
+
158
+ `ArCache` 跟他们存在一些下述的差异:
159
+
160
+ - `ArCache` 不依赖 `ActiveRecord` 的 `commit` 回调,所以你可以无所顾虑的直接使用跳过回调的方法。
161
+ - `ArCache` 的缓存是 `json` 序列化,不是 `Marshal` 序列化,所以缓存的使用是没有局限的。(仅当使用 `redis/memcached` 作为存储器时)
162
+ - `ArCache` 自动代理了标准的 `ActiveRecord` 实例化查询请求,所以不需要额外学习怎么使用缓存。
163
+ - `ArCache` 缓存是懒写入的,因此新创建的数据,不会直接写入缓存。
164
+ - `ArCache` 不会热更新缓存,因此数据被更新后,缓存就没有了。
165
+ - ...