#721 RedisJSON 体验

2022-01-09

相关阅读:Redis 拓展模块,其中用 RedisJSON 举例编译安装。

简单示例 (GET / SET):

127.0.0.1:6379> json.set abc . 123
OK
127.0.0.1:6379> json.get abc .
"123"
127.0.0.1:6379> json.set xyz . '{"a": 1, "b": true, "c": [{"name": "foo"}, {"name": "bar"}]}'
OK
json.get xyz .c[0]
"{\"name\":\"foo\"}"
127.0.0.1:6379> json.set xyz .a 2
OK
127.0.0.1:6379> json.get xyz .c[0].name
"\"foo\""
127.0.0.1:6379> json.set xyz .c[0].name '"loong"'
OK
127.0.0.1:6379> json.get xyz .a .c[0].name
"{\".c[0].name\":\"loong\",\".a\":2}"

Json 路径语法

现在还没有相关行业标准,RedisJSON 自己实现了一套(v1), 后来参考 JSONPath 语法又重新实现了一遍 (v2)。
至于 v1 和 v2 有什么区分,就不用深究了。

大致知道这样可以就行了:

.store.book[0].title
// 相当于 `V['store']['book'][0]['title']`

拓展命令

  1. JSON.ARRAPPEND arrappend
  2. JSON.ARRINDEX arrindex
  3. JSON.ARRINSERT arrinsert
  4. JSON.ARRLEN arrlen
  5. JSON.ARRPOP arrpop
  6. JSON.ARRTRIM arrtrim
  7. JSON.CLEAR clear
  8. JSON.DEBUG debug
  9. JSON.DEL delete
  10. JSON.GET get / jsonget
  11. JSON.MGET mget / jsonmget
  12. JSON.NUMINCRBY numincrby
  13. JSON.NUMMULTBY nummultby img
  14. JSON.OBJKEYS objkeys
  15. JSON.OBJLEN objlen
  16. JSON.RESP resp
  17. JSON.SET set / jsonset
  18. JSON.STRAPPEND strappend
  19. JSON.STRLEN strlen
  20. JSON.TOGGLE toggle
  21. JSON.TYPE type

Python 库还有以下两个方法:

  1. set_file(name, path, file_name, nx=False, xx=False, decode_keys=False)
    return self.set(name, path, file_content, nx=nx, xx=xx, decode_keys=decode_keys)
    
    1. set_path(json_path, root_folder, nx=False, xx=False, decode_keys=False)
    遍历 root_folder 得到 file_path, file_name (file_path.split('.', 1)[0])
    然后调用 set_file(file_name, json_path, file_path, nx=nx, xx=xx, decode_keys=decode_keys)

使用(Python)

Python 最知名的 Redis 客户端库 redis-py 已经支持 RedisJSON 拓展指令。

import redis
from redis.commands.json import JSON

r = redis.Redis(host='localhost', port=6379, db=0)
jr = JSON(r)

jr.set('foo', '.', {"a": 1, "b": True, "c": [{"name": "foo"}, {"name": "bar"}]})

jr.numincrby('foo', 'a', 1)

jr.toggle('foo', '.b') # only works for booleans

jr.arrappend('foo', '.c', {"name": "air"})

print(jr.get('foo', '.'))
# {'a': 2, 'b': False, 'c': [{'name': 'foo'}, {'name': 'bar'}, {'name': 'air'}]}

print(jr.get('foo', '.c[-1].name'))
# air

就缺搜索了,如果加上 RediSearch,就完美了。
PS: RediSearch 的新版本已经优化了对 JSON 的支持。

参考资料与拓展阅读

#720 Redis 拓展模块

2022-01-09

Redis 官方其实还提供了以下拓展:

PS: 还有更多第三方拓展,参考 https://redis.io/modules

关于授权协议

Redis 是 BSD 协议,Redis 拓展模块是 AGPL 协议。
2018 年 8 月,为了防止云服务厂商的利益侵害,Redis 拓展模块授权协议切换到 Apache v2.0 modified with Commons Clause (官方声明)。其中 Common Clause 就是限制提供商业的 Reids 服务。
2019 年 2 月,Redis 拓展模块授权协议再次切换,改成 Redis Source Available License (RSAL),(官方声明)。因为认为当前协议不够明确,容易让人产生误解,而且对 Redis 公司的权益保障不到位。

