pg 外链pg

通过外部表的方式连接其他postgresql服务器

install

安装相关插件 针对centos

yum install postgresql96-contrib -y

配置

查看外部表插件是否有安装

select * from pg_available_extensions;

为你所需要的数据库创建extension

create extension postgres_fdw;

查看是否有了插件

select * from pg_extension;

创建服务

create server server_remote_70 foreign data wrapper postgres_fdw options(host ‘192.168.10.8’,port ‘5432’,dbname ‘postgres’);

创建用户可以访问的外链服务

create user mapping for postgres server server_remote_70 options(user ‘postgres’,password ‘postgres’);

查看

select * from pg_user_mappings;

创建外部表

CREATE FOREIGN TABLE tbl_fdw(a int) server server_remote_70 options (schema_name ‘public’,table_name ‘tb1’);

注意这里创建外部表,需要跟对应的数据表结构保持一致

当你通过super user创建完外部表之后,需要将数据表进行赋权给其他用户

ALTER FOREIGN TABLE tbl_fdw OWNER TO new_owner

postgres=# drop foreign table tbl_kenyon;
DROP FOREIGN TABLE
postgres=# drop user mapping for postgres server server_remote_71 ;
DROP USER MAPPING
postgres=# drop server server_remote_71 ;
DROP SERVER
postgres=# drop extension postgres_fdw ;
DROP EXTENSION

jupyterhub 安装和配置

Install juptyhub

首先安装

1
2
3
python3 -m pip install notebook
npm install -g configurable-http-proxy
python3 -m pip install jupyterhub

生成器配置文件

jupyterhub_config.py
jupyterhub_cookie_secret
jupyterhub.sqlite

[Unit]
Description=Jupyterhub

[Service]
User=root
ExecStart=/usr/local/bin/jupyterhub –JupyterHub.spawner_class=sudospawner.SudoSpawner

[Install]
WantedBy=multi-user.target

gradle项目创建

需要学习的语言:

  • java
  • kotlin

为什么要选择Kotlin而不是groovy? 我主要考量是Kotlin是DSL, 具体的一些分析可以见此链接

关于Kotlin

初始化项目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$ gradle init

Select type of project to generate:
1: basic
2: cpp-application
3: cpp-library
4: groovy-application
5: groovy-library
6: java-application
7: java-library
8: kotlin-application
9: kotlin-library
10: scala-library
Enter selection (default: basic) [1..10] 6

Select build script DSL:
1: groovy
2: kotlin
Enter selection (default: groovy) [1..2]

Select test framework:
1: junit
2: testng
3: spock
Enter selection (default: junit) [1..3]

Project name (default: demo):

Source package (default: demo):


BUILD SUCCESSFUL in 1s
2 actionable tasks: 2 executed

init主要任务是生成wrapper文件、项目配置依赖(build.gradle.kts,settings.gradle.kts)和创建默认的项目目录.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
├── build.gradle.kts
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle.kts
└── src
├── main
│ └── java
│ └── demo
│ └── App.java
└── test
└── java
└── demo
└── AppTest.java

settings.gradle.kts
1
rootProject.name = "demo"
build.gradle.kts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
plugins {
java
application
}

repositories {
jcenter()
}

dependencies {
implementation("com.google.guava:guava:26.0-jre")

testImplementation("junit:junit:4.12")
}

application {
mainClassName = "demo.App"
}

dependencies : 依赖

  • implementation : 如果我们使用了implementation方式来依赖项目的话,那么这个库就在编译时期,只对当前的module可见,对其他的module不可见,但是在运行使其是可见的,这种方式的好处是可以显著减少 build项目的时间,因为假如该依赖库有接口或者代码变动,那么Gradle只会去重新编译和它有直接依赖关系的module,也就是该库不存在传递性
  • api: 使用api方式来依赖项目或者库的话,那么这个库,在编译时期和运行时期都可以对其他module可见
  • compileOnly: 假如在项目中,对某些库你只是想要在编译时期使用,而在运行时期并不需要这个库,你可以使用这种方式!
  • runtimeOnly: Gradle 在运行时会将该库添加到 build 的 output 中去

