0%

文章字数:623,阅读全文大约需要2分钟

openssl是目前最流行的SSL密码库工具,提供了一组通用、健壮、完备的工具。

构成

  • 密码算法库
  • 秘钥和证书封装管理
  • SSL通讯API接口

秘钥操作

  1. 生成不加密的RSA私钥
1
openssl genrsa -out rsa_private.key 2048
  1. 使用不加密的RSA私钥生成公钥
1
openssl rsa -in rsa_private.key -pubout -out rsa_public.key
  1. 生成加密RSA私钥(使用AES256加密)
1
openssl genrsa -aes256 -passout pass:123456 -out rsa_aes_private.key 2048
  1. 使用加密的RSA私钥生成公钥
1
openssl rsa -in rsa_aes_private.key -passin pass:123456 -pubout -out rsa_public.key

转换相关

  1. 加密私钥转非加密
1
openssl rsa -in rsa_aes_private.key -passin pass:123456 -out rsa_private.key
  1. 非加密私钥转加密
1
openssl rsa -in rsa_private.key -aes256 -passout pass:123456 -out rsa_aes_private.key
  1. 私钥PEMDER
  • -inform-outform参数制定输入输出格式,由derpem格式同理
1
openssl rsa -in rsa_private.key -outform der-out rsa_aes_private.der
  1. 私钥PKCS1PKCS8(加密算法填充模式)
1
openssl pkcs8 -topk8 -in rsa_private.key -passout pass:123456 -out pkcs8_private.key
  1. 查看私钥明细
1
openssl rsa -in rsa_private.key -noout -text

生成自签证书

  1. 生成RSA私钥和自签名证书
1
openssl req -newkey rsa:2048 -nodes -keyout rsa_private.key -x509 -days 365 -out cert.crt
  • req证书请求的子命令
  • newkey rsa:2048 -keyout private_key.pem生成私钥(PKCS8格式)
  • -nodes秘钥不加密,无此参数则提示输入密码
  • -x509输出证书
  • -days365有效期
  • subj证书拥有者信息,如果没有此参数,也可以根据提示输入
  1. 使用已有RSA私钥生成自签名证书
1
openssl req -new -x509 -days 365 -key rsa_private.key -out cert.crt
  • -new生成证书请求
  • -x509直接输出证书
  • -key指定私钥

生成签名请求文件及CA签名

  1. 生成RSA秘钥
1
openssl genrsa -aes256 -passout pass:123456 -out server.key 2048
  1. 生成CSR签名请求(把秘钥生成向CA发起签发证书请求的文件)
1
openssl req -new -key server.key -out server.csr -subj "/C=CN/ST=FJ/L=XM/O=COL/CN=127.0.0.1"
  1. 使用CA证书及CA秘钥,对请求签发证书进行签发,生成x509证书
1
openssl x509 -req -days 3650 -in server.csr -CA ca.cert -CAkey ca.key -passin pass:123456 -CAcreateserial -out server.crt

文章字数:532,阅读全文大约需要2分钟

OSI开放系统互联(open system interconnection)是由国际标准化组织(ISO)指定的七层计算机互联模型。TCP/IP则是简化版的OSI,TCP/IP是四层模型,并且淘汰了OSI,被大规模使用。

OSI参考模型

位置 模型层名 作用 常见协议
主机 应用层 访问网络服务的端口,应用程序协议 HTTP、FTP、SMTP、TELNET、DNS
主机 表示层 数据格式转换、语义关联 LPP(轻量级表示协议)、NBSSN NetBIOS(会话服务协议)、XDP(外部数据表示协议)
主机 会话层 建立端连接,提供访问验证会话管理 SSL(安全套接字层协议)、TLS(传输层安全协议)、RPC(远程过程调用协议)、DAP(目录访问协议)、LDAP(轻量级目录访问协议)
主机 传输层 端到端基础通讯 TCP、UDP
网络 网络层 节点,子网控制。逻辑编址、分组传输、路由选择 ipv4、ipv6、icmp(报文控制协议)ping发送的就是icmp
网络 链路层 物理寻址,将比特流建立逻辑传输路线
网络 物理层 原始比特传输 IEEE 802.2

TCP/IP

模型层名 作用
应用层 用户进程
运输层 TCP、UDP
网络层 ICMP、IP、IGMP
链路层 ARP、硬件接口、RARP

文章字数:59,阅读全文大约需要1分钟

基本使用