这个协议对普通用户(个人或企业)没有限制,只是限制了直接利用 Redis 服务赚钱的云厂商。我觉得这是开发者的合理诉求,没有什么值得质疑的。

模块的安装

img

如果只是要体验一下,不想编译,可以去 https://redis.com/redis-enterprise-software/download-center/modules/ 下载试用。

  1. 下载模块源代码,然后编译,生成动态链接库 xxx.so
  2. 修改 Redis 配置文件 loadmodule xxx.so,然后重启 Redis 服务
    PS: 也可以在启动时使用 --loadmodule 参数动态加载模块。

比如 ReJSON:

wget https://github.com/RedisJSON/RedisJSON/archive/refs/tags/v2.0.6.zip -O redisjson-v2.0.6.zip
unzip redisjson-v2.0.6.zip
cd RedisJSON-2.0.6/

# 安装需要用到官网没有提到的 libclang.so
# From: bindgen-0.59.2/src/lib.rs
sudo apt install libclang-dev

cargo build --release
cargo test --features test
# 需要先安装 Rust (请参考其他资料)
# 我了解到的其他模块大多数是 C 写的,RedisJSON 比较特殊,用 Rust 写的

redis-server --loadmodule target/release/librejson.so

相关文章:RedisJSON 体验

#719 西安一码通的“优化”

2022-01-07

西安一码通半个月内两次宕机,值此西安疫情突发之时,可是严重的安全故障。相关负责人(西安大数据资源管理局局长)已经停职检查。

为确保系统运行更高效,他们将一张图片从1MB压缩到500KB,再从500KB优化到100KB。这样的工作看似简单,却蕴含着高技术含量,他们连续两天两夜守在电脑前,终于攻下难关。

#718 对个人职业生涯的一点展望

2022-01-02

维持之前的设定,走技术专家的路线。

  1. 能处理工作中的难点问题,需要对业务有全局性的认识
  2. 对技术有深刻的理解,尤其是基础技术一定要扎实
  3. 方案设计能力:1. 对产品更多思考 2. 架构能力 3. 编码规范 4. 了解产品测试和运维
  4. 良好的沟通能力,培养个人影响力

第一点,今年会得到改进。
第二点,需要更长时间周期的投入才能见效。
第三点,比较泛,需要更多思考。
第四点,可能是最难的。我不知道该怎么做。

#717 对过去工作的一点总结和反思

2022-01-01

新的一年,岁数又会 +1,在这个一年开始的时候,对过去做个总结,对将来做个展望。

对过去的反思

  1. 工作这么多年,还是缺少拿得出手的项目经历,不足以支撑我对自己的定位或者目标
    工作年限越长,这个问题就会更加突出
    新的一年需要思考思考这个问题
  2. 技术深度不够
  3. 主力开发语言 Python 应该更加深入,完成 CPython 源码阅读
  4. PHP, Node, Golang 需要加强,能够熟练掌握 (主要是软件生态),使之达到新的线上业务开发的程度
  5. 前端也一样
  6. 知识结构缺乏深入的整理
  7. 比如软件设计的一些思考
  8. 应该对产品方面更加用心一些 img
    现在就是对技术方面过于感兴趣而忽略了产品
    这个问题对于工作来说比较突出,新的一年一定要注意这个问题

今年的计划

前提:工作习惯养成:1. 计划,2. 重要的事情优先完成,3. 不加班 (上班时间完成工作)