关于编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
> Task :tasks

------------------------------------------------------------
Tasks runnable from root project
------------------------------------------------------------

Application tasks
-----------------
run - Runs this project as a JVM application

Build tasks
-----------
assemble - Assembles the outputs of this project.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
classes - Assembles main classes.
clean - Deletes the build directory.
jar - Assembles a jar archive containing the main classes.
testClasses - Assembles test classes.

Build Setup tasks
-----------------
init - Initializes a new Gradle build.
wrapper - Generates Gradle wrapper files.

Distribution tasks
------------------
assembleDist - Assembles the main distributions
distTar - Bundles the project as a distribution.
distZip - Bundles the project as a distribution.
installDist - Installs the project as a distribution as-is.

Documentation tasks
-------------------
javadoc - Generates Javadoc API documentation for the main source code.

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'demo3'.
components - Displays the components produced by root project 'demo3'. [incubating]
dependencies - Displays all dependencies declared in root project 'demo3'.
dependencyInsight - Displays the insight into a specific dependency in root project 'demo3'.
dependentComponents - Displays the dependent components of components in root project 'demo3'. [incubating]
help - Displays a help message.
kotlinDslAccessorsReport - Prints the Kotlin code for accessing the currently available project extensions and conventions.
model - Displays the configuration model of root project 'demo3'. [incubating]
projects - Displays the sub-projects of root project 'demo3'.
properties - Displays the properties of root project 'demo3'.
tasks - Displays the tasks runnable from root project 'demo3'.

redis at rails

认识Redis

Redis是一个高性能的kv数据库.它特点就是在NOSQL和并发快速.之所以快速是因为它将所有的数据都放入内存,因此如何使用变得非常关键.

redis安装和简单配置

install redis

其实没有没有什么讲的,几乎所有任何的发行版本都已经加入.如果官方下载包也容易,只要make一下就编译完成. 至于时候要make install 自己看着办吧.

Config redis

redis的配置文件就ubuntu而言,是在/etc/redis/下,有两个文件,一个是redis.conf 一个是sentinel.conf.

redis.conf 配置redis服务用的.

redis.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
# Redis 配置文件

# 当配置中需要配置内存大小时,可以使用 1k, 5GB, 4M 等类似的格式,其转换方式如下(不区分大小写)
#
# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes
#
# 内存配置大小写是一样的.比如 1gb 1Gb 1GB 1gB

# daemonize no 默认情况下,redis不是在后台运行的,如果需要在后台运行,把该项的值更改为yes
daemonize yes

# 当redis在后台运行的时候,Redis默认会把pid文件放在/var/run/redis.pid,你可以配置到其他地址。
# 当运行多个redis服务时,需要指定不同的pid文件和端口
pidfile /var/run/redis.pid

# 指定redis运行的端口,默认是6379
port 6379

# 指定redis只接收来自于该IP地址的请求,如果不进行设置,那么将处理所有请求,
# 在生产环境中最好设置该项
# bind 127.0.0.1

# Specify the path for the unix socket that will be used to listen for
# incoming connections. There is no default, so Redis will not listen
# on a unix socket when not specified.
#
# unixsocket /tmp/redis.sock
# unixsocketperm 755

# 设置客户端连接时的超时时间,单位为秒。当客户端在这段时间内没有发出任何指令,那么关闭该连接
# 0是关闭此设置
timeout 0

# 指定日志记录级别
# Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose
# debug 记录很多信息,用于开发和测试
# varbose 有用的信息,不像debug会记录那么多
# notice 普通的verbose,常用于生产环境
# warning 只有非常重要或者严重的信息会记录到日志
loglevel debug

# 配置log文件地址
# 默认值为stdout,标准输出,若后台模式会输出到/dev/null
#logfile stdout
logfile /var/log/redis/redis.log

# To enable logging to the system logger, just set 'syslog-enabled' to yes,
# and optionally update the other syslog parameters to suit your needs.
# syslog-enabled no

# Specify the syslog identity.
# syslog-ident redis

# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7.
# syslog-facility local0

# 可用数据库数
# 默认值为16,默认数据库为0,数据库范围在0-(database-1)之间
databases 16