1
2
3
4
5
6
-- 从data表中模糊查询data_content(json)中的code属性
select * from data where data_content::json ->> 'code' like '%123%'

-- ::json转成json
-- ->>接收字符串
-- -->>'code' 字符串类型的code字段

操作符

1
2
3
-> / ->> 取一层
#> / #>> 可取多层: jsonContent::json #>>{a,b} //bbbb
{"a":"{'b':'bbbb'}"}

文章字数:185,阅读全文大约需要1分钟

相同点

线程和进程都是并发操作,多个代码块并行(几乎)操作

不同

进程是操作系统级别的,等于打开多个程序
线程是进程下又开辟的多个并行代码

线程开销小,但是python的线程是基于解释器的,解释器有个全局锁。实际上代码还是串行执行的。
进程开销大但是是并行处理,能够利用多核处理器的优势。
线程在io密集时可以使用,计算密集的状态下不仅并行和单线程时间一样,还要多算线程切换的消耗。计算密集的情况下还是使用多进程。


文章字数:120,阅读全文大约需要1分钟

keys命令是用于查找所有符合要求的key,但是redis是单线程操作,单个命令占用时间太长会降低效率。scan命令是通过游标的方式逐个返回匹配的对象,可以提交keys命令

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
public void scan(String pattern, Consumer<byte[]> consumer) {
this.stringRedisTemplate.execute((RedisConnection connection) -> {
try (Cursor<byte[]> cursor =
connection.scan(ScanOptions.scanOptions().count(Long.MAX_VALUE).match(pattern).build())) {
cursor.forEachRemaining(consumer);
return null;
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
});
}

/**
* 获取符合条件的key
*
* @param pattern 表达式
* @return
*/
public List<String> keys(String pattern) {
List<String> keys = new ArrayList<>();
this.scan(pattern, item -> {
// 符合条件的key
String key = new String(item, StandardCharsets.UTF_8);
keys.add(key);
});
return keys;
}

文章字数:987,阅读全文大约需要3分钟

指定字符编码 # -*- coding: utf-8 -*-

输入输出

  1. 输入 name = input()
  2. 输出 print('1+1=',1+1)

循环

  1. if

    1
    2
    3
    4
    5
    6
    7
    8
    # :后面的缩进(4个空格)都是代码块
    a = 100
    if a >= 0:
    print(a)
    elif a = 0:
    print(0)
    else:
    print(-a)
  2. for

1
2
3
4
5
6
names = [1,2,3,5]
for name in names
print(name)

for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:
sum = sum + x
  1. while
1
2
3
4
n = 0
while n > 0:
sum = sum + n
n = n - 2
  1. 退出
  • break退出所有循环
  • continue退出本次循环

数据类型

变量不用声明,直接用 a=123

  1. 整数 1
  2. 浮点数 1.23
  3. 字符串
  • ' '
  • " "
  • r' ' 内部不转义
  • ''' sss ''' 多行文本
  1. 布尔值 True False使用and or not运算
  2. 空值 None

集合

  1. list
  • 声明 classmates = ['Michael', 'Bob', 'Tracy']
  • 长度 len(classmates)
  • 正向下标取值classmates[0] 第一个
  • 负向下标取值classmates[-1] 最后一个
  • 追加到末尾classmates.append('Adam')
  • 插入指定位置classmates.insert(1, 'Jack')
  • 删除末尾classmates.pop()
  • 删除指定位置classmates.pop(1)
  • 切片获取 r[0:3]从0取到3,0可省略
  1. tuple不可变集合
  • 声明classmates = ('Michael', 'Bob', 'Tracy')
  • 声明空的tuplet = ()
  • 声明一个:t = (1,)为了和数值型区分,后面加,
  1. dict:键值对
  • 声明 d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
  • 取出d['Michael']或者d.get('Michael')
  • 判断是否key在字典中'Thomas' in d返回布尔
  • 删除d.pop('Bob')
  1. set无序集合
  • 声明s = set([1, 2, 3])
  • 添加s.add(4)
  • 删除remove(key)
  • 交集并集s1 & s2 s1 | s2

函数

  1. 函数赋值a = abs指向abs(),然后a()

  2. 声明

    1
    2
    3
    4
    5
    def my_fun(x):
    if x >= 0:
    return x
    # 返回None
    return
  3. 空函数

1
2
3
def nop():
# 占位,也可用于循环的占位
pass
  1. 返回多值
1
2
3
4
5
def xx():
return 1,2

# 其实是个cuple
x, y = xx()

对象

  • 对象迭代
1
2
3
d = {'a': 1, 'b': 2, 'c': 3}
for key in d:
print(key)
  • 声明
1
2
3
4
5
# object代表父类
class Cl(object):
# self代表本身,永远是第一个
def __init__(self, name)
self.name = nema

c = Cl('123')

  • 指定对象可以使用的属性
    __slots__ = ('name', 'age')仅当前类有用,子类无作用

  • toString 写__str__方法

  • 类作用于len():写__len__方法

  • 对象可以被遍历

1
2
3
4
5
def __iter__(self):
return self
def __next__(self):
# 迭代器每次都会调用这个方法,接收返回
# raise StopIteration()退出(抛出异常)
  • get set
1
2
3
4
5
6
@property
def score(self):
return self._score

@score.setter
def score(self, value):

s.score:等于s.get_sore()
s.score = 60:s.set_sore(60)

函数式编程

  1. map/reduce
    r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])f是函数,接收一个值,map会把list的参数一个个传进去