如果按平均每天 2h 来计划,全年有 730h。

  1. img 对当前公司业务的梳理, 需要有计划有步骤的推进 (这一项可以在工作中完成)
  2. img 完成 Golang 的学习目标, 达到熟练的程度(第一季度) (60h, 按一个月算)
  3. img CPython 源码阅读 (120h, 按两个月算)
  4. img 英语和数学
    真是 年年列计划, 年年没时间
    英语达到六级词汇, 能不借助工具流利阅读英语资料 (180h, 按每天半小时算)
    数学复习到高等数学, 不用达到应试的程度, 了解相关概念就行 (60h, 按一个月算)
  5. img 计算机网络 (50h)
  6. img Markjour 文章更新速度放缓, 每周一篇就够了 (104h, 按每周两个小时算)
  7. img 对以往知识的总结 (104h,按每周两个小时算)
  8. img 剩下的时间 (52h) 差不多每周 1h, 用来记入其他学习任务。

个人项目的开发不占用这里的学习时间,另外从周末时间里面挤。

可选个人项目

  1. 短网址
  2. 记账
  3. Home Assistant 方向
    我预测未来几年,智能家居会变的很流行
    OpenWrt + Home Assistant 是一个很好的方案
  4. 通用管理后台
  5. 商城
  6. 重构 markjour

#716 IPv6 地址

2021-12-30
$ ip -c -6 addr show dev wlp6s0
3: wlp6s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    inet6 2409:8a4d:c81:c140::5/128 scope global dynamic noprefixroute
       valid_lft 226977sec preferred_lft 140577sec
    inet6 2409:8a4d:c81:c140:ca67:f46:7f29:1dad/64 scope global temporary dynamic
       valid_lft 376sec preferred_lft 376sec
    inet6 2409:8a4d:c81:c140:fcf0:3456:fac4:3b63/64 scope global dynamic mngtmpaddr noprefixroute
       valid_lft 376sec preferred_lft 376sec
    inet6 fe80::56f8:128b:b513:e571/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
# ipconfig /all
# ipconfig

无线局域网适配器 WLAN:

   连接特定的 DNS 后缀 . . . . . . . :
   IPv6 地址 . . . . . . . . . . . . : 2409:8a4d:c81:c140::6
   IPv6 地址 . . . . . . . . . . . . : 2409:8a4d:c81:c140:68cd:b350:9fe8:9feb
   临时 IPv6 地址. . . . . . . . . . : 2409:8a4d:c81:c140:757f:88b3:b455:5882
   本地链接 IPv6 地址. . . . . . . . : fe80::68cd:b350:9fe8:9feb%5
   IPv4 地址 . . . . . . . . . . . . : 192.168.1.7
   子网掩码  . . . . . . . . . . . . : 255.255.255.0
   默认网关. . . . . . . . . . . . . : fe80::1%5
                                       192.168.1.1

   DHCP 服务器 . . . . . . . . . . . : 192.168.1.1
   DNS 服务器  . . . . . . . . . . . : 2409:804c:2000:1::1
                                       2409:804c:2000:2::1
                                       192.168.1.1

一、地址格式

IPv4 4 字节, 一般用四个十进制的数字表示,xxx.xxx.xxx.xxx 形式,每一段的范围是 0~255。
IPv6 16 字节,一般用 32 个十六进制数表示,每四个一组,共八组,xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx 形式,每一段的范围是 0000~FFFF。

缩写

  1. 高位的 0 可以省略,比如 0001 就可以写成 1
  2. 全 0 段可以省略,用分号表示,比如 fe80::, :: (全 0), 又比如上面的 2409:8a4d:c81:c140::5
    但是, 只能缩写一次,比如 A:B:0:0:C:D:0:0 不能写成 A:B::C:D::, 只能缩写成 A:B::C:D:0:0A:B:0:0:C:D::

百分号

如果一台机器有多张网卡,都有一个 fe80 的链路地址,操作系统无法区分一个包该走哪张网卡出。

在 IPv4 中,不同网卡一般配置了不同子网,比如 172.16.31.0/24, 172.168.32.0/24

但是 IPv6 的分配可以自己生成(无状态地址自动配置),大家都在 fe80 段。

百分号后面附加的是 zone index,这个数据是操作系统解释的。Windows 会采用接口号(整型数),而 Linux 习惯端口名称,比如 eth0, enp7s0。
PS: 推荐阅读: 网卡名称的变迁(ethX -> enpXsY)

  • windows: netsh interface ipv6 show address
  • linux: ifconfig