################################ 快照 #################################
#
# 保存数据到磁盘,格式如下:
#
# save <seconds> <changes>
#
# 指出在多长时间内,有多少次更新操作,就将数据同步到数据文件rdb。
# 相当于条件触发抓取快照,这个可以多个条件配合
#
# 比如默认配置文件中的设置,就设置了三个条件
#
# save 900 1 900秒内至少有1个key被改变
# save 300 10 300秒内至少有300个key被改变
# save 60 10000 60秒内至少有10000个key被改变

save 900 1
save 300 10
save 60 10000

# 存储至本地数据库时(持久化到rdb文件)是否压缩数据,默认为yes
rdbcompression yes

# 本地持久化数据库文件名,默认值为dump.rdb
dbfilename dump.rdb

# 工作目录
#
# 数据库镜像备份的文件放置的路径。
# 这里的路径跟文件名要分开配置是因为redis在进行备份时,先会将当前数据库的状态写入到一个临时文件中,等备份完成时,
# 再把该该临时文件替换为上面所指定的文件,而这里的临时文件和上面所配置的备份文件都会放在这个指定的路径当中。
#
# AOF文件也会存放在这个目录下面
#
# 注意这里必须制定一个目录而不是文件
dir ./

################################# 复制 #################################

# 主从复制. 设置该数据库为其他数据库的从数据库.
# 设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步
#
# slaveof <masterip> <masterport>

# 当master服务设置了密码保护时(用requirepass制定的密码)
# slav服务连接master的密码
#
# masterauth <master-password>


# 当从库同主机失去连接或者复制正在进行,从机库有两种运行方式:
#
# 1) 如果slave-serve-stale-data设置为yes(默认设置),从库会继续相应客户端的请求
#
# 2) 如果slave-serve-stale-data是指为no,出去INFO和SLAVOF命令之外的任何请求都会返回一个
# 错误"SYNC with master in progress"
#
slave-serve-stale-data yes

# 从库会按照一个时间间隔向主库发送PINGs.可以通过repl-ping-slave-period设置这个时间间隔,默认是10秒
#
# repl-ping-slave-period 10

# repl-timeout 设置主库批量数据传输时间或者ping回复时间间隔,默认值是60秒
# 一定要确保repl-timeout大于repl-ping-slave-period
# repl-timeout 60

################################## 安全 ###################################

# 设置客户端连接后进行任何其他指定前需要使用的密码。
# 警告:因为redis速度相当快,所以在一台比较好的服务器下,一个外部的用户可以在一秒钟进行150K次的密码尝试,这意味着你需要指定非常非常强大的密码来防止暴力破解
#
# requirepass foobared

# 命令重命名.
#
# 在一个共享环境下可以重命名相对危险的命令。比如把CONFIG重名为一个不容易猜测的字符。
#
# 举例:
#
# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
#
# 如果想删除一个命令,直接把它重命名为一个空字符""即可,如下:
#
# rename-command CONFIG ""

################################### 约束 ####################################

# 设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,
# 如果设置 maxclients 0,表示不作限制。
# 当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息
#
# maxclients 128

# 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key
# Redis同时也会移除空的list对象
#
# 当此方法处理后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作
#
# 注意:Redis新的vm机制,会把Key存放内存,Value会存放在swap区
#
# maxmemory的设置比较适合于把redis当作于类似memcached的缓存来使用,而不适合当做一个真实的DB。
# 当把Redis当做一个真实的数据库使用的时候,内存使用将是一个很大的开销
# maxmemory <bytes>

# 当内存达到最大值的时候Redis会选择删除哪些数据?有五种方式可供选择
#
# volatile-lru -> 利用LRU算法移除设置过过期时间的key (LRU:最近使用 Least Recently Used )
# allkeys-lru -> 利用LRU算法移除任何key
# volatile-random -> 移除设置过过期时间的随机key
# allkeys->random -> remove a random key, any key
# volatile-ttl -> 移除即将过期的key(minor TTL)
# noeviction -> 不移除任何可以,只是返回一个写错误
#
# 注意:对于上面的策略,如果没有合适的key可以移除,当写的时候Redis会返回一个错误
#
# 写命令包括: set setnx setex append
# incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
# sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
# zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
# getset mset msetnx exec sort
#
# 默认是:
#
# maxmemory-policy volatile-lru

