多个条件进行操作的时候,难免遇到冲突
比如触发器,不同的触发器的触发条件如果有冲突,顺序不同,影响不同。如果A触发器先执行更改记录,会导致B触发器条件不满足而无法执行。如果让B先执行,则两者都可以顺利执行。
为Ubuntu升级JDK 到java 8
到官网下载 JDK-1.8 版本
mkdir -p /usr/lib/jvm 如果目录不存在。
将压缩包解压到 /usr/lib/jvm
sudo ln -s jdk1.8.0_131 java-8
修改.bashrc 如果用zsh, 则修改.zshrc
export JAVA_HOME=/usr/lib/jvm/java-8
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
source ~/.bashrc
配置默认JDK版本
sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/java-8/bin/java 300
sudo update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/java-8/bin/javac 300
sudo update-alternatives --config java
选择 路径 优先级 状态
------------------------------------------------------------
0 /usr/lib/jvm/java-6-openjdk/jre/bin/java 1061 自动模式
1 /usr/lib/jvm/java-6-openjdk/jre/bin/java 1061 手动模式
2 /usr/lib/jvm/java-8/bin/java 300 手动模式
要维持当前值 请按回车键,或者键入选择的编号:2
update-alternatives: 使用 /usr/lib/jvm/java-8/bin/java 来提供 /usr/bin/java (java),于 手动模式 中。
验证:
java -version
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
##### 关于全文搜索的优化和观点 如果客户能输入一个更有意义,更准确的词去进行全文搜索,这样才是最好的搜索优化。 因为,一个更合适的词,能够更好的从大数据中进行匹配筛选,得到的数据也是更接近于想要搜索得到的。 举个例子:想要得到天安门的地址。 如果你输入”的地”和输入”天安门”,显然”天安门”能够更准确和快速的搜索得到 想要的结果。
在项目中,使用了nGram这样的分词。这个分词的作用是: abc => [a,ab,abc, ac, b, bc,c]这样的分词。如果用这样的分词, 是能够通过”的地”把结构搜索出来。但是,这样的分词有性能问题,产生了大量实际中使用不到的token。而且,在产生大量分词的时候, 对CPU的使用率是非常消耗的。并且在搜索长的字符串的时候,也会产生性能问题,或者慢日志。虽然,这种分词能够涵盖的搜索情况最大,因为分的 token最多。但是,随着数据量的增加,如果到一定的数据量,ES会很快就到性能瓶颈。即使增加集群,也会随着数据量增加而很快到达瓶颈。而进入 性能黑洞。所以,使用IK或英文的分词,将有意义的词分成token,产生倒排索引。当用户能够输入有意义的词语进行搜索的时候,就能很好的搜索到结果。如果输入的是没有什么意义的词,就直接不匹配到结果,这是合理的情况。而兼顾没有意义的分词的情况,这不叫智能。这也失去了真正全文搜索的真实意义。我觉得全文搜索的真实意义是:得到更加精确的匹配结果,而不是得到更多匹配的结果。
ES同样有分页性能瓶颈
今天遇到一个ES的问题。ES在一段时间突然负载变大,涨了5倍。查找原因,分析日志后,结果是一个客户写了爬虫疯狂的爬我们的列表页面(他们把cookie的取出来用在爬虫中),而这个列表页面用的是ES。然后,爬虫开始分页,从第一页爬到5w多页。系统中用的是普通的ES分页方法。from 数量,size 数量。这种分页方案在数据量大且翻页到一定大的页数时,会产生严重的性能问题。而且,对方不是爬一次就结束了,而是一分钟疯狂的爬。所以,导致了ES的性能问题。
rails controller callback 顺序
首先,controller 中的 callback是一个队列,当有同名的callback的时候,调用顺序是按照先进先出,也就是从上到下的顺序。
把before_action 和 after_action 看成等价的。所以,他们是按照队列顺序调用。
after_action 无论是否放在上面,都是最后执行的。
如果有prepend_xxx 这是最先执行的
prepend_before_action prepend_after_action, prepend_around_action
after_action :log_a
before_action :log_b
def index
puts "run"
end
def log_a
puts "===around action 1"
yield
puts "===around action 2"
end
def log_b
puts "===before action"
end
# 这样的结果是
===around action 1
===before action
run
===around action 2
关于tags标签表的设计
有时候系统中需要使用标签功能, 并且不是一个地方或一个表需要标签。
新建一个tags表,tags的 name 名称就是唯一标识的。
新建一个中间表, taggings表。 表中有 tag_id 和 tagging_id tagging_type
tags 和 对应的某个表就是 多对多的关系
例如: user、product、post等地方需要tag,就可以共用tags一张表,对taggings来说他们都是多态
ES mapping field customer.level 和level 的搜索情况
索引 tickets 其中有这样的mapping
"customer": {
"properties": {
"level": {
"type": "string",
"index": "not_analyzed"
},
"nick_name": {
"type": "string",
"analyzer": "char_split"
}
}
}
进行下面搜索时
1.
GET tickets/ticket/_search
{
"query":{
"filtered":{
"filter":{
"bool":{
"must": [
{"term":{
"company_id": 1
}},
{"term":{
"customer.level":"vip"
}}
]
}
}
}
}
}
2.
GET tickets/ticket/_search
{
"query":{
"filtered":{
"filter":{
"bool":{
"must": [
{"term":{
"company_id": 1
}},
{"term":{
"level":"vip"
}}
]
}
}
}
}
}
这两种搜索都能得到结果。但个人会选择第一种方式,避免以后有可能造成的冲突
Rails send_data and send_file
send_data(data, options = {})
send_file(path, options = {})
Main difference here is that you pass DATA (binary code or whatever) with send_data or file PATH with send_file
So you can generate some data and send it as an inline text or as an attachment without generating file on your server via send_data. Or you can send ready file with send_file
data = "Hello World!"
send_data( data, :filename => "my_file.txt" )
OR
data = "Hello World!"
file = "my_file.txt"
File.open(file, "w"){ |f| f << data }
send_file( file )
使用oink分析内存问题
最近公司的服务器内存涨了4G,是在上回发版后开始上升。在访问请求并没有上涨的情况下,增加了这么多内存。公司原来就有装oink这个公司。
登入一台服务器,然后 输入 bundle exec oink –threshold=10 log/oink.log –threshold=10 表示10M内存
可以得到以下的信息(这是在测试服务器上测试的):
---- MEMORY THRESHOLD ----
THRESHOLD: 10 MB
-- SUMMARY --
Worst Requests:
1. Jun 16 15:03:08, 87944 KB, home#index
2.
3.
......
10.
Worst Actions:
23, home#index
Aggregated Totals:
Action Max Mean Min Total Number of requests
home#index 53260 17994 10964 197944 11
然后可以查看哪些action和请求url是消耗内存较多的,查看这些action的相关代码。查出一个昨天刚离职的同事之前写了一个优化count语句的代码修改,他把所有相关id找出来,然后存在数组中在size来优化原来的count。。。这样这个数据可以有几十万个元素,内存自然暴涨了
oink果然是个神器
rails 上传文件file 的 read 和 rewind
从params[:file] 上传得到一个文件流对象。rails会帮你封装好这个对象并且提供许多方法。
file = params[:file]
当file.read , 再执行 file.read的时候, 是读取到”“。 因为file已经被读过了,对应的文件指针应该是到了最尾部。此时的file的流内容是空的。如果,需要重新读这个file的内容,需要 file.rewind。 这样,之后再执行 file.read 就又可以读取到内容。
file 还有一个重要的属性,就是tempfile。file.tempfile.path,可以得到临时文件的位置。实际上,上传文件操作,服务器先生成了一个临时文件,在对这个临时文件进行读取或者是另存为一个新的文件,最后这个临时文件就没有用了,可以被删除。
constantize underscore
model = “Ticket”
table = model.constantize => class Ticket
model.underscore => “ticket”
table.table_name
table.index_name 在include es模块的情况下
record.slice
使用model.slice方法,简单的构造hash。
u = User.first
result = u.slice(:id, :nick_name)
result[:nick_name] #=> Tom
result["nick_name"] #=> Tom
default params in method
def my_method(name, city=[], age, color=[]) end
在ruby 2.1.1 下这样定义方法会报错 改为
def my_method(name, city, age, color=[]) end
presence
”“.presence => nil [].present => nil 当你想要把空类型的值都转为nil的时候,presence可以帮助你
例子:
name = params[:name].presence | default_name |
的前面需要为空,当参数为”“,或” “的时候,也可以通过presence转为nil,然后就可以用到default_name了 |
RestClient 的 post
RestClient.post “http://example.com/resource”, {‘x’ => 1}.to_json, {content_type: :json, accept: :json} 如果payload只是一个hash, 则RestClient默认会使用表单提交(x-www-form-urlencoded) 方式提交请求,
如果payload转为了json(to_json), RestClient会使用(application/json)的方式发起请求
在最后一个参数增加了 {accept: :json}, 表示接收 json 类型的response 如果不写这个参数, 如果response默认返回xml,则你的结果会是xml类型。
如果没有想要去升级某个库、包或gem,那么也许永远也不会更新了
如果没有想要去升级某个库、包或gem,那么也许永远也不会更新了。 因为当项目变得庞大了,想要做升级,代价无疑是巨大的
rails中的多对多出现慢查询
user_group 和 user 是多对多的关系,有中间表 users_user_group 执行这条语句user_group.users 实际执行的是:
User Load (6.7ms) SELECT `users`.* FROM `users` INNER JOIN `users_user_groups` ON `users`.`id` = `users_user_groups`.`user_id` WHERE `users_user_groups`.`user_group_id` = 1
很快,几毫秒就可以了。
而这条语句: user_group.users.agents
Role Load (1.2ms) SELECT `roles`.* FROM `roles` WHERE `roles`.`name` = 'agent' LIMIT 1
User Load (2266.9ms) SELECT `users`.* FROM `users` INNER JOIN `users_user_groups` ON `users`.`id` = `users_user_groups`.`user_id` WHERE `users_user_groups`.`user_group_id` = 1 AND `users`.`role_id` = 2
OMG,执行了两秒。 原因在于多了AND users
.role_id
= 2
优化方法:
json.array! user_group.users do |user|
if user.role_id = Role.agent.id
json.(agent, :id, :nick_name, :aliase)
end
end
当然,也可以考虑加合适的索引方式来进行优化
redis重启,之前的key已经使用默认的持久化方式,当重启后,redis会恢复这些key
只是当key的数量大量的时候,有可能会丢失一些。
所以,如果要清空sidekiq中的任务,就需要在redis中flushDB,清除相关的key