reduce(f, [x1, x2, x3, x4])f是函数,接收两个值第一个是上一个的返回值,第二个是list的元素

  1. filter filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])返回满足条件的集合

  2. sorted([36, 5, -12, 9, -21])排序

  3. 函数可以返回函数

  4. 获取函数变量的方法名fun.__name__

模块

  • 定义abc.py就是abc模块
  • 引入import abc

常用方法

  1. range(5)生成 0-5 的有序集合
  2. list(range(5))展示list
  3. b = a.replace('a', 'A')字符替换
  4. help(abs)查看函数说明
  5. abs(100)取整
  6. int()转换类型
  7. max(1,2,3,)取最大值
  8. hex()十进制转16
  9. now()现在的时间
  10. type('abc')获取类型,也可以传对象

io

  1. 打开文件
  • f = open('/Users/michael/test.txt', 'r')r只读
  • f = open('/Users/michael/gbk.txt', 'r', encoding='gbk')指定字符编码
  • f = open('/Users/michael/gbk.txt', 'r', encoding='gbk', errors='ignore')字符编码错误忽略
  1. 读取f.read()

  2. 关闭f.close()

  3. 安全打开(有异常也关闭)

1
2
3
4
5
try:
f = open('/Users/michael/test.txt', 'r')
finally:
if f:
f.close()
  1. 自动关闭

    1
    2
    with open('/path/to/file', 'r') as f:
    print(f.read())
  2. 其它读

  • read(size)读取固定大小
  • readline()读取一行
  • readlines()读一行,返回所有内容的list
  • 覆盖w追加a
  • f.write('Hello, world!')
  1. StringIO,BytesIO
  • f = StringIO('Hello!\nHi!\nGoodbye!')string转成io
  • f = BytesIO()然后写f.write('中文'.encode('utf-8'))
    f.getvalue() : b'\xe4\xb8\xad\xe6\x96\x87'二进制数据
  1. 文件目录
    import os
  • os.rename('test.txt', 'test.py')重命名
  • os.remove('test.py')删除
  • os.mkdir('/Users/michael/testdir')创建目录
  • os.rmdir('/Users/michael/testdir')删除目录
  1. 对象写入
  • 转换成bytes:
    1
    2
    3
    4
    5
    import pickle
    f = open('dump.txt', 'wb')
    d = dict(name='Bob', age=20, score=88)
    pickle.dumps(d)
    f.close()
  • 转json
    1
    2
    3
    4
    5
    import json
    d = dict(name='Bob', age=20, score=88)
    json.dumps(d)
    # 解析json
    json.loads(json_str)

多线程

  1. 支持多进程
  2. 多线程
    1
    2
    3
    4
    5
    6
    def loop():
    ...

    t = threading.Thread(target=loop, name='LoopThread')
    t.start()
    t.join()

文章字数:59,阅读全文大约需要1分钟

使用redisTemplate来操作redis,而redisTemplate并不会自动释放连接。可以使用redis.maxIdle=1000增加连接池大小,但是治标不治本。

方法

使用try...finally包裹操作,在finally里
RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
断开连接


文章字数:1671,阅读全文大约需要6分钟

获取

1
2
3
4
5
6
7
8
9
10
RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
RedisConnection conn = null;
Map redisInfo = null;
try {
conn = RedisConnectionUtils.getConnection(factory);
redisInfo = conn.info();
} finally {
RedisConnectionUtils.releaseConnection(conn, factory);
}
return redisInfo;