# LRU 和 minimal TTL 算法都不是精准的算法,但是相对精确的算法(为了节省内存),随意你可以选择样本大小进行检测。
# Redis默认的灰选择3个样本进行检测,你可以通过maxmemory-samples进行设置
#
# maxmemory-samples 3

############################## AOF ###############################


# 默认情况下,redis会在后台异步的把数据库镜像备份到磁盘,但是该备份是非常耗时的,而且备份也不能很频繁,如果发生诸如拉闸限电、拔插头等状况,那么将造成比较大范围的数据丢失。
# 所以redis提供了另外一种更加高效的数据库备份及灾难恢复方式。
# 开启append only模式之后,redis会把所接收到的每一次写操作请求都追加到appendonly.aof文件中,当redis重新启动时,会从该文件恢复出之前的状态。
# 但是这样会造成appendonly.aof文件过大,所以redis还支持了BGREWRITEAOF指令,对appendonly.aof 进行重新整理。
# 你可以同时开启asynchronous dumps 和 AOF

appendonly no

# AOF文件名称 (默认: "appendonly.aof")
# appendfilename appendonly.aof

# Redis支持三种同步AOF文件的策略:
#
# no: 不进行同步,系统去操作 . Faster.
# always: always表示每次有写操作都进行同步. Slow, Safest.
# everysec: 表示对写操作进行累积,每秒同步一次. Compromise.
#
# 默认是"everysec",按照速度和安全折中这是最好的。
# 如果想让Redis能更高效的运行,你也可以设置为"no",让操作系统决定什么时候去执行
# 或者相反想让数据更安全你也可以设置为"always"
#
# 如果不确定就用 "everysec".

# appendfsync always
appendfsync everysec
# appendfsync no

# AOF策略设置为always或者everysec时,后台处理进程(后台保存或者AOF日志重写)会执行大量的I/O操作
# 在某些Linux配置中会阻止过长的fsync()请求。注意现在没有任何修复,即使fsync在另外一个线程进行处理
#
# 为了减缓这个问题,可以设置下面这个参数no-appendfsync-on-rewrite
#
# This means that while another child is saving the durability of Redis is
# the same as "appendfsync none", that in pratical terms means that it is
# possible to lost up to 30 seconds of log in the worst scenario (with the
# default Linux settings).
#
# If you have latency problems turn this to "yes". Otherwise leave it as
# "no" that is the safest pick from the point of view of durability.
no-appendfsync-on-rewrite no

# Automatic rewrite of the append only file.
# AOF 自动重写
# 当AOF文件增长到一定大小的时候Redis能够调用 BGREWRITEAOF 对日志文件进行重写
#
# 它是这样工作的:Redis会记住上次进行些日志后文件的大小(如果从开机以来还没进行过重写,那日子大小在开机的时候确定)
#
# 基础大小会同现在的大小进行比较。如果现在的大小比基础大小大制定的百分比,重写功能将启动
# 同时需要指定一个最小大小用于AOF重写,这个用于阻止即使文件很小但是增长幅度很大也去重写AOF文件的情况
# 设置 percentage 为0就关闭这个特性

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

################################## SLOW LOG ###################################

# Redis Slow Log 记录超过特定执行时间的命令。执行时间不包括I/O计算比如连接客户端,返回结果等,只是命令执行时间
#
# 可以通过两个参数设置slow log:一个是告诉Redis执行超过多少时间被记录的参数slowlog-log-slower-than(微妙),
# 另一个是slow log 的长度。当一个新命令被记录的时候最早的命令将被从队列中移除

# 下面的时间以微妙微单位,因此1000000代表一分钟。
# 注意制定一个负数将关闭慢日志,而设置为0将强制每个命令都会记录
slowlog-log-slower-than 10000

# 对日志长度没有限制,只是要注意它会消耗内存
# 可以通过 SLOWLOG RESET 回收被慢日志消耗的内存
slowlog-max-len 1024