注意:用在 URL 中时,这个百分号应该转义成 %25

二、前缀

IPv4 有分区的概念,一开始叫做分类网络,ABCDE 五类。后来又有无类网络 (Classless Inter-Domain Routing, CIDR),取任意长度作前缀,比如 172.16.0.0/12 以 1010 1100 0001 做前缀。

IPv6 也有分区的概念,和 CIDR 一样,可以取任意长度作前缀。
比如 fe80::/10 就是以 1111 1110 10 做前缀。

移动网络给我分配的是 /64 段,听说有地方能拿到更短前缀(V2EX, 2020/07, 电信 IPv6 大家还能拿到/56 么)。

如果拿到更短前缀,就可以自己在家划分子网了。根据现在的实践(SLAAC),一个网络最少需要留 64 位,如果正好分的是 64 位前缀,那么就不能采用 SLAAC 方案了,只能走 DHCP。

无状态自动配置

  1. RS, Router Solicitation
  2. RA, Router Advertisement 路由器告诉机器 IPv6 前缀
  3. NS, Neighbor Solicitation 机器广播自己将要采用某一个 IPv6

#715 转载:免费的编程书籍

2021-12-30

语言无关

版本控制

编程艺术

编辑器

编译原理

操作系统

程序员杂谈

大数据

分布式系统

管理和监控

函数式概念

计算机图形学

其它

软件开发方法

设计模式

数据库

项目相关

在线教育

正则表达式

智能系统

IDE

Web

WEB 服务器

语言相关

Android

Assembly

AWK

C

C Sharp

C++

CoffeeScript

Dart

Elasticsearch

Elixir

Erlang

Fortran

Golang

Groovy

Haskell

HTML / CSS

iOS

Java

JavaScript

AngularJS

:information_source: See also … Angular

Backbone.js

D3.js

Electron.js

ExtJS

impress.js

jQuery

Node.js

React.js

Vue.js

Zepto.js

LaTeX

LISP

Lua

Markdown

MySQL

NoSQL

Perl

PHP

Laravel

Symfony

PostgreSQL

Python

Django

R

reStructuredText

Ruby

Rust

Scala

Scheme

Scratch

Shell

Swift

TypeScript

Angular

:information_source: See also … AngularJS

Deno

VBA (Microsoft Visual Basic Applications)

Vim

Visual Prolog

#714 VPN 重新配置流程

2021-12-27

处于安全原因,每隔几个月重新更换一次 OpenVPN 的配置文件,以防被攻击。运维讲配置文件加密打包分发给每个人,然后大家将其覆盖到现在的目录中。

我是 Linux 环境(Ubuntu, 准备切入 Fedora),这里我记录一下更新流程,下次务必 1 分钟之内切换完成。

  1. 通过密码解压配置文件
ls ~/Documents/Mine/config20211213/
# ca.crt  client.crt  client.key  client.ovpn
  1. 备份之前的证书文件
cd /etc/openvpn
sudo mkdir backup20211227
sudo mv ca.crt client.crt client.key client.ovpn backup20211227/
sudo cp client.conf backup20211227/
  1. 采用新的证书文件
sudo mv ~/Documents/Mine/config20211213/{ca.crt,client.crt,client.key,client.ovpn} /etc/openvpn
sudo chmod 400 /etc/openvpn/{ca.crt,client.crt,client.key,client.ovpn}
  1. 通过和旧的 client.ovpn 文件比对,讲需要修改的地方同步到 /etc/openvpn/client.conf
sudo diff client.ovpn backup20211227/client.ovpn
sudo vim /etc/openvpn/client.conf
# w! sudo tee %
  1. 重新启动 OpenVPN,试一下是否配置成功
sudo systemctl restart openvpn@client

#713 转载:正则表达式历史

2021-12-19

正则表达式在我们日常的软件开发过程中被广泛使用,例如编写 Nginx 配置文件、在 Linux 与 macOS 下查找文件,然而不同软件不同操作系统对于正则的应用有着不一样的行为,主要原因是正则表达式演进过程中,出现 POSIXPCRE 派系之分。