含义

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
redis> INFO
# Server
# Redis服务器版本
redis_version:999.999.999
redis_git_sha1:3c968ff0
redis_git_dirty:0
redis_build_id:51089de051945df4
redis_mode:standalone
# Redis 服务器的宿主操作系统
os:Linux 4.8.0-1-amd64 x86_64
# 架构(32 或 64 位)
arch_bits:64
# Redis 所使用的事件处理机制
multiplexing_api:epoll
atomicvar_api:atomic-builtin
# 编译 Redis 时所使用的 GCC 版本
gcc_version:6.3.0
# 服务器进程的 PID
process_id:9941
# Redis 服务器的随机标识符(用于 Sentinel 和集群)
run_id:b770a8af038963f3d1b55358c2e376d0b5e00182
# TCP/IP 监听端口
tcp_port:6379
# 自 Redis 服务器启动以来,经过的秒数
uptime_in_seconds:1028993
# 自 Redis 服务器启动以来,经过的天数
uptime_in_days:11
hz:10
# 以分钟为单位进行自增的时钟,用于 LRU 管理
lru_clock:10750613
executable:/usr/local/bin/redis-server
config_file:

# Clients
# 已连接客户端的数量(不包括通过从属服务器连接的客户端)
connected_clients:4
# 当前连接的客户端当中,最长的输出列表
client_longest_output_list:0
# 当前连接的客户端当中,最大输入缓存
client_biggest_input_buf:0
# 正在等待阻塞命令(BLPOP、BRPOP、BRPOPLPUSH)的客户端的数量
blocked_clients:0

# Memory
# 由 Redis 分配器分配的内存总量,以字节(byte)为单位
used_memory:154272800
# 以人类可读的格式返回 Redis 分配的内存总量
used_memory_human:147.13M
# 从操作系统的角度,返回 Redis 已分配的内存总量(俗称常驻集大小)。这个值和 top 、 ps等命令的输出一致。
used_memory_rss:160612352
# 以人类可读的格式返回
used_memory_rss_human:153.17M
# Redis 的内存消耗峰值(以字节为单位)
used_memory_peak:154319968
# 以人类可读的格式返回 Redis 的内存消耗峰值
used_memory_peak_human:147.17M
# 使用内存达到峰值内存的百分比,即(used_memory/ used_memory_peak) *100%
used_memory_peak_perc:99.97%
# Redis为了维护数据集的内部机制所需的内存开销,包括所有客户端输出缓冲区、查询缓冲区、AOF重写缓冲区和主从复制的backlog
used_memory_overhead:44082040
# Redis服务器启动时消耗的内存
used_memory_startup:510704
# 数据占用的内存大小,即used_memory-used_memory_overhead
used_memory_dataset:110190760
# 数据占用的内存大小的百分比,100%*(used_memory_dataset/(used_memory-used_memory_startup))
used_memory_dataset_perc:71.66%
allocator_allocated:154256264
allocator_active:154550272
allocator_resident:159731712
# 整个系统内存
total_system_memory:1044770816
# 以更直观的格式显示整个系统内存
total_system_memory_human:996.37M
# Lua脚本存储占用的内存
used_memory_lua:37888
# 以更直观的格式显示Lua脚本存储占用的内存
used_memory_lua_human:37.00K
# Redis实例的最大内存配置
maxmemory:0
# 以更直观的格式显示Redis实例的最大内存配置
maxmemory_human:0B
# 当达到maxmemory时的淘汰策略
maxmemory_policy:noeviction
allocator_frag_ratio:1.00
allocator_frag_bytes:294008
allocator_rss_ratio:1.03
allocator_rss_bytes:5181440
rss_overhead_ratio:1.01
rss_overhead_bytes:880640
# 碎片率,used_memory_rss/ used_memory
mem_fragmentation_ratio:1.04
mem_fragmentation_bytes:6422528
# 在编译时指定的, Redis 所使用的内存分配器。可以是 libc 、 jemalloc 或者 tcmalloc 。
mem_allocator:jemalloc-4.0.3
active_defrag_running:0
lazyfree_pending_objects:0