################################ VM ###############################

### WARNING! Virtual Memory is deprecated in Redis 2.4
### The use of Virtual Memory is strongly discouraged.

# Virtual Memory allows Redis to work with datasets bigger than the actual
# amount of RAM needed to hold the whole dataset in memory.
# In order to do so very used keys are taken in memory while the other keys
# are swapped into a swap file, similarly to what operating systems do
# with memory pages.
#
# To enable VM just set 'vm-enabled' to yes, and set the following three
# VM parameters accordingly to your needs.

vm-enabled no
# vm-enabled yes

# This is the path of the Redis swap file. As you can guess, swap files
# can't be shared by different Redis instances, so make sure to use a swap
# file for every redis process you are running. Redis will complain if the
# swap file is already in use.
#
# The best kind of storage for the Redis swap file (that's accessed at random)
# is a Solid State Disk (SSD).
#
# *** WARNING *** if you are using a shared hosting the default of putting
# the swap file under /tmp is not secure. Create a dir with access granted
# only to Redis user and configure Redis to create the swap file there.
vm-swap-file /tmp/redis.swap

# vm-max-memory configures the VM to use at max the specified amount of
# RAM. Everything that deos not fit will be swapped on disk *if* possible, that
# is, if there is still enough contiguous space in the swap file.
#
# With vm-max-memory 0 the system will swap everything it can. Not a good
# default, just specify the max amount of RAM you can in bytes, but it's
# better to leave some margin. For instance specify an amount of RAM
# that's more or less between 60 and 80% of your free RAM.
vm-max-memory 0

# Redis swap files is split into pages. An object can be saved using multiple
# contiguous pages, but pages can't be shared between different objects.
# So if your page is too big, small objects swapped out on disk will waste
# a lot of space. If you page is too small, there is less space in the swap
# file (assuming you configured the same number of total swap file pages).
#
# If you use a lot of small objects, use a page size of 64 or 32 bytes.
# If you use a lot of big objects, use a bigger page size.
# If unsure, use the default :)
vm-page-size 32

# Number of total memory pages in the swap file.
# Given that the page table (a bitmap of free/used pages) is taken in memory,
# every 8 pages on disk will consume 1 byte of RAM.
#
# The total swap size is vm-page-size * vm-pages
#
# With the default of 32-bytes memory pages and 134217728 pages Redis will
# use a 4 GB swap file, that will use 16 MB of RAM for the page table.
#
# It's better to use the smallest acceptable value for your application,
# but the default is large in order to work in most conditions.
vm-pages 134217728

# Max number of VM I/O threads running at the same time.
# This threads are used to read/write data from/to swap file, since they
# also encode and decode objects from disk to memory or the reverse, a bigger
# number of threads can help with big objects even if they can't help with
# I/O itself as the physical device may not be able to couple with many
# reads/writes operations at the same time.
#
# The special value of 0 turn off threaded I/O and enables the blocking
# Virtual Memory implementation.
vm-max-threads 4

############################### ADVANCED CONFIG ###############################

# 当hash中包含超过指定元素个数并且最大的元素没有超过临界时,
# hash将以一种特殊的编码方式(大大减少内存使用)来存储,这里可以设置这两个临界值
# Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现,
# 这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap,
# 当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。
hash-max-zipmap-entries 512
hash-max-zipmap-value 64

# list数据类型多少节点以下会采用去指针的紧凑存储格式。
# list数据类型节点值大小小于多少字节会采用紧凑存储格式。
list-max-ziplist-entries 512
list-max-ziplist-value 64

# set数据类型内部数据如果全部是数值型,且包含多少节点以下会采用紧凑格式存储。
set-max-intset-entries 512

# zsort数据类型多少节点以下会采用去指针的紧凑存储格式。
# zsort数据类型节点值大小小于多少字节会采用紧凑存储格式。
zset-max-ziplist-entries 128
zset-max-ziplist-value 64

# Redis将在每100毫秒时使用1毫秒的CPU时间来对redis的hash表进行重新hash,可以降低内存的使用
#
# 当你的使用场景中,有非常严格的实时性需要,不能够接受Redis时不时的对请求有2毫秒的延迟的话,把这项配置为no。
#
# 如果没有这么严格的实时性要求,可以设置为yes,以便能够尽可能快的释放内存
activerehashing yes

################################## INCLUDES ###################################

# 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件

# include /path/to/local.conf
# include /path/to/other.conf

而sentinel.conf主要作为监控使用, M-S(master,slaves)集群提供了:

  • master存活检测
  • 集群中M-S服务监控
  • 自动故障转移,M-S角色转换等能力,从一个方面说是提高了redis集群的可用性.

一般情况下,最小M-S单元各有一个maste和slave组成,当master失效后,sentinel可以帮助我们自动将slave提升为master;有了sentinel组件,可以减少系统管理员的人工切换slave的操作过程.

sentinel.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 首先要设置port
port 26379

# 其次要设置sentinel的监控地址
# 第一行配置指示 Sentinel 去监视一个名为 mymaster 的主服务器,
# 这个主服务器的 IP 地址为 127.0.0.1 , 端口号为 6379 ,
# 而将这个主服务器判断为失效至少需要 2 个 Sentinel 同意 (只要同意
# Sentinel 的数量不达标,自动故障迁移就不会执行)。

# 不过要注意, 无论你设置要多少个 Sentinel 同意才能判断一个服务器失效,
# 一个 Sentinel 都需要获得系统中多数(majority) Sentinel 的支持,
# 才能发起一次自动故障迁移, 并预留一个给定的配置纪元 (configuration
# Epoch ,一个配置纪元就是一个新主服务器配置的版本号)。

# 换句话说, 在只有少数(minority) Sentinel 进程正常运作的情况下,
# Sentinel 是不能执行自动故障迁移的。
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1

sentinel monitor resque 192.168.1.3 6380 4
sentinel down-after-milliseconds resque 10000
sentinel failover-timeout resque 180000
sentinel parallel-syncs resque 5

#down-after-milliseconds 选项指定了 Sentinel认为服务器已经断线所需的毫秒数。
#parallel-syncs 选项指定了在执行故障转移时,最多可以有多少个从服务器同时对新的主服务器进行同步, 这个数字越小,完成故障转移所需的时间就越长。

# ref: http://redis.readthedocs.org/en/latest/topic/sentinel.html

最后,你可以运行sudo redis-sentinel /etc/redis/sentinel.conf

Redis-sentinel是Redis实例的监控管理、通知和实例失效备援服务,是Redis集群的管理工具。在一般的分布式中心节点数据库
中,Redis-sentinel的作用是中心节点的工作,监控各个其他节点的工作情况并且进行故障恢复,来提高集群的高可用性。

Redis-sentinel是Redis的作者antirez在今年6月份完成的,因为Redis实例在各个大公司的应用,每个公司都需要一个Redis集群的管理工具,被迫都自己写管理工具来管理Redis集群,antirez考虑到社区的急迫需要(详情),花了几个星期写出了Redis-sentinel。

Redis-sentinel的三大功能: 监测 通知 * 自动故障恢复
首先Redis-sentinel要建立一个监控的master列表,然后针对master列表的每个master获取监控其的sentinels和slaves供以后故障恢复使用

##关于redis监控

  • redis的系统报告可以使用redis-cli info,redis-cli -h localhost -p 6380 monitor
  • 使用redis-benchmark工具,作为性能检测. redis-benchmark -h localhost -p 6379 -c 100 -n 100000
  • 一些web方式的监控工具:

pow for mac

Pow 介绍

Pow 简单的说是一个可以实时快速将rails在mac系统中进行部署测试的插件,你只需要做几个简单设置,就可以通过特定的域名进行访问。

Pow 安装和配置

安装pow

1
$ curl get.pow.cx | sh

卸载pow

1
$ curl get.pow.cx/uninstall.sh | sh

###在rvm环境下的配置
需要在每个app中设置powenv或是powrc