# Persistence,RDB 持久化和 AOF 持久化有关信息
# 一个标志值,记录了服务器是否正在载入持久化文件
loading:0
# 距离最近一次成功创建持久化文件之后,经过了多少秒
rdb_changes_since_last_save:3813014
# 一个标志值,记录了服务器是否正在创建 RDB 文件
rdb_bgsave_in_progress:0
# 最近一次成功创建 RDB 文件的 UNIX 时间戳
rdb_last_save_time:1570002708
# 一个标志值,记录了最近一次创建 RDB 文件的结果是成功还是失败
rdb_last_bgsave_status:ok
# 记录了最近一次创建 RDB 文件耗费的秒数
rdb_last_bgsave_time_sec:-1
# 如果服务器正在创建 RDB 文件,那么这个域记录的就是当前的创建操作已经耗费的秒数
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:0
# 一个标志值,记录了 AOF 是否处于打开状态
aof_enabled:0
# 一个标志值,记录了服务器是否正在创建 AOF 文件
aof_rewrite_in_progress:0
# 一个标志值,记录了在 RDB 文件创建完毕之后,是否需要执行预约的 AOF 重写操作
aof_rewrite_scheduled:0
# 最近一次创建 AOF 文件耗费的时长
aof_last_rewrite_time_sec:-1
# 如果服务器正在创建 AOF 文件,那么这个域记录的就是当前的创建操作已经耗费的秒数
aof_current_rewrite_time_sec:-1
# 一个标志值,记录了最近一次创建 AOF 文件的结果是成功还是失败
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:0

# Stats,一般统计信息
# 服务器已接受的连接请求数量
total_connections_received:96
# 服务器已执行的命令数量
total_commands_processed:8700000
# 服务器每秒钟执行的命令数量
instantaneous_ops_per_sec:11
total_net_input_bytes:710523330
total_net_output_bytes:109073206
instantaneous_input_kbps:1.04
instantaneous_output_kbps:0.32
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
# 因为过期而被自动删除的数据库键数量
expired_keys:13569
expired_stale_perc:0.00
expired_time_cap_reached_count:0
# 因为最大内存容量限制而被驱逐(evict)的键数量
evicted_keys:0
# 查找数据库键成功的次数
keyspace_hits:1911035
# 查找数据库键失败的次数
keyspace_misses:749427
# 目前被订阅的频道数量
pubsub_channels:0
# 目前被订阅的模式数量
pubsub_patterns:0
# 最近一次 fork() 操作耗费的毫秒数
latest_fork_usec:0
migrate_cached_sockets:0
slave_expires_tracked_keys:0
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0

# Replication,主/从复制信息
# 服务器角色
role:master
# 已连接的从服务器数量
connected_slaves:0
master_replid:33f9e49948d61df7fa02e315ecff02bbc3b2c9aa
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

# CPU
used_cpu_sys:925.48
used_cpu_user:3467.41
used_cpu_sys_children:0.00
used_cpu_user_children:0.00

# Cluster
cluster_enabled:0

# Keyspace
db0:keys=876234,expires=3,avg_ttl=204565882

注解摘自原文

文章字数:93,阅读全文大约需要1分钟

线上需要禁止或者重命名

  1. keys xxx模糊查询符合要求的键,大数据量的情况会导致CPU飙升,redis锁住。
  2. flushAll清空redis所有数据,不会执行失败
  3. flushdb删除Redis中当前数据库的所有记录,不会失败
  4. config修改配置

禁用命令

1
2
rename-command KEYS " "
rename-command FLUSHALL ""

重命名

1
rename-command FLUSHALL "xxxxxxxxxxxxx"

文章字数:590,阅读全文大约需要2分钟

  1. 完全基于内存,读写速度非常快
  2. 数据结构采用哈希表的形式,操作时间复杂度O(1);(有序列表内的数据存储用到了跳表)
  3. 数据结构简单,所以对于数据的操作也简单
  4. 单线程,避免上下文切换以及锁的问题
  5. 多路I/O复用模型,非阻塞IO
  6. 改造了VM机制,对于系统的调用更快

多路 I/O 复用模型

多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。

  1. 多路:多个网络连接请求
  2. 复用:复用一个线程去处理

单线程

  1. 官方的解释是cpu不是redis的瓶颈,机器的内存和网络带宽才更可能是。所以采用更简单的单线程

  2. 这里的单线程只是处理网络请求时是单线程

  3. 为了有效利用多核cpu,可以在一个服务器上部署多个redis,采用 主-从\主-主 形式。

多线程

6.0版本之后增加了worker线程的子线程,用于处理命令的io操作,worker专注于命令处理。每个命令开一个新的子线程处理结束和返回结果的io