.powenv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# detect `$rvm_path`
if [ -z "${rvm_path:-}" ] && [ -x "${HOME:-}/.rvm/bin/rvm" ]
then rvm_path="${HOME:-}/.rvm"
fi
if [ -z "${rvm_path:-}" ] && [ -x "/usr/local/rvm/bin/rvm" ]
then rvm_path="/usr/local/rvm"
fi

# load environment of current project ruby
if
[ -n "${rvm_path:-}" ] &&
[ -x "${rvm_path:-}/bin/rvm" ] &&
rvm_project_environment=`"${rvm_path:-}/bin/rvm" . do rvm env --path 2>/dev/null` &&
[ -n "${rvm_project_environment:-}" ] &&
[ -s "${rvm_project_environment:-}" ]
then
echo "RVM loading: ${rvm_project_environment:-}"
\. "${rvm_project_environment:-}"
else
echo "RVM project not found at: $PWD"
fi

.powrc
1
2
3
4
if [ -f "$rvm_path/scripts/rvm" ] && [ -f ".rvmrc" ]; then
source "$rvm_path/scripts/rvm"
source ".rvmrc"
fi

关于Rails下的分页数据

#Rails 的分页#
Rails下的分页显示数据的插件有很多,比较常用的是will_paginate,源代码在mislav的github上去git clone一下。

##如何使用will_paginate呢?##
使用起来没有太多复杂的东西,只需要将Post.all替换成如下就可以

Post Controller
1
2
3
4

# :order 作为排序设置
# :per_page 每页的记录
@posts = Post.paginate(:page => params[:page],:order => 'id DESC', :per_page => 20)

然后下面我们就是设置视图了

index.html.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

<%= page_entries_info @posts %>

<%=
# :class => 'pagination',
# :previous_label => nil,
# :next_label => nil,
# :inner_window => 4, # links around the current page
# :outer_window => 1, # links around beginning and end
# :link_separator => ' ', # single space is friendly to spiders and non-graphic browsers
# :param_name => :page,
# :params => nil,
# :page_links => true,
# :container => true

# 具体操作will_paginate / lib / will_paginate / view_helpers.rb 下面则有批注
will_paginate @posts, :previous_label => '上一页', :next_label => '下一页', :container => false
%>

##关于css

http://mislav.uniqpath.com/will_paginate/?page=2 可以去着网站上下载其分页样式,之后将它放到assets/stylesheets下就可以了。

1
2
3
4
5
6
<div class='digg_pagination'>
<div class='pag_info'>
<%= page_entries_info @posts %>
</div>
<%= will_paginate @posts :previous_label => '上一页', :next_label => '下一页',:container => false %>
</div>

-eof-

custom library and define constant at rails 4

#如何设置在rails设置常量

##initializer目录
这个是一个初始化目录,里面的所有脚本顾名思义都是在rails初始化执行的。因此在里面创建的所有文件也都将被执行。

创建config.rb
1
2
3
raw_config=File.read("#{Rail.root}/config/config.yml")#设置yml的文件名和路径
erb_result=ERB.new(raw_config).result
APP_CONFIG=YAML.load(erb_result)[Rails.env]#指定了如何调用常量

设置config.yml

config.yml
1
2
3
4
5
6
7
8
9
defaults: &defaults
redis_server: '127.0.0.1'
redis_port: '6379'

development:
<<: * defaults

production:
<<: *defaults

#创建自己的library
其实要在rails下创建自己的library很简单,只需要在/lib/ 直接进行添加你创建的ruby文件,那如何引用呢?其实也很简单,只需要在自己的contoller下使用require filename.rb就可以了

rails中post

#Form Helper basic#
view中设置其表单,其中form_tag定义提交给谁和用什么方法

Form表单提交给helo
1
2
3
4
5
<%= form_tag("helo",method: 'post') do %>
<%= label_tag(:search, "search for:") %>
<%= text_field_tag(:search) %>
<%= submit_tag("Search") %>
<% end %>

#Controller 如何实现接受#

在接收的方法中使用params[:search]

Controller中抓去post值
1
2
3
def helo
@helo=params[:search]
end

#route将取决安排程序路径使用什么方法传递#

route.rb
1
2
3
4
namespace :admin do
post 'tasks/helo' #使用post方式请求
get 'tasks/say'
end

Model-for-rails(2)

#Migeration#
Migeration是一种可以随时改变数据模式的一种途径。通过使用Ruby DSL,从而摆脱了SQL的编写,从而使得数据库独立。Migeration保存着你历史数据结构,ActiveRecord会通过更新db/schema.rb来同步更新你的数据库结构。

##创建一个标准的Migration##
使用rails g migration MIGRATION_NAME用来创建一个标准的空migration.

  • 如果你的migration名字是’AddXXXToyyy’或是’RemoveXXXToYYY’,那么migration会自动在文档里创建add_column或是remove_column
  • 如果你的migration名字是’CreateXXX’那么他将自动在文档里创建create_table XXX

同样如果你的名字是AddXXXRefToYYY,就会自动添加add_reference :xxx, :yyy, index:true

如果CreateJoinTableNNNN XXX YYY,则会自动添加create_join_table :xxx,:yyy,实际上,他会生成一张表讲带有xxx_id和yyy_id.

另外可以通过{}来限制起最大值和多态性比如$ rails generate migration AddDetailsToProducts price:decimal{5,2} supplier:references{polymorphic}

##使用change方法 ##
以下方法支持change

  • add_column
  • add_index
  • add_reference
  • add_timestamps
  • create_table
  • create_join_table
  • drop_table (must supply a block)
  • drop_join_table (must supply a block)
  • remove_timestamps
  • rename_column
  • rename_index
  • remove_reference
  • rename_table

##回滚migrations##
每个生成的migration都会根据时间自动生成版本号标签,你可以通过rake db:migrate VERSION=20080906120000 来回到所要的版本号,如果你只是要回滚到最后一个版本,则可以rake db:rollback,或是在最后第三个版本,则可以rake db:rollback STEP=3

##REST DB##
REST数据其实很简单,只要执行rake db:rest就可以了

model for rails(1)

#ActiveRecord Models#

我们可以通过rails g的命令来创建一个Model

1
rails g model User name:string email:string

/app/models//app/db/migration中会创建相应的文件

##Active Record Basic##
Active Record是一个ORM的框架

###命名规范###
Model/Class|Table/Schema
———–|————
Post |posts
LineItem |line_items
Deer |deer
Mouse |mice
Person |people

###支持的数据类型####

  • :binary
  • :boolean
  • :date
  • :datetime
  • :decimal
  • :float
  • :integer
  • :primary_key
  • :string
  • :text
  • :time
  • :timestamp

###Schema 模式###
外键 Foreign Keys: tablename_id
主键 Primary Keys: 默认为id

另外还会自动创建两个字段 created_atupdated_at

###create or overriding name conventions ###
通常我们继承了一个ActiveRecord的类就好比创建了一张表。

Product
1
2
class Product < ActiveRecord:Base
end

类名通常就是这个表的表名,但其实我们可以重新定义。

1
2
3
changeProduct < ActiveRecord:Base
self.table_name = "Product"
end

手动添加primary_key

1
set_primary_key "product_id"

###about CRUD###

####create####
Active Record 对象是用hash来呈现的,使用create方法,将数据保存在数据库中

1
user=User.create(name: "Dexter", location: "mars")

而如果使用new方法,则只是实例化,并不保存数据,如果你要保存数据,则是user.save

####read#####
更多的关于read的api,可访问http://api.rubyonrails.org/classes/ActiveRecord/Base.html
下面一些简单的关于read的例子

1
2
3
4
5
6
users=User.all #返回所有的用户信息
user=User.first #返回第一条记录
david=User.find_by_name('David') #返回第一条叫David的记录

#按照条件和时间排序搜索
users = User.where(name: 'David', occupation: 'Code Artist').order('created_at DESC')

####update####
基本和create性质一样

1
2
user=User.find_by_[KEY_NAME]('davis') #KEYNAME所查询的字段名称
user.update(KEYNAME: 'dav') #更新keyname里的值

若你要更新所有的值,那update_all会很有用

1
User.update_all "max_login_attempts = 3, must_change_password = 'true'"

####delete####

1
2
user = User.find_by_name('David')
user.